r23055: Rewrite messages.c to use auto-generated marshalling in the tdb. I'm
[tprouty/samba.git] / source / rpc_server / srv_srvsvc_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1997,
5  *  Copyright (C) Jeremy Allison               2001.
6  *  Copyright (C) Nigel Williams               2001.
7  *  Copyright (C) Gerald (Jerry) Carter        2006.
8  *  Copyright (C) Jelmer Vernooij                          2006.
9  *  
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 /* This is the implementation of the srvsvc pipe. */
26
27 #include "includes.h"
28
29 #define MAX_SERVER_DISK_ENTRIES 15
30
31 extern struct generic_mapping file_generic_mapping;
32 extern userdom_struct current_user_info;
33
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_RPC_SRV
36
37 /* Use for enumerating connections, pipes, & files */
38
39 struct file_enum_count {
40         TALLOC_CTX *ctx;
41         uint32 count;
42         struct srvsvc_NetFileInfo3 *info;
43 };
44
45 struct sess_file_count {
46         struct server_id pid;
47         uid_t uid;
48         int count;
49 };
50
51 /****************************************************************************
52  Count the entries belonging to a service in the connection db.
53 ****************************************************************************/
54
55 static int pipe_enum_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *p)
56 {
57         struct pipe_open_rec prec;
58         struct file_enum_count *fenum = (struct file_enum_count *)p;
59  
60         if (dbuf.dsize != sizeof(struct pipe_open_rec))
61                 return 0;
62
63         memcpy(&prec, dbuf.dptr, sizeof(struct pipe_open_rec));
64  
65         if ( process_exists(prec.pid) ) {
66                 struct srvsvc_NetFileInfo3 *f;
67                 int i = fenum->count;
68                 pstring fullpath;
69                 
70                 snprintf( fullpath, sizeof(fullpath), "\\PIPE\\%s", prec.name );
71                 
72                 f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, struct srvsvc_NetFileInfo3, i+1 );
73                 if ( !f ) {
74                         DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
75                         return 1;
76                 }
77
78                 fenum->info = f;
79                 
80                 fenum->info[i].fid = (uint32)((procid_to_pid(&prec.pid)<<16) & prec.pnum);
81                 fenum->info[i].permissions = (FILE_READ_DATA|FILE_WRITE_DATA);
82                 fenum->info[i].num_locks = 0;
83                 if (!(fenum->info[i].user = talloc_strdup(
84                               fenum->ctx, uidtoname(prec.uid)))) {
85                         /* There's not much we can do here. */
86                         fenum->info[i].user = "";
87                 }
88                 if (!(fenum->info[i].path = talloc_strdup(
89                               fenum->ctx, fullpath))) {
90                         /* There's not much we can do here. */
91                         fenum->info[i].path = "";
92                 }
93                         
94                 fenum->count++;
95         }
96
97         return 0;
98 }
99
100 /*******************************************************************
101 ********************************************************************/
102
103 static WERROR net_enum_pipes( TALLOC_CTX *ctx, struct srvsvc_NetFileInfo3 **info, 
104                               uint32 *count, uint32 *resume )
105 {
106         struct file_enum_count fenum;
107
108         fenum.ctx = ctx;
109         fenum.info = *info;
110         fenum.count = *count;
111
112         if (connections_traverse(pipe_enum_fn, &fenum) == -1) {
113                 DEBUG(0,("net_enum_pipes: traverse of connections.tdb "
114                          "failed\n"));
115                 return WERR_NOMEM;
116         }
117         
118         *info  = fenum.info;
119         *count = fenum.count;
120         
121         return WERR_OK;
122 }
123
124 /*******************************************************************
125 ********************************************************************/
126
127 /* global needed to make use of the share_mode_forall() callback */
128 static struct file_enum_count f_enum_cnt;
129
130 static void enum_file_fn( const struct share_mode_entry *e, 
131                           const char *sharepath, const char *fname,
132                           void *dummy )
133 {
134         struct file_enum_count *fenum = &f_enum_cnt;
135  
136         /* If the pid was not found delete the entry from connections.tdb */
137
138         if ( process_exists(e->pid) ) {
139                 struct srvsvc_NetFileInfo3 *f;
140                 int i = fenum->count;
141                 files_struct fsp;
142                 struct byte_range_lock *brl;
143                 int num_locks = 0;
144                 pstring fullpath;
145                 uint32 permissions;
146                 
147                 f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, struct srvsvc_NetFileInfo3, i+1 );                   
148                 if ( !f ) {
149                         DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
150                         return;
151                 }
152                 fenum->info = f;
153
154                 /* need to count the number of locks on a file */
155                 
156                 ZERO_STRUCT( fsp );             
157                 fsp.dev   = e->dev;
158                 fsp.inode = e->inode;
159                 
160                 if ( (brl = brl_get_locks_readonly(NULL,&fsp)) != NULL ) {
161                         num_locks = brl->num_locks;
162                         TALLOC_FREE( brl );
163                 }
164                 
165                 if ( strcmp( fname, "." ) == 0 ) {
166                         pstr_sprintf( fullpath, "C:%s", sharepath );
167                 } else {
168                         pstr_sprintf( fullpath, "C:%s/%s", sharepath, fname );
169                 }
170                 string_replace( fullpath, '/', '\\' );
171                 
172                 /* mask out create (what ever that is) */
173                 permissions = e->share_access & (FILE_READ_DATA|FILE_WRITE_DATA);
174
175                 fenum->info[i].fid = e->share_file_id;
176                 fenum->info[i].permissions = permissions;
177                 fenum->info[i].num_locks = num_locks;
178                 if (!(fenum->info[i].user = talloc_strdup(
179                               fenum->ctx, uidtoname(e->uid)))) {
180                         /* There's not much we can do here. */
181                         fenum->info[i].user = "";
182                 }
183                 if (!(fenum->info[i].path = talloc_strdup(
184                               fenum->ctx, fullpath))) {
185                         /* There's not much we can do here. */
186                         fenum->info[i].path = "";
187                 }
188                         
189                 fenum->count++;
190         }
191
192         return;
193
194 }
195
196 /*******************************************************************
197 ********************************************************************/
198
199 static WERROR net_enum_files( TALLOC_CTX *ctx, struct srvsvc_NetFileInfo3 **info, 
200                               uint32 *count, uint32 *resume )
201 {
202         f_enum_cnt.ctx = ctx;
203         f_enum_cnt.count = *count;
204         f_enum_cnt.info = *info;
205         
206         share_mode_forall( enum_file_fn, NULL );
207         
208         *info  = f_enum_cnt.info;
209         *count = f_enum_cnt.count;
210         
211         return WERR_OK;
212 }
213
214 /*******************************************************************
215  Utility function to get the 'type' of a share from a share definition.
216  ********************************************************************/
217 static uint32 get_share_type(const struct share_params *params)
218 {
219         char *net_name = lp_servicename(params->service);
220         int len_net_name = strlen(net_name);
221         
222         /* work out the share type */
223         uint32 type = STYPE_DISKTREE;
224
225         if (lp_print_ok(params->service))
226                 type = STYPE_PRINTQ;
227         if (strequal(lp_fstype(params->service), "IPC"))
228                 type = STYPE_IPC;
229         if (net_name[len_net_name-1] == '$')
230                 type |= STYPE_HIDDEN;
231
232         return type;
233 }
234         
235 /*******************************************************************
236  Fill in a share info level 0 structure.
237  ********************************************************************/
238
239 static void init_srv_share_info_0(pipes_struct *p, struct srvsvc_NetShareInfo0 *sh0,
240                                   const struct share_params *params)
241 {
242         sh0->name = lp_servicename(params->service);
243 }
244
245 /*******************************************************************
246  Fill in a share info level 1 structure.
247  ********************************************************************/
248
249 static void init_srv_share_info_1(pipes_struct *p, struct srvsvc_NetShareInfo1 *sh1,
250                                   const struct share_params *params)
251 {
252         connection_struct *conn = p->conn;
253
254         sh1->comment = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
255                                      conn->user, conn->connectpath, conn->gid,
256                                      get_current_username(),
257                                      current_user_info.domain,
258                                      lp_comment(params->service));
259
260         sh1->name = lp_servicename(params->service);
261         sh1->type = get_share_type(params);
262 }
263
264 /*******************************************************************
265  Fill in a share info level 2 structure.
266  ********************************************************************/
267
268 static void init_srv_share_info_2(pipes_struct *p, struct srvsvc_NetShareInfo2 *sh2,
269                                   const struct share_params *params)
270 {
271         connection_struct *conn = p->conn;
272         char *remark;
273         char *path;
274         int max_connections = lp_max_connections(params->service);
275         uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
276         int count = 0;
277         char *net_name = lp_servicename(params->service);
278         
279         remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
280                                      conn->user, conn->connectpath, conn->gid,
281                                      get_current_username(),
282                                      current_user_info.domain,
283                                      lp_comment(params->service));
284         path = talloc_asprintf(p->mem_ctx, "C:%s",
285                                lp_pathname(params->service));
286
287         /*
288          * Change / to \\ so that win2k will see it as a valid path.  This was
289          * added to enable use of browsing in win2k add share dialog.
290          */ 
291
292         string_replace(path, '/', '\\');
293
294         count = count_current_connections( net_name, False  );
295         sh2->name = net_name;
296         sh2->type = get_share_type(params);
297         sh2->comment = remark;
298         sh2->permissions = 0;
299         sh2->max_users = max_uses;
300         sh2->current_users = count;
301         sh2->path = path;
302         sh2->password = "";
303 }
304
305 /*******************************************************************
306  Map any generic bits to file specific bits.
307 ********************************************************************/
308
309 static void map_generic_share_sd_bits(SEC_DESC *psd)
310 {
311         int i;
312         SEC_ACL *ps_dacl = NULL;
313
314         if (!psd)
315                 return;
316
317         ps_dacl = psd->dacl;
318         if (!ps_dacl)
319                 return;
320
321         for (i = 0; i < ps_dacl->num_aces; i++) {
322                 SEC_ACE *psa = &ps_dacl->aces[i];
323                 uint32 orig_mask = psa->access_mask;
324
325                 se_map_generic(&psa->access_mask, &file_generic_mapping);
326                 psa->access_mask |= orig_mask;
327         }       
328 }
329
330 /*******************************************************************
331  Fill in a share info level 501 structure.
332 ********************************************************************/
333
334 static void init_srv_share_info_501(pipes_struct *p, struct srvsvc_NetShareInfo501 *sh501,
335                                     const struct share_params *params)
336 {
337         connection_struct *conn = p->conn;
338         char *remark;
339         const char *net_name = lp_servicename(params->service);
340
341         remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
342                                      conn->user, conn->connectpath, conn->gid,
343                                      get_current_username(),
344                                      current_user_info.domain,
345                                      lp_comment(params->service));
346
347
348         sh501->name = net_name;
349         sh501->type = get_share_type(params);
350         sh501->comment = remark;
351         sh501->csc_policy = (lp_csc_policy(params->service) << 4);
352 }
353
354 /*******************************************************************
355  Fill in a share info level 502 structure.
356  ********************************************************************/
357
358 static void init_srv_share_info_502(pipes_struct *p, struct srvsvc_NetShareInfo502 *sh502,
359                                     const struct share_params *params)
360 {
361         int max_connections = lp_max_connections(params->service);
362         uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
363         connection_struct *conn = p->conn;
364         int count; 
365         char *net_name;
366         char *remark;
367         char *path;
368         SEC_DESC *sd;
369         size_t sd_size;
370         TALLOC_CTX *ctx = p->mem_ctx;
371
372
373         ZERO_STRUCTP(sh502);
374
375         net_name = lp_servicename(params->service);
376         count = count_current_connections( net_name, False  );
377
378         remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
379                                      conn->user, conn->connectpath, conn->gid,
380                                      get_current_username(),
381                                      current_user_info.domain,
382                                      lp_comment(params->service));
383
384         path = talloc_asprintf(p->mem_ctx, "C:%s",
385                                lp_pathname(params->service));
386
387         /*
388          * Change / to \\ so that win2k will see it as a valid path.  This was
389          * added to enable use of browsing in win2k add share dialog.
390          */ 
391
392         string_replace(path, '/', '\\');
393
394         sd = get_share_security(ctx, lp_servicename(params->service),
395                                 &sd_size);
396
397         sh502->name = net_name;
398         sh502->type = get_share_type(params);
399         sh502->comment = remark;
400         sh502->path = path;
401         sh502->password = "";
402         sh502->sd = sd;
403         sh502->permissions = 0;
404         sh502->max_users = max_uses;
405         sh502->current_users = count;
406         sh502->unknown = 1;
407 }
408
409 /***************************************************************************
410  Fill in a share info level 1004 structure.
411  ***************************************************************************/
412
413 static void init_srv_share_info_1004(pipes_struct *p,
414                                      struct srvsvc_NetShareInfo1004* sh1004,
415                                      const struct share_params *params)
416 {
417         connection_struct *conn = p->conn;
418         char *remark;
419
420         remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
421                                      conn->user, conn->connectpath, conn->gid,
422                                      get_current_username(),
423                                      current_user_info.domain,
424                                      lp_comment(params->service));
425
426         ZERO_STRUCTP(sh1004);
427
428         sh1004->comment = remark;
429 }
430
431 /***************************************************************************
432  Fill in a share info level 1005 structure.
433  ***************************************************************************/
434
435 static void init_srv_share_info_1005(pipes_struct *p,
436                                      struct srvsvc_NetShareInfo1005* sh1005,
437                                      const struct share_params *params)
438 {
439         sh1005->dfs_flags = 0;
440
441         if(lp_host_msdfs() && lp_msdfs_root(params->service))
442                 sh1005->dfs_flags |= 
443                         SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
444         sh1005->dfs_flags |= 
445                 lp_csc_policy(params->service) << SHARE_1005_CSC_POLICY_SHIFT;
446 }
447 /***************************************************************************
448  Fill in a share info level 1006 structure.
449  ***************************************************************************/
450
451 static void init_srv_share_info_1006(pipes_struct *p,
452                                      struct srvsvc_NetShareInfo1006* sh1006,
453                                      const struct share_params *params)
454 {
455         sh1006->max_users = -1;
456 }
457
458 /***************************************************************************
459  Fill in a share info level 1007 structure.
460  ***************************************************************************/
461
462 static void init_srv_share_info_1007(pipes_struct *p,
463                                      struct srvsvc_NetShareInfo1007* sh1007,
464                                      const struct share_params *params)
465 {
466         uint32 flags = 0;
467
468         ZERO_STRUCTP(sh1007);
469   
470         sh1007->flags = flags;
471         sh1007->alternate_directory_name = "";
472 }
473
474 /*******************************************************************
475  Fill in a share info level 1501 structure.
476  ********************************************************************/
477
478 static void init_srv_share_info_1501(pipes_struct *p,
479                                      struct sec_desc_buf *sh1501,
480                                      const struct share_params *params)
481 {
482         SEC_DESC *sd;
483         size_t sd_size;
484         TALLOC_CTX *ctx = p->mem_ctx;
485
486         ZERO_STRUCTP(sh1501);
487
488         sd = get_share_security(ctx, lp_servicename(params->service),
489                                 &sd_size);
490
491         sh1501->sd = sd;
492 }
493
494 /*******************************************************************
495  True if it ends in '$'.
496  ********************************************************************/
497
498 static BOOL is_hidden_share(const struct share_params *params)
499 {
500         const char *net_name = lp_servicename(params->service);
501
502         return (net_name[strlen(net_name) - 1] == '$');
503 }
504
505 /*******************************************************************
506  Fill in a share info structure.
507  ********************************************************************/
508
509 static WERROR init_srv_share_info_ctr(pipes_struct *p,
510                                       union srvsvc_NetShareCtr *ctr,
511                                       uint32 info_level, uint32 *resume_hnd,
512                                       uint32 *total_entries, BOOL all_shares)
513 {
514         TALLOC_CTX *ctx = p->mem_ctx;
515         struct share_iterator *shares;
516         struct share_params *share;
517         WERROR result = WERR_NOMEM;
518
519         DEBUG(5,("init_srv_share_info_ctr\n"));
520
521         ZERO_STRUCTP(ctr);
522
523         if (resume_hnd) {
524                 *resume_hnd = 0;
525         }
526
527         /* Ensure all the usershares are loaded. */
528         become_root();
529         load_usershare_shares();
530         load_registry_shares();
531         unbecome_root();
532
533         *total_entries = 0;
534
535         if (!(shares = share_list_all(ctx))) {
536                 DEBUG(5, ("Could not list shares\n"));
537                 return WERR_ACCESS_DENIED;
538         }
539
540         switch (info_level) {
541         case 0:
542                 if (!(ctr->ctr0 = TALLOC_ZERO_P(
543                               p->mem_ctx, struct srvsvc_NetShareCtr0))) {
544                         goto done;
545                 }
546                 break;
547         case 1:
548                 if (!(ctr->ctr1 = TALLOC_ZERO_P(
549                               p->mem_ctx, struct srvsvc_NetShareCtr1))) {
550                         goto done;
551                 }
552                 break;
553         case 2:
554                 if (!(ctr->ctr2 = TALLOC_ZERO_P(
555                               p->mem_ctx, struct srvsvc_NetShareCtr2))) {
556                         goto done;
557                 }
558                 break;
559         case 501:
560                 if (!(ctr->ctr501 = TALLOC_ZERO_P(
561                               p->mem_ctx, struct srvsvc_NetShareCtr501))) {
562                         goto done;
563                 }
564                 break;
565         case 502:
566                 if (!(ctr->ctr502 = TALLOC_ZERO_P(
567                               p->mem_ctx, struct srvsvc_NetShareCtr502))) {
568                         goto done;
569                 }
570                 break;
571         case 1004:
572                 if (!(ctr->ctr1004 = TALLOC_ZERO_P(
573                               p->mem_ctx, struct srvsvc_NetShareCtr1004))) {
574                         goto done;
575                 }
576                 break;
577         case 1005:
578                 if (!(ctr->ctr1005 = TALLOC_ZERO_P(
579                               p->mem_ctx, struct srvsvc_NetShareCtr1005))) {
580                         goto done;
581                 }
582                 break;
583         case 1006:
584                 if (!(ctr->ctr1006 = TALLOC_ZERO_P(
585                               p->mem_ctx, struct srvsvc_NetShareCtr1006))) {
586                         goto done;
587                 }
588                 break;
589         case 1007:
590                 if (!(ctr->ctr1007 = TALLOC_ZERO_P(
591                               p->mem_ctx, struct srvsvc_NetShareCtr1007))) {
592                         goto done;
593                 }
594                 break;
595         case 1501:
596                 if (!(ctr->ctr1501 = TALLOC_ZERO_P(
597                               p->mem_ctx, struct srvsvc_NetShareCtr1501))) {
598                         goto done;
599                 }
600                 break;
601         default:
602                 DEBUG(5,("init_srv_share_info_ctr: unsupported switch "
603                          "value %d\n", info_level));
604                 return WERR_UNKNOWN_LEVEL;
605         }
606
607         while ((share = next_share(shares)) != NULL) {
608                 if (!lp_browseable(share->service)) {
609                         continue;
610                 }
611                 if (!all_shares && is_hidden_share(share)) {
612                         continue;
613                 }
614
615                 switch (info_level) {
616                 case 0:
617                 {
618                         struct srvsvc_NetShareInfo0 i;
619                         init_srv_share_info_0(p, &i, share);
620                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo0, i,
621                                      &ctr->ctr0->array, &ctr->ctr0->count);
622                         if (ctr->ctr0->array == NULL) {
623                                 return WERR_NOMEM;
624                         }
625                         *total_entries = ctr->ctr0->count;
626                         break;
627                 }
628
629                 case 1:
630                 {
631                         struct srvsvc_NetShareInfo1 i;
632                         init_srv_share_info_1(p, &i, share);
633                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1, i,
634                                      &ctr->ctr1->array, &ctr->ctr1->count);
635                         if (ctr->ctr1->array == NULL) {
636                                 return WERR_NOMEM;
637                         }
638                         *total_entries = ctr->ctr1->count;
639                         break;
640                 }
641
642                 case 2:
643                 {
644                         struct srvsvc_NetShareInfo2 i;
645                         init_srv_share_info_2(p, &i, share);
646                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo2, i,
647                                      &ctr->ctr2->array, &ctr->ctr2->count);
648                         if (ctr->ctr2->array == NULL) {
649                                 return WERR_NOMEM;
650                         }
651                         *total_entries = ctr->ctr2->count;
652                         break;
653                 }
654
655                 case 501:
656                 {
657                         struct srvsvc_NetShareInfo501 i;
658                         init_srv_share_info_501(p, &i, share);
659                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo501, i,
660                                      &ctr->ctr501->array, &ctr->ctr501->count);
661                         if (ctr->ctr501->array == NULL) {
662                                 return WERR_NOMEM;
663                         }
664                         *total_entries = ctr->ctr501->count;
665                         break;
666                 }
667
668                 case 502:
669                 {
670                         struct srvsvc_NetShareInfo502 i;
671                         init_srv_share_info_502(p, &i, share);
672                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo502, i,
673                                      &ctr->ctr502->array, &ctr->ctr502->count);
674                         if (ctr->ctr502->array == NULL) {
675                                 return WERR_NOMEM;
676                         }
677                         *total_entries = ctr->ctr502->count;
678                         break;
679                 }
680
681                 /* here for completeness but not currently used with enum
682                  * (1004 - 1501)*/
683         
684                 case 1004:
685                 {
686                         struct srvsvc_NetShareInfo1004 i;
687                         init_srv_share_info_1004(p, &i, share);
688                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1004, i,
689                                      &ctr->ctr1004->array, &ctr->ctr1004->count);
690                         if (ctr->ctr1004->array == NULL) {
691                                 return WERR_NOMEM;
692                         }
693                         *total_entries = ctr->ctr1004->count;
694                         break;
695                 }
696
697                 case 1005:
698                 {
699                         struct srvsvc_NetShareInfo1005 i;
700                         init_srv_share_info_1005(p, &i, share);
701                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1005, i,
702                                      &ctr->ctr1005->array, &ctr->ctr1005->count);
703                         if (ctr->ctr1005->array == NULL) {
704                                 return WERR_NOMEM;
705                         }
706                         *total_entries = ctr->ctr1005->count;
707                         break;
708                 }
709
710                 case 1006:
711                 {
712                         struct srvsvc_NetShareInfo1006 i;
713                         init_srv_share_info_1006(p, &i, share);
714                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1006, i,
715                                      &ctr->ctr1006->array, &ctr->ctr1006->count);
716                         if (ctr->ctr1006->array == NULL) {
717                                 return WERR_NOMEM;
718                         }
719                         *total_entries = ctr->ctr1006->count;
720                         break;
721                 }
722
723                 case 1007:
724                 {
725                         struct srvsvc_NetShareInfo1007 i;
726                         init_srv_share_info_1007(p, &i, share);
727                         ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1007, i,
728                                      &ctr->ctr1007->array, &ctr->ctr1007->count);
729                         if (ctr->ctr1007->array == NULL) {
730                                 return WERR_NOMEM;
731                         }
732                         *total_entries = ctr->ctr1007->count;
733                         break;
734                 }
735
736                 case 1501:
737                 {
738                         struct sec_desc_buf i;
739                         init_srv_share_info_1501(p, &i, share);
740                         ADD_TO_ARRAY(ctx, struct sec_desc_buf, i,
741                                      &ctr->ctr1501->array, &ctr->ctr1501->count);
742                         if (ctr->ctr1501->array == NULL) {
743                                 return WERR_NOMEM;
744                         }
745                         *total_entries = ctr->ctr1501->count;
746                         break;
747                 }
748                 }
749
750                 TALLOC_FREE(share);
751         }
752
753         result = WERR_OK;
754  done:
755         TALLOC_FREE(shares);
756         return result;
757 }
758
759 /*******************************************************************
760  fill in a sess info level 0 structure.
761  ********************************************************************/
762
763 static void init_srv_sess_info_0(pipes_struct *p, struct srvsvc_NetSessCtr0 *ss0, uint32 *snum, uint32 *stot)
764 {
765         struct sessionid *session_list;
766         uint32 num_entries = 0;
767         (*stot) = list_sessions(p->mem_ctx, &session_list);
768
769         if (ss0 == NULL) {
770                 if (snum) {
771                         (*snum) = 0;
772                 }
773                 return;
774         }
775
776         DEBUG(5,("init_srv_sess_0_ss0\n"));
777
778         ss0->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetSessInfo0, *stot);
779
780         if (snum) {
781                 for (; (*snum) < (*stot); (*snum)++) {
782                         ss0->array[num_entries].client = session_list[(*snum)].remote_machine;
783                         num_entries++;
784                 }
785
786                 ss0->count = num_entries;
787                 
788                 if ((*snum) >= (*stot)) {
789                         (*snum) = 0;
790                 }
791
792         } else {
793                 ss0->array = NULL;
794                 ss0->count = 0;
795         }
796 }
797
798 /*******************************************************************
799 ********************************************************************/
800
801 static void sess_file_fn( const struct share_mode_entry *e, 
802                           const char *sharepath, const char *fname,
803                           void *private_data )
804 {
805         struct sess_file_count *sess = (struct sess_file_count *)private_data;
806  
807         if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
808                 sess->count++;
809         }
810         
811         return;
812 }
813
814 /*******************************************************************
815 ********************************************************************/
816
817 static int net_count_files( uid_t uid, struct server_id pid )
818 {
819         struct sess_file_count s_file_cnt;
820
821         s_file_cnt.count = 0;
822         s_file_cnt.uid = uid;
823         s_file_cnt.pid = pid;
824         
825         share_mode_forall( sess_file_fn, (void *)&s_file_cnt );
826         
827         return s_file_cnt.count;
828 }
829
830 /*******************************************************************
831  fill in a sess info level 1 structure.
832  ********************************************************************/
833
834 static void init_srv_sess_info_1(pipes_struct *p, struct srvsvc_NetSessCtr1 *ss1, uint32 *snum, uint32 *stot)
835 {
836         struct sessionid *session_list;
837         uint32 num_entries = 0;
838         time_t now = time(NULL);
839
840         if ( !snum ) {
841                 ss1->count = 0;
842                 ss1->array = NULL;
843                 
844                 (*stot) = 0;
845
846                 return;
847         }
848         
849         if (ss1 == NULL) {
850                 if (snum != NULL)
851                         (*snum) = 0;
852                 return;
853         }
854
855         (*stot) = list_sessions(p->mem_ctx, &session_list);
856
857         ss1->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetSessInfo1, *stot);
858         
859         for (; (*snum) < (*stot); (*snum)++) {
860                 uint32 num_files;
861                 uint32 connect_time;
862                 struct passwd *pw = sys_getpwnam(session_list[*snum].username);
863                 BOOL guest;
864                         
865                 if ( !pw ) {
866                         DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
867                                 session_list[*snum].username));
868                         continue;
869                 }
870                                 
871                 connect_time = (uint32)(now - session_list[*snum].connect_start);
872                 num_files = net_count_files(pw->pw_uid, session_list[*snum].pid);
873                 guest = strequal( session_list[*snum].username, lp_guestaccount() );
874                                         
875                 if (!(ss1->array[num_entries].client = talloc_strdup(
876                               ss1->array, session_list[*snum].remote_machine))) {
877                         ss1->array[num_entries].client = "";
878                 }
879                 if (!(ss1->array[num_entries].user = talloc_strdup(
880                               ss1->array, session_list[*snum].username))) {
881                         ss1->array[num_entries].user = "";
882                 }
883                 ss1->array[num_entries].num_open = num_files;
884                 ss1->array[num_entries].time = connect_time;
885                 ss1->array[num_entries].idle_time = 0;
886                 ss1->array[num_entries].user_flags = guest;
887
888                 num_entries++;
889         }
890
891         ss1->count = num_entries;
892         
893         if ((*snum) >= (*stot)) {
894                 (*snum) = 0;
895         }
896 }
897
898 /*******************************************************************
899  makes a SRV_R_NET_SESS_ENUM structure.
900 ********************************************************************/
901
902 static WERROR init_srv_sess_info_ctr(pipes_struct *p, union srvsvc_NetSessCtr *ctr,
903                                 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
904 {
905         WERROR status = WERR_OK;
906         DEBUG(5,("init_srv_sess_info_ctr: %d\n", __LINE__));
907
908         switch (switch_value) {
909         case 0:
910                 ctr->ctr0 = talloc(p->mem_ctx, struct srvsvc_NetSessCtr0);
911                 init_srv_sess_info_0(p, ctr->ctr0, resume_hnd, total_entries);
912                 break;
913         case 1:
914                 ctr->ctr1 = talloc(p->mem_ctx, struct srvsvc_NetSessCtr1);
915                 init_srv_sess_info_1(p, ctr->ctr1, resume_hnd, total_entries);
916                 break;
917         default:
918                 DEBUG(5,("init_srv_sess_info_ctr: unsupported switch value %d\n", switch_value));
919                 if (resume_hnd != NULL)
920                         (*resume_hnd) = 0;
921                 (*total_entries) = 0;
922                 ctr->ctr0 = NULL;
923                 status = WERR_UNKNOWN_LEVEL;
924                 break;
925         }
926
927         return status;
928 }
929
930 /*******************************************************************
931  fill in a conn info level 0 structure.
932  ********************************************************************/
933
934 static void init_srv_conn_info_0(pipes_struct *p, struct srvsvc_NetConnCtr0 *ss0, uint32 *snum, uint32 *stot)
935 {
936         uint32 num_entries = 0;
937         (*stot) = 1;
938
939         if (ss0 == NULL) {
940                 if (snum != NULL)
941                         (*snum) = 0;
942                 return;
943         }
944
945         DEBUG(5,("init_srv_conn_0_ss0\n"));
946
947         if (snum) {
948                 ss0->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetConnInfo0, *stot);
949                 for (; (*snum) < (*stot); (*snum)++) {
950
951                         ss0->array[num_entries].conn_id = (*stot);
952
953                         /* move on to creating next connection */
954                         /* move on to creating next conn */
955                         num_entries++;
956                 }
957
958                 ss0->count = num_entries;
959                 
960                 if ((*snum) >= (*stot)) {
961                         (*snum) = 0;
962                 }
963
964         } else {
965                 ss0->array = NULL;
966                 ss0->count = 0;
967
968                 (*stot) = 0;
969         }
970 }
971
972 /*******************************************************************
973  fill in a conn info level 1 structure.
974  ********************************************************************/
975
976 static void init_srv_conn_info_1(pipes_struct *p, struct srvsvc_NetConnCtr1 *ss1, uint32 *snum, uint32 *stot)
977 {
978         uint32 num_entries = 0;
979         (*stot) = 1;
980
981         if (ss1 == NULL) {
982                 if (snum != NULL)
983                         (*snum) = 0;
984                 return;
985         }
986
987         DEBUG(5,("init_srv_conn_1_ss1\n"));
988
989         if (snum) {
990                 ss1->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetConnInfo1, *stot);
991                 for (; (*snum) < (*stot); (*snum)++) {
992                         ss1->array[num_entries].conn_id = (*stot);
993                         ss1->array[num_entries].conn_type = 0x3;
994                         ss1->array[num_entries].num_open = 1;
995                         ss1->array[num_entries].num_users = 1;
996                         ss1->array[num_entries].conn_time = 3;
997                         ss1->array[num_entries].user = "dummy_user";
998                         ss1->array[num_entries].share = "IPC$";
999
1000                         /* move on to creating next connection */
1001                         /* move on to creating next conn */
1002                         num_entries++;
1003                 }
1004
1005                 ss1->count = num_entries;
1006
1007                 if ((*snum) >= (*stot)) {
1008                         (*snum) = 0;
1009                 }
1010
1011         } else {
1012                 ss1->count = 0;
1013                 ss1->array = NULL;
1014                 
1015                 (*stot) = 0;
1016         }
1017 }
1018
1019 /*******************************************************************
1020  makes a SRV_R_NET_CONN_ENUM structure.
1021 ********************************************************************/
1022
1023 static WERROR init_srv_conn_info_ctr(pipes_struct *p, union srvsvc_NetConnCtr *ctr,
1024                                 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
1025 {
1026         WERROR status = WERR_OK;
1027         DEBUG(5,("init_srv_conn_info_ctr: %d\n", __LINE__));
1028
1029         switch (switch_value) {
1030         case 0:
1031                 init_srv_conn_info_0(p, ctr->ctr0, resume_hnd, total_entries);
1032                 break;
1033         case 1:
1034                 init_srv_conn_info_1(p, ctr->ctr1, resume_hnd, total_entries);
1035                 break;
1036         default:
1037                 DEBUG(5,("init_srv_conn_info_ctr: unsupported switch value %d\n", switch_value));
1038                 ctr->ctr0 = NULL;
1039                 (*resume_hnd) = 0;
1040                 (*total_entries) = 0;
1041                 status = WERR_UNKNOWN_LEVEL;
1042                 break;
1043         }
1044
1045         return status;
1046 }
1047
1048 /*******************************************************************
1049  makes a SRV_R_NET_FILE_ENUM structure.
1050 ********************************************************************/
1051
1052 static WERROR net_file_enum_3(pipes_struct *p, union srvsvc_NetFileCtr *ctr, uint32 *resume_hnd, uint32 *num_entries )
1053 {
1054         TALLOC_CTX *ctx = get_talloc_ctx();
1055         WERROR status;
1056
1057         /* TODO -- Windows enumerates 
1058            (b) active pipes
1059            (c) open directories and files */
1060
1061         ctr->ctr3 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetFileCtr3);
1062         
1063         status = net_enum_files( ctx, &ctr->ctr3->array, num_entries, resume_hnd );
1064         if ( !W_ERROR_IS_OK(status))
1065                 return status;
1066                 
1067         status = net_enum_pipes( ctx, &ctr->ctr3->array, num_entries, resume_hnd );
1068         if ( !W_ERROR_IS_OK(status))
1069                 return status;
1070
1071         ctr->ctr3->count = *num_entries;
1072         
1073         return WERR_OK;
1074 }
1075
1076 /*******************************************************************
1077 *******************************************************************/
1078
1079 WERROR _srvsvc_NetFileEnum(pipes_struct *p, struct srvsvc_NetFileEnum *r)
1080 {
1081         switch ( *r->in.level ) {
1082         case 3:
1083                 return net_file_enum_3(p, r->in.ctr, r->in.resume_handle, r->out.totalentries );        
1084         default:
1085                 return WERR_UNKNOWN_LEVEL;
1086         }
1087         
1088         return WERR_OK;
1089 }
1090
1091 /*******************************************************************
1092 net server get info
1093 ********************************************************************/
1094
1095 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p, struct srvsvc_NetSrvGetInfo *r)
1096 {
1097         WERROR status = WERR_OK;
1098
1099         ZERO_STRUCTP(r->out.info);
1100
1101         DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1102
1103         if (!pipe_access_check(p)) {
1104                 DEBUG(3, ("access denied to srv_net_srv_get_info\n"));
1105                 return WERR_ACCESS_DENIED;
1106         }
1107
1108         switch (r->in.level) {
1109
1110                 /* Technically level 102 should only be available to
1111                    Administrators but there isn't anything super-secret
1112                    here, as most of it is made up. */
1113
1114         case 102:
1115                 r->out.info->info102 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1116
1117                 r->out.info->info102->platform_id = 500;
1118                 r->out.info->info102->version_major = lp_major_announce_version();
1119                 r->out.info->info102->version_minor = lp_minor_announce_version();
1120                 r->out.info->info102->server_name = global_myname(); 
1121                 r->out.info->info102->server_type = lp_default_server_announce();
1122                 r->out.info->info102->userpath = "C:\\";
1123                 r->out.info->info102->licenses = 10000;
1124                 r->out.info->info102->anndelta = 3000;
1125                 r->out.info->info102->disc = 0xf;
1126                 r->out.info->info102->users = 0xffffffff;
1127                 r->out.info->info102->hidden = 0;
1128                 r->out.info->info102->announce = 240;
1129                 r->out.info->info102->comment = lp_serverstring();
1130                 break;
1131         case 101:
1132                 r->out.info->info101 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1133                         r->out.info->info101->platform_id = 500;
1134                         r->out.info->info101->server_name = global_myname();
1135                         r->out.info->info101->version_major = lp_major_announce_version();
1136                         r->out.info->info101->version_minor = lp_minor_announce_version();
1137                         r->out.info->info101->server_type = lp_default_server_announce();
1138                         r->out.info->info101->comment = lp_serverstring();
1139                 break;
1140         case 100:
1141                 r->out.info->info100 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1142                 r->out.info->info100->platform_id = 500;
1143                 r->out.info->info100->server_name = global_myname();
1144                 break;
1145         default:
1146                 return WERR_UNKNOWN_LEVEL;
1147                 break;
1148         }
1149
1150         DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1151
1152         return status;
1153 }
1154
1155 /*******************************************************************
1156 net server set info
1157 ********************************************************************/
1158
1159 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p, struct srvsvc_NetSrvSetInfo *r)
1160 {
1161         /* Set up the net server set info structure. */
1162         if (r->out.parm_error) {
1163                 *r->out.parm_error = 0;
1164         }
1165         return WERR_OK;
1166 }
1167
1168 /*******************************************************************
1169 net conn enum
1170 ********************************************************************/
1171
1172 WERROR _srvsvc_NetConnEnum(pipes_struct *p, struct srvsvc_NetConnEnum *r)
1173 {
1174         DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
1175
1176         ZERO_STRUCTP(r->out.ctr);
1177
1178         /* set up the */
1179         return init_srv_conn_info_ctr(p, r->out.ctr, *r->in.level, r->in.resume_handle, r->out.totalentries);
1180 }
1181
1182 /*******************************************************************
1183 net sess enum
1184 ********************************************************************/
1185
1186 WERROR _srvsvc_NetSessEnum(pipes_struct *p, struct srvsvc_NetSessEnum *r)
1187 {
1188         DEBUG(5,("_srv_net_sess_enum: %d\n", __LINE__));
1189
1190         ZERO_STRUCTP(r->out.ctr);
1191
1192         /* set up the */
1193         return init_srv_sess_info_ctr(p, r->out.ctr,
1194                                 *r->in.level, 
1195                                 r->in.resume_handle,
1196                                 r->out.totalentries);
1197 }
1198
1199 /*******************************************************************
1200 net sess del
1201 ********************************************************************/
1202
1203 WERROR _srvsvc_NetSessDel(pipes_struct *p, struct srvsvc_NetSessDel *r)
1204 {
1205         struct sessionid *session_list;
1206         int num_sessions, snum;
1207         WERROR status;
1208
1209         char *machine = talloc_strdup(p->mem_ctx, r->in.server_unc);
1210
1211         /* strip leading backslashes if any */
1212         while (machine[0] == '\\') {
1213                 memmove(machine, &machine[1], strlen(machine));
1214         }
1215
1216         num_sessions = list_sessions(p->mem_ctx, &session_list);
1217
1218         DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
1219
1220         status = WERR_ACCESS_DENIED;
1221
1222         /* fail out now if you are not root or not a domain admin */
1223
1224         if ((p->pipe_user.ut.uid != sec_initial_uid()) && 
1225                 ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
1226
1227                 goto done;
1228         }
1229
1230         for (snum = 0; snum < num_sessions; snum++) {
1231
1232                 if ((strequal(session_list[snum].username, r->in.user) || r->in.user[0] == '\0' ) &&
1233                      strequal(session_list[snum].remote_machine, machine)) {
1234                         NTSTATUS ntstat;
1235
1236                         ntstat = messaging_send(smbd_messaging_context(),
1237                                                 session_list[snum].pid,
1238                                                 MSG_SHUTDOWN, &data_blob_null);
1239                 
1240                         if (NT_STATUS_IS_OK(ntstat))
1241                                 status = WERR_OK;
1242                 }
1243         }
1244
1245         DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
1246
1247 done:
1248         return status;
1249 }
1250
1251 /*******************************************************************
1252  Net share enum all.
1253 ********************************************************************/
1254
1255 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p, struct srvsvc_NetShareEnumAll *r)
1256 {
1257         DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1258
1259         if (!pipe_access_check(p)) {
1260                 DEBUG(3, ("access denied to srv_net_share_enum_all\n"));
1261                 return WERR_ACCESS_DENIED;
1262         }
1263
1264         /* Create the list of shares for the response. */
1265         return init_srv_share_info_ctr(p, r->out.ctr, *r->in.level,
1266                                               r->in.resume_handle, r->out.totalentries, True);
1267 }
1268
1269 /*******************************************************************
1270  Net share enum.
1271 ********************************************************************/
1272
1273 WERROR _srvsvc_NetShareEnum(pipes_struct *p, struct srvsvc_NetShareEnum *r)
1274 {
1275         DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1276
1277         if (!pipe_access_check(p)) {
1278                 DEBUG(3, ("access denied to srv_net_share_enum\n"));
1279                 return WERR_ACCESS_DENIED;
1280         }
1281
1282         /* Create the list of shares for the response. */
1283         return init_srv_share_info_ctr(p, r->out.ctr, *r->in.level,
1284                                               r->in.resume_handle, r->out.totalentries, False);
1285 }
1286
1287 /*******************************************************************
1288  Net share get info.
1289 ********************************************************************/
1290
1291 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p, struct srvsvc_NetShareGetInfo *r)
1292 {
1293         const struct share_params *params;
1294
1295         params = get_share_params(p->mem_ctx, r->in.share_name);
1296
1297         if (params != NULL) {
1298                 switch (r->in.level) {
1299                 case 0:
1300                         r->out.info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1301                         init_srv_share_info_0(p, r->out.info->info0, params);
1302                         break;
1303                 case 1:
1304                         r->out.info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1305                         init_srv_share_info_1(p, r->out.info->info1, params);
1306                         break;
1307                 case 2:
1308                         r->out.info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1309                         init_srv_share_info_2(p, r->out.info->info2, params);
1310                         break;
1311                 case 501:
1312                         r->out.info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1313                         init_srv_share_info_501(p, r->out.info->info501, params);
1314                         break;
1315                 case 502:
1316                         r->out.info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1317                         init_srv_share_info_502(p, r->out.info->info502, params);
1318                         break;
1319
1320                         /* here for completeness */
1321                 case 1004:
1322                         r->out.info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1323                         init_srv_share_info_1004(p, r->out.info->info1004, params);
1324                         break;
1325                 case 1005:
1326                         r->out.info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1327                         init_srv_share_info_1005(p, r->out.info->info1005, params);
1328                         break;
1329
1330                         /* here for completeness 1006 - 1501 */
1331                 case 1006:
1332                         r->out.info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1333                         init_srv_share_info_1006(p, r->out.info->info1006,
1334                                                  params);
1335                         break;
1336                 case 1007:
1337                         r->out.info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1338                         init_srv_share_info_1007(p, r->out.info->info1007,
1339                                                  params);
1340                         break;
1341                 case 1501:
1342                         r->out.info->info1501 = talloc(p->mem_ctx, struct sec_desc_buf);
1343                         init_srv_share_info_1501(p, r->out.info->info1501,
1344                                                  params);
1345                         break;
1346                 default:
1347                         DEBUG(5,("init_srv_net_share_get_info: unsupported "
1348                                  "switch value %d\n", r->in.level));
1349                         return WERR_UNKNOWN_LEVEL;
1350                         break;
1351                 }
1352         } else {
1353                 return WERR_INVALID_NAME;
1354         }
1355
1356         return WERR_OK;
1357 }
1358
1359 /*******************************************************************
1360  Check a given DOS pathname is valid for a share.
1361 ********************************************************************/
1362
1363 char *valid_share_pathname(char *dos_pathname)
1364 {
1365         char *ptr;
1366
1367         /* Convert any '\' paths to '/' */
1368         unix_format(dos_pathname);
1369         unix_clean_name(dos_pathname);
1370
1371         /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1372         ptr = dos_pathname;
1373         if (strlen(dos_pathname) > 2 && ptr[1] == ':' && ptr[0] != '/')
1374                 ptr += 2;
1375
1376         /* Only absolute paths allowed. */
1377         if (*ptr != '/')
1378                 return NULL;
1379
1380         return ptr;
1381 }
1382
1383 static void setval_helper(struct registry_key *key, const char *name,
1384                           const char *value, WERROR *err)
1385 {
1386         struct registry_value val;
1387
1388         if (!W_ERROR_IS_OK(*err)) {
1389                 return;
1390         }
1391
1392         ZERO_STRUCT(val);
1393         val.type = REG_SZ;
1394         val.v.sz.str = CONST_DISCARD(char *, value);
1395         val.v.sz.len = strlen(value)+1;
1396
1397         *err = reg_setvalue(key, name, &val);
1398 }
1399
1400 static WERROR add_share(const char *share_name, const char *path,
1401                         const char *comment, uint32 max_connections,
1402                         const struct nt_user_token *token,
1403                         BOOL is_disk_op)
1404 {
1405         if (lp_add_share_cmd() && *lp_add_share_cmd()) {
1406                 char *command;
1407                 int ret;
1408
1409                 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1410                              lp_add_share_cmd(), dyn_CONFIGFILE, share_name,
1411                              path, comment, max_connections) == -1) {
1412                         return WERR_NOMEM;
1413                 }
1414
1415                 DEBUG(10,("add_share: Running [%s]\n", command ));
1416
1417                 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1418         
1419                 if ( is_disk_op )
1420                         become_root();
1421
1422                 if ( (ret = smbrun(command, NULL)) == 0 ) {
1423                         /* Tell everyone we updated smb.conf. */
1424                         message_send_all(smbd_messaging_context(),
1425                                          MSG_SMB_CONF_UPDATED,
1426                                          NULL, 0, NULL);
1427                 }
1428
1429                 if ( is_disk_op )
1430                         unbecome_root();
1431                 
1432                 /********* END SeDiskOperatorPrivilege BLOCK *********/
1433
1434                 DEBUG(3,("_srv_net_share_add: Running [%s] returned (%d)\n",
1435                          command, ret ));
1436
1437                 /*
1438                  * No fallback to registry shares, the user did define a add
1439                  * share command, so fail here.
1440                  */
1441
1442                 SAFE_FREE(command);
1443                 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1444         }
1445
1446         if (lp_registry_shares()) {
1447                 char *keyname;
1448                 struct registry_key *key;
1449                 enum winreg_CreateAction action;
1450                 WERROR err;
1451                 TALLOC_CTX *mem_ctx;
1452
1453                 if (!(keyname = talloc_asprintf(NULL, "%s\\%s", KEY_SMBCONF,
1454                                                 share_name))) {
1455                         return WERR_NOMEM;
1456                 }
1457
1458                 mem_ctx = (TALLOC_CTX *)keyname;
1459
1460                 err = reg_create_path(mem_ctx, keyname, REG_KEY_WRITE,
1461                                       is_disk_op ? get_root_nt_token():token,
1462                                       &action, &key);
1463
1464                 if (action != REG_CREATED_NEW_KEY) {
1465                         err = WERR_ALREADY_EXISTS;
1466                 }
1467
1468                 if (!W_ERROR_IS_OK(err)) {
1469                         TALLOC_FREE(mem_ctx);
1470                         return err;
1471                 }
1472
1473                 setval_helper(key, "path", path, &err);
1474                 if ((comment != NULL) && (comment[0] != '\0')) {
1475                         setval_helper(key, "comment", comment, &err);
1476                 }
1477                 if (max_connections != 0) {
1478                         char tmp[16];
1479                         snprintf(tmp, sizeof(tmp), "%d", max_connections);
1480                         setval_helper(key, "max connections", tmp, &err);
1481                 }
1482
1483                 if (!W_ERROR_IS_OK(err)) {
1484                         /*
1485                          * Hmmmm. We'd need transactions on the registry to
1486                          * get this right....
1487                          */
1488                         reg_delete_path(is_disk_op ? get_root_nt_token():token,
1489                                         keyname);
1490                 }
1491                 TALLOC_FREE(mem_ctx);
1492                 return err;
1493         }
1494
1495         return WERR_ACCESS_DENIED;
1496 }
1497
1498 static WERROR delete_share(const char *sharename, 
1499                            const struct nt_user_token *token,
1500                            BOOL is_disk_op)
1501 {
1502         if (lp_delete_share_cmd() && *lp_delete_share_cmd()) {
1503                 char *command;
1504                 int ret;
1505
1506                 if (asprintf(&command, "%s \"%s\" \"%s\"",
1507                              lp_delete_share_cmd(), dyn_CONFIGFILE,
1508                              sharename)) {
1509                         return WERR_NOMEM;
1510                 }
1511
1512                 DEBUG(10,("delete_share: Running [%s]\n", command ));
1513
1514                 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1515         
1516                 if ( is_disk_op )
1517                         become_root();
1518
1519                 if ( (ret = smbrun(command, NULL)) == 0 ) {
1520                         /* Tell everyone we updated smb.conf. */
1521                         message_send_all(smbd_messaging_context(),
1522                                          MSG_SMB_CONF_UPDATED,
1523                                          NULL, 0, NULL);
1524                 }
1525
1526                 if ( is_disk_op )
1527                         unbecome_root();
1528
1529                 /********* END SeDiskOperatorPrivilege BLOCK *********/
1530
1531                 SAFE_FREE(command);
1532
1533                 DEBUG(3,("_srv_net_share_del: Running [%s] returned (%d)\n",
1534                          command, ret ));
1535                 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1536         }
1537
1538         if (lp_registry_shares()) {
1539                 char *keyname;
1540                 WERROR err;
1541
1542                 if (asprintf(&keyname, "%s\\%s", KEY_SMBCONF,
1543                              sharename) == -1) {
1544                         return WERR_NOMEM;
1545                 }
1546
1547                 err = reg_delete_path(is_disk_op ? get_root_nt_token():token,
1548                                       keyname);
1549                 SAFE_FREE(keyname);
1550                 return err;
1551         }
1552
1553         return WERR_ACCESS_DENIED;
1554 }
1555
1556 static WERROR change_share(const char *share_name, const char *path,
1557                            const char *comment, uint32 max_connections,
1558                            const struct nt_user_token *token,
1559                            BOOL is_disk_op)
1560 {
1561         if (lp_change_share_cmd() && *lp_change_share_cmd()) {
1562                 char *command;
1563                 int ret;
1564
1565                 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1566                              lp_change_share_cmd(), dyn_CONFIGFILE, share_name,
1567                              path, comment, max_connections) == -1) {
1568                         return WERR_NOMEM;
1569                 }
1570
1571                 DEBUG(10,("_srv_net_share_set_info: Running [%s]\n", command));
1572                                 
1573                 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1574         
1575                 if ( is_disk_op )
1576                         become_root();
1577                         
1578                 if ( (ret = smbrun(command, NULL)) == 0 ) {
1579                         /* Tell everyone we updated smb.conf. */
1580                         message_send_all(smbd_messaging_context(),
1581                                          MSG_SMB_CONF_UPDATED,
1582                                          NULL, 0, NULL);
1583                 }
1584                 
1585                 if ( is_disk_op )
1586                         unbecome_root();
1587                         
1588                 /********* END SeDiskOperatorPrivilege BLOCK *********/
1589
1590                 DEBUG(3,("_srv_net_share_set_info: Running [%s] returned "
1591                          "(%d)\n", command, ret ));
1592
1593                 SAFE_FREE(command);
1594
1595                 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1596         }
1597
1598         if (lp_registry_shares()) {
1599                 char *keyname;
1600                 struct registry_key *key;
1601                 WERROR err;
1602                 TALLOC_CTX *mem_ctx;
1603
1604                 if (!(keyname = talloc_asprintf(NULL, "%s\\%s", KEY_SMBCONF,
1605                                                 share_name))) {
1606                         return WERR_NOMEM;
1607                 }
1608
1609                 mem_ctx = (TALLOC_CTX *)keyname;
1610
1611                 err = reg_open_path(mem_ctx, keyname, REG_KEY_WRITE,
1612                                     is_disk_op ? get_root_nt_token():token,
1613                                     &key);
1614                 if (!W_ERROR_IS_OK(err)) {
1615                         TALLOC_FREE(mem_ctx);
1616                         return err;
1617                 }
1618
1619                 setval_helper(key, "path", path, &err);
1620
1621                 reg_deletevalue(key, "comment");
1622                 if ((comment != NULL) && (comment[0] != '\0')) {
1623                         setval_helper(key, "comment", comment, &err);
1624                 }
1625
1626                 reg_deletevalue(key, "max connections");
1627                 if (max_connections != 0) {
1628                         char tmp[16];
1629                         snprintf(tmp, sizeof(tmp), "%d", max_connections);
1630                         setval_helper(key, "max connections", tmp, &err);
1631                 }
1632
1633                 TALLOC_FREE(mem_ctx);
1634                 return err;
1635         }               
1636
1637         return WERR_ACCESS_DENIED;
1638 }
1639
1640 /*******************************************************************
1641  Net share set info. Modify share details.
1642 ********************************************************************/
1643
1644 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p, struct srvsvc_NetShareSetInfo *r)
1645 {
1646         pstring comment;
1647         pstring pathname;
1648         int type;
1649         int snum;
1650         char *path;
1651         SEC_DESC *psd = NULL;
1652         SE_PRIV se_diskop = SE_DISK_OPERATOR;
1653         BOOL is_disk_op = False;
1654         int max_connections = 0;
1655         fstring tmp_share_name;
1656
1657         DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1658
1659         if (r->out.parm_error) {
1660                 *r->out.parm_error = 0;
1661         }
1662
1663         if ( strequal(r->in.share_name,"IPC$") 
1664                 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1665                 || strequal(r->in.share_name,"global") )
1666         {
1667                 return WERR_ACCESS_DENIED;
1668         }
1669
1670         fstrcpy(tmp_share_name, r->in.share_name);
1671         snum = find_service(tmp_share_name);
1672
1673         /* Does this share exist ? */
1674         if (snum < 0)
1675                 return WERR_NET_NAME_NOT_FOUND;
1676
1677         /* No change to printer shares. */
1678         if (lp_print_ok(snum))
1679                 return WERR_ACCESS_DENIED;
1680
1681         is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1682                                           &se_diskop );
1683         
1684         /* fail out now if you are not root and not a disk op */
1685         
1686         if ( p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
1687                 return WERR_ACCESS_DENIED;
1688
1689         switch (r->in.level) {
1690         case 1:
1691                 pstrcpy(pathname, lp_pathname(snum));
1692                 pstrcpy(comment, r->in.info.info1->comment);
1693                 type = r->in.info.info1->type;
1694                 psd = NULL;
1695                 break;
1696         case 2:
1697                 pstrcpy(comment, r->in.info.info2->comment);
1698                 pstrcpy(pathname, r->in.info.info2->path);
1699                 type = r->in.info.info2->type;
1700                 max_connections = (r->in.info.info2->max_users == 0xffffffff) ?
1701                         0 : r->in.info.info2->max_users;
1702                 psd = NULL;
1703                 break;
1704         case 502:
1705                 pstrcpy(comment, r->in.info.info502->comment);
1706                 pstrcpy(pathname, r->in.info.info502->path);
1707                 type = r->in.info.info502->type;
1708                 psd = r->in.info.info502->sd;
1709                 map_generic_share_sd_bits(psd);
1710                 break;
1711         case 1004:
1712                 pstrcpy(pathname, lp_pathname(snum));
1713                 pstrcpy(comment, r->in.info.info1004->comment);
1714                 type = STYPE_DISKTREE;
1715                 break;
1716         case 1005:
1717                 /* XP re-sets the csc policy even if it wasn't changed by the
1718                    user, so we must compare it to see if it's what is set in
1719                    smb.conf, so that we can contine other ops like setting
1720                    ACLs on a share */
1721                 if (((r->in.info.info1005->dfs_flags &
1722                       SHARE_1005_CSC_POLICY_MASK) >>
1723                      SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1724                         return WERR_OK;
1725                 else {
1726                         DEBUG(3, ("_srv_net_share_set_info: client is trying "
1727                                   "to change csc policy from the network; "
1728                                   "must be done with smb.conf\n"));
1729                         return WERR_ACCESS_DENIED;
1730                 }
1731         case 1006:
1732         case 1007:
1733                 return WERR_ACCESS_DENIED;
1734         case 1501:
1735                 pstrcpy(pathname, lp_pathname(snum));
1736                 pstrcpy(comment, lp_comment(snum));
1737                 psd = r->in.info.info1501->sd;
1738                 map_generic_share_sd_bits(psd);
1739                 type = STYPE_DISKTREE;
1740                 break;
1741         default:
1742                 DEBUG(5,("_srv_net_share_set_info: unsupported switch value "
1743                          "%d\n", r->in.level));
1744                 return WERR_UNKNOWN_LEVEL;
1745         }
1746
1747         /* We can only modify disk shares. */
1748         if (type != STYPE_DISKTREE)
1749                 return WERR_ACCESS_DENIED;
1750                 
1751         /* Check if the pathname is valid. */
1752         if (!(path = valid_share_pathname( pathname )))
1753                 return WERR_OBJECT_PATH_INVALID;
1754
1755         /* Ensure share name, pathname and comment don't contain '"'
1756          * characters. */
1757         string_replace(tmp_share_name, '"', ' ');
1758         string_replace(path, '"', ' ');
1759         string_replace(comment, '"', ' ');
1760
1761         DEBUG(10,("_srv_net_share_set_info: change share command = %s\n",
1762                   lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1763
1764         /* Only call modify function if something changed. */
1765         
1766         if (strcmp(path, lp_pathname(snum))
1767             || strcmp(comment, lp_comment(snum)) 
1768             || (lp_max_connections(snum) != max_connections) ) {
1769                 WERROR err;
1770
1771                 err = change_share(tmp_share_name, path, comment,
1772                                    max_connections, p->pipe_user.nt_user_token,
1773                                    is_disk_op);
1774
1775                 if (!W_ERROR_IS_OK(err)) {
1776                         return err;
1777                 }
1778         }
1779
1780         /* Replace SD if changed. */
1781         if (psd) {
1782                 SEC_DESC *old_sd;
1783                 size_t sd_size;
1784
1785                 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum),
1786                                             &sd_size);
1787
1788                 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1789                         if (!set_share_security(r->in.share_name, psd)) {
1790                                 DEBUG(0,("_srv_net_share_set_info: Failed to "
1791                                          "change security info in share %s.\n",
1792                                          r->in.share_name ));
1793                         }
1794                 }
1795         }
1796                         
1797         DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1798
1799         return WERR_OK;
1800 }
1801
1802
1803 /*******************************************************************
1804  Net share add. Call 'add_share_command "sharename" "pathname" 
1805  "comment" "max connections = "
1806 ********************************************************************/
1807
1808 WERROR _srvsvc_NetShareAdd(pipes_struct *p, struct srvsvc_NetShareAdd *r)
1809 {
1810         pstring share_name;
1811         pstring comment;
1812         pstring pathname;
1813         char *path;
1814         int type;
1815         SEC_DESC *psd = NULL;
1816         SE_PRIV se_diskop = SE_DISK_OPERATOR;
1817         BOOL is_disk_op;
1818         uint32 max_connections = 0;
1819         WERROR err;
1820
1821         DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1822
1823         if (r->out.parm_error) {
1824                 *r->out.parm_error = 0;
1825         }
1826
1827         is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1828                                           &se_diskop );
1829
1830         if (p->pipe_user.ut.uid != sec_initial_uid()  && !is_disk_op ) 
1831                 return WERR_ACCESS_DENIED;
1832
1833         switch (r->in.level) {
1834         case 0:
1835                 /* No path. Not enough info in a level 0 to do anything. */
1836                 return WERR_ACCESS_DENIED;
1837         case 1:
1838                 /* Not enough info in a level 1 to do anything. */
1839                 return WERR_ACCESS_DENIED;
1840         case 2:
1841                 pstrcpy(share_name, r->in.info.info2->name);
1842                 pstrcpy(comment, r->in.info.info2->comment);
1843                 pstrcpy(pathname, r->in.info.info2->path);
1844                 max_connections = (r->in.info.info2->max_users == 0xffffffff) ?
1845                         0 : r->in.info.info2->max_users;
1846                 type = r->in.info.info2->type;
1847                 break;
1848         case 501:
1849                 /* No path. Not enough info in a level 501 to do anything. */
1850                 return WERR_ACCESS_DENIED;
1851         case 502:
1852                 pstrcpy(share_name, r->in.info.info502->name);
1853                 pstrcpy(comment, r->in.info.info502->comment);
1854                 pstrcpy(pathname, r->in.info.info502->path);
1855                 type = r->in.info.info502->type;
1856                 psd = r->in.info.info502->sd;
1857                 map_generic_share_sd_bits(psd);
1858                 break;
1859
1860                 /* none of the following contain share names.  NetShareAdd
1861                  * does not have a separate parameter for the share name */ 
1862
1863         case 1004:
1864         case 1005:
1865         case 1006:
1866         case 1007:
1867                 return WERR_ACCESS_DENIED;
1868         case 1501:
1869                 /* DFS only level. */
1870                 return WERR_ACCESS_DENIED;
1871         default:
1872                 DEBUG(5,("_srv_net_share_add: unsupported switch value %d\n",
1873                          r->in.level));
1874                 return WERR_UNKNOWN_LEVEL;
1875         }
1876
1877         /* check for invalid share names */
1878
1879         if ( !validate_net_name( share_name, INVALID_SHARENAME_CHARS,
1880                                  sizeof(share_name) ) ) {
1881                 DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n",
1882                          share_name));
1883                 return WERR_INVALID_NAME;
1884         }
1885
1886         if ( strequal(share_name,"IPC$") || strequal(share_name,"global")
1887              || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") ) )
1888         {
1889                 return WERR_ACCESS_DENIED;
1890         }
1891
1892         if (get_share_params(p->mem_ctx, share_name) != NULL) {
1893                 /* Share already exists. */
1894                 return WERR_ALREADY_EXISTS;
1895         }
1896
1897         /* We can only add disk shares. */
1898         if (type != STYPE_DISKTREE)
1899                 return WERR_ACCESS_DENIED;
1900                 
1901         /* Check if the pathname is valid. */
1902         if (!(path = valid_share_pathname( pathname )))
1903                 return WERR_OBJECT_PATH_INVALID;
1904
1905         /* Ensure share name, pathname and comment don't contain '"'
1906          * characters. */
1907
1908         string_replace(share_name, '"', ' ');
1909         string_replace(path, '"', ' ');
1910         string_replace(comment, '"', ' ');
1911
1912         err = add_share(share_name, path, comment, max_connections,
1913                         p->pipe_user.nt_user_token, is_disk_op);
1914
1915         if (!W_ERROR_IS_OK(err)) {
1916                 return err;
1917         }
1918
1919         if (psd) {
1920                 if (!set_share_security(share_name, psd)) {
1921                         DEBUG(0,("_srv_net_share_add: Failed to add security "
1922                                  "info to share %s.\n", share_name ));
1923                 }
1924         }
1925
1926         /*
1927          * We don't call reload_services() here, the message will
1928          * cause this to be done before the next packet is read
1929          * from the client. JRA.
1930          */
1931
1932         DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1933
1934         return WERR_OK;
1935 }
1936
1937 /*******************************************************************
1938  Net share delete. Call "delete share command" with the share name as
1939  a parameter.
1940 ********************************************************************/
1941
1942 WERROR _srvsvc_NetShareDel(pipes_struct *p, struct srvsvc_NetShareDel *r)
1943 {
1944         struct share_params *params;
1945         SE_PRIV se_diskop = SE_DISK_OPERATOR;
1946         BOOL is_disk_op;
1947         WERROR err;
1948
1949         DEBUG(5,("_srv_net_share_del: %d\n", __LINE__));
1950
1951         if ( strequal(r->in.share_name, "IPC$") 
1952              || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1953              || strequal(r->in.share_name, "global") )
1954         {
1955                 return WERR_ACCESS_DENIED;
1956         }
1957
1958         if (!(params = get_share_params(p->mem_ctx, r->in.share_name))) {
1959                 return WERR_NO_SUCH_SHARE;
1960         }
1961
1962         /* No change to printer shares. */
1963         if (lp_print_ok(params->service))
1964                 return WERR_ACCESS_DENIED;
1965
1966         is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1967                                           &se_diskop );
1968
1969         if (p->pipe_user.ut.uid != sec_initial_uid()  && !is_disk_op ) 
1970                 return WERR_ACCESS_DENIED;
1971
1972         err = delete_share(lp_servicename(params->service),
1973                            p->pipe_user.nt_user_token, is_disk_op);
1974
1975         if (!W_ERROR_IS_OK(err)) {
1976                 return err;
1977         }
1978
1979         /* Delete the SD in the database. */
1980         delete_share_security(params);
1981
1982         lp_killservice(params->service);
1983
1984         return WERR_OK;
1985 }
1986
1987 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p, struct srvsvc_NetShareDelSticky *r)
1988 {
1989         struct srvsvc_NetShareDel s;
1990
1991         DEBUG(5,("_srv_net_share_del_stick: %d\n", __LINE__));
1992
1993         s.in.server_unc = r->in.server_unc;
1994         s.in.share_name = r->in.share_name;
1995         s.in.reserved = r->in.reserved;
1996
1997         return _srvsvc_NetShareDel(p, &s);
1998 }
1999
2000 /*******************************************************************
2001 time of day
2002 ********************************************************************/
2003
2004 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p, struct srvsvc_NetRemoteTOD *r)
2005 {
2006         struct tm *t;
2007         time_t unixdate = time(NULL);
2008         WERROR status = WERR_OK;
2009
2010         /* We do this call first as if we do it *after* the gmtime call
2011            it overwrites the pointed-to values. JRA */
2012
2013         uint32 zone = get_time_zone(unixdate)/60;
2014
2015         DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
2016
2017         t = gmtime(&unixdate);
2018
2019         /* set up the */
2020         r->out.info->elapsed = unixdate;
2021         r->out.info->msecs = 0;
2022         r->out.info->hours = t->tm_hour;
2023         r->out.info->mins = t->tm_min;
2024         r->out.info->secs = t->tm_sec;
2025         r->out.info->hunds = 0;
2026         r->out.info->timezone = zone;
2027         r->out.info->tinterval = 10000;
2028         r->out.info->day = t->tm_mday;
2029         r->out.info->month = t->tm_mon + 1;
2030         r->out.info->year = 1900+t->tm_year;
2031         r->out.info->weekday = t->tm_wday;
2032         
2033         DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
2034
2035         return status;
2036 }
2037
2038 /***********************************************************************************
2039  Win9x NT tools get security descriptor.
2040 ***********************************************************************************/
2041
2042 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecurity *r)
2043 {
2044         SEC_DESC *psd = NULL;
2045         size_t sd_size;
2046         DATA_BLOB null_pw;
2047         files_struct *fsp = NULL;
2048         SMB_STRUCT_STAT st;
2049         NTSTATUS nt_status;
2050         connection_struct *conn = NULL;
2051         BOOL became_user = False; 
2052         WERROR status = WERR_OK;
2053         pstring tmp_file;
2054
2055         ZERO_STRUCT(st);
2056
2057
2058         /* Null password is ok - we are already an authenticated user... */
2059         null_pw = data_blob_null;
2060
2061         become_root();
2062         conn = make_connection(r->in.share, null_pw, "A:", p->pipe_user.vuid, &nt_status);
2063         unbecome_root();
2064
2065         if (conn == NULL) {
2066                 DEBUG(3,("_srv_net_file_query_secdesc: Unable to connect to %s\n", r->in.share));
2067                 status = ntstatus_to_werror(nt_status);
2068                 goto error_exit;
2069         }
2070
2071         if (!become_user(conn, conn->vuid)) {
2072                 DEBUG(0,("_srv_net_file_query_secdesc: Can't become connected user!\n"));
2073                 status = WERR_ACCESS_DENIED;
2074                 goto error_exit;
2075         }
2076         became_user = True;
2077
2078         pstrcpy(tmp_file, r->in.file);
2079         nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
2080         if (!NT_STATUS_IS_OK(nt_status)) {
2081                 DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", r->in.file));
2082                 status = WERR_ACCESS_DENIED;
2083                 goto error_exit;
2084         }
2085
2086         nt_status = check_name(conn, r->in.file);
2087         if (!NT_STATUS_IS_OK(nt_status)) {
2088                 DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", r->in.file));
2089                 status = WERR_ACCESS_DENIED;
2090                 goto error_exit;
2091         }
2092
2093         nt_status = open_file_stat(conn, r->in.file, &st, &fsp);
2094         if (!NT_STATUS_IS_OK(nt_status)) {
2095                 /* Perhaps it is a directory */
2096                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2097                         nt_status = open_directory(conn, r->in.file, &st,
2098                                         READ_CONTROL_ACCESS,
2099                                         FILE_SHARE_READ|FILE_SHARE_WRITE,
2100                                         FILE_OPEN,
2101                                         0,
2102                                         FILE_ATTRIBUTE_DIRECTORY,
2103                                         NULL, &fsp);
2104
2105                 if (!NT_STATUS_IS_OK(nt_status)) {
2106                         DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", r->in.file));
2107                         status = WERR_ACCESS_DENIED;
2108                         goto error_exit;
2109                 }
2110         }
2111
2112         sd_size = SMB_VFS_GET_NT_ACL(fsp, fsp->fsp_name, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
2113
2114         if (sd_size == 0) {
2115                 DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", r->in.file));
2116                 status = WERR_ACCESS_DENIED;
2117                 goto error_exit;
2118         }
2119
2120         r->out.sd_buf->sd_size= sd_size;
2121         r->out.sd_buf->sd = psd;
2122
2123         psd->dacl->revision = (uint16) NT4_ACL_REVISION;
2124
2125         close_file(fsp, NORMAL_CLOSE);
2126         unbecome_user();
2127         close_cnum(conn, p->pipe_user.vuid);
2128         return status;
2129
2130 error_exit:
2131
2132         if(fsp) {
2133                 close_file(fsp, NORMAL_CLOSE);
2134         }
2135
2136         if (became_user)
2137                 unbecome_user();
2138
2139         if (conn) 
2140                 close_cnum(conn, p->pipe_user.vuid);
2141
2142         return status;
2143 }
2144
2145 /***********************************************************************************
2146  Win9x NT tools set security descriptor.
2147 ***********************************************************************************/
2148
2149 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecurity *r)
2150 {
2151         BOOL ret;
2152         DATA_BLOB null_pw;
2153         files_struct *fsp = NULL;
2154         SMB_STRUCT_STAT st;
2155         NTSTATUS nt_status;
2156         connection_struct *conn = NULL;
2157         BOOL became_user = False;
2158         WERROR status = WERR_OK;
2159         pstring tmp_file;
2160
2161         ZERO_STRUCT(st);
2162
2163         /* Null password is ok - we are already an authenticated user... */
2164         null_pw = data_blob_null;
2165
2166         become_root();
2167         conn = make_connection(r->in.share, null_pw, "A:", p->pipe_user.vuid, &nt_status);
2168         unbecome_root();
2169
2170         if (conn == NULL) {
2171                 DEBUG(3,("_srv_net_file_set_secdesc: Unable to connect to %s\n", r->in.share));
2172                 status = ntstatus_to_werror(nt_status);
2173                 goto error_exit;
2174         }
2175
2176         if (!become_user(conn, conn->vuid)) {
2177                 DEBUG(0,("_srv_net_file_set_secdesc: Can't become connected user!\n"));
2178                 status = WERR_ACCESS_DENIED;
2179                 goto error_exit;
2180         }
2181         became_user = True;
2182
2183         pstrcpy(tmp_file, r->in.file);
2184         nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
2185         if (!NT_STATUS_IS_OK(nt_status)) {
2186                 DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", r->in.file));
2187                 status = WERR_ACCESS_DENIED;
2188                 goto error_exit;
2189         }
2190
2191         nt_status = check_name(conn, r->in.file);
2192         if (!NT_STATUS_IS_OK(nt_status)) {
2193                 DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", r->in.file));
2194                 status = WERR_ACCESS_DENIED;
2195                 goto error_exit;
2196         }
2197
2198
2199         nt_status = open_file_stat(conn, r->in.file, &st, &fsp);
2200
2201         if (!NT_STATUS_IS_OK(nt_status)) {
2202                 /* Perhaps it is a directory */
2203                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2204                         nt_status = open_directory(conn, r->in.file, &st,
2205                                                 FILE_READ_ATTRIBUTES,
2206                                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
2207                                                 FILE_OPEN,
2208                                                 0,
2209                                                 FILE_ATTRIBUTE_DIRECTORY,
2210                                                 NULL, &fsp);
2211
2212                 if (!NT_STATUS_IS_OK(nt_status)) {
2213                         DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", r->in.file));
2214                         status = WERR_ACCESS_DENIED;
2215                         goto error_exit;
2216                 }
2217         }
2218
2219         ret = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, r->in.securityinformation, r->in.sd_buf.sd);
2220
2221         if (ret == False) {
2222                 DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", r->in.file));
2223                 status = WERR_ACCESS_DENIED;
2224                 goto error_exit;
2225         }
2226
2227         close_file(fsp, NORMAL_CLOSE);
2228         unbecome_user();
2229         close_cnum(conn, p->pipe_user.vuid);
2230         return status;
2231
2232 error_exit:
2233
2234         if(fsp) {
2235                 close_file(fsp, NORMAL_CLOSE);
2236         }
2237
2238         if (became_user) {
2239                 unbecome_user();
2240         }
2241
2242         if (conn) {
2243                 close_cnum(conn, p->pipe_user.vuid);
2244         }
2245
2246         return status;
2247 }
2248
2249 /***********************************************************************************
2250  It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2251  We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2252  These disks would the disks listed by this function.
2253  Users could then create shares relative to these disks.  Watch out for moving these disks around.
2254  "Nigel Williams" <nigel@veritas.com>.
2255 ***********************************************************************************/
2256
2257 static const char *server_disks[] = {"C:"};
2258
2259 static uint32 get_server_disk_count(void)
2260 {
2261         return sizeof(server_disks)/sizeof(server_disks[0]);
2262 }
2263
2264 static uint32 init_server_disk_enum(uint32 *resume)
2265 {
2266         uint32 server_disk_count = get_server_disk_count();
2267
2268         /*resume can be an offset into the list for now*/
2269
2270         if(*resume & 0x80000000)
2271                 *resume = 0;
2272
2273         if(*resume > server_disk_count)
2274                 *resume = server_disk_count;
2275
2276         return server_disk_count - *resume;
2277 }
2278
2279 static const char *next_server_disk_enum(uint32 *resume)
2280 {
2281         const char *disk;
2282
2283         if(init_server_disk_enum(resume) == 0)
2284                 return NULL;
2285
2286         disk = server_disks[*resume];
2287
2288         (*resume)++;
2289
2290         DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2291
2292         return disk;
2293 }
2294
2295 WERROR _srvsvc_NetDiskEnum(pipes_struct *p, struct srvsvc_NetDiskEnum *r)
2296 {
2297         uint32 i;
2298         const char *disk_name;
2299
2300         WERROR status = WERR_OK;
2301
2302         *r->out.totalentries = init_server_disk_enum(r->in.resume_handle);
2303         r->out.info->count = 0;
2304
2305         if(!(r->out.info->disks =  TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetDiskInfo0, MAX_SERVER_DISK_ENTRIES))) {
2306                 return WERR_NOMEM;
2307         }
2308
2309         /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2310
2311         for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(r->in.resume_handle)); i++) {
2312
2313                 r->out.info->count++;
2314                 (*r->out.totalentries)++;
2315
2316                 /*copy disk name into a unicode string*/
2317
2318                 r->out.info->disks[i].disk = disk_name; 
2319         }
2320
2321         /* add a terminating null string.  Is this there if there is more data to come? */
2322
2323         r->out.info->count++;
2324         (*r->out.totalentries)++;
2325
2326         r->out.info->disks[i].disk = "";
2327
2328         return status;
2329 }
2330
2331 /********************************************************************
2332 ********************************************************************/
2333
2334 WERROR _srvsvc_NetNameValidate(pipes_struct *p, struct srvsvc_NetNameValidate *r)
2335 {
2336         int len;
2337
2338         if ((r->in.flags != 0x0) && (r->in.flags != 0x80000000)) {
2339                 return WERR_INVALID_PARAM;
2340         }
2341
2342         switch ( r->in.name_type ) {
2343         case 0x9:
2344                 len = strlen_m(r->in.name);
2345
2346                 if ((r->in.flags == 0x0) && (len > 81)) {
2347                         DEBUG(5,("_srv_net_name_validate: share name too long (%s > 81 chars)\n", r->in.name));
2348                         return WERR_INVALID_NAME;
2349                 }
2350                 if ((r->in.flags == 0x80000000) && (len > 13)) {
2351                         DEBUG(5,("_srv_net_name_validate: share name too long (%s > 13 chars)\n", r->in.name));
2352                         return WERR_INVALID_NAME;
2353                 }
2354
2355                 if ( ! validate_net_name( r->in.name, INVALID_SHARENAME_CHARS, sizeof(r->in.name) ) ) {
2356                         DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", r->in.name));
2357                         return WERR_INVALID_NAME;
2358                 }
2359                 break;
2360
2361         default:
2362                 return WERR_UNKNOWN_LEVEL;
2363         }
2364
2365         return WERR_OK;
2366 }
2367
2368
2369 /********************************************************************
2370 ********************************************************************/
2371
2372 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2373 {
2374         return WERR_ACCESS_DENIED;
2375 }
2376
2377 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2378 {
2379         p->rng_fault_state = True;
2380         return WERR_NOT_SUPPORTED;
2381 }
2382
2383 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2384 {
2385         p->rng_fault_state = True;
2386         return WERR_NOT_SUPPORTED;
2387 }
2388
2389 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2390 {
2391         p->rng_fault_state = True;
2392         return WERR_NOT_SUPPORTED;
2393 }
2394
2395 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2396 {
2397         p->rng_fault_state = True;
2398         return WERR_NOT_SUPPORTED;
2399 }
2400
2401 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2402 {
2403         p->rng_fault_state = True;
2404         return WERR_NOT_SUPPORTED;
2405 }
2406
2407 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2408 {
2409         p->rng_fault_state = True;
2410         return WERR_NOT_SUPPORTED;
2411 }
2412
2413 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2414 {
2415         p->rng_fault_state = True;
2416         return WERR_NOT_SUPPORTED;
2417 }
2418
2419 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2420 {
2421         p->rng_fault_state = True;
2422         return WERR_NOT_SUPPORTED;
2423 }
2424
2425 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2426 {
2427         p->rng_fault_state = True;
2428         return WERR_NOT_SUPPORTED;
2429 }
2430
2431 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2432 {
2433         p->rng_fault_state = True;
2434         return WERR_NOT_SUPPORTED;
2435 }
2436
2437 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2438 {
2439         p->rng_fault_state = True;
2440         return WERR_NOT_SUPPORTED;
2441 }
2442
2443 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2444 {
2445         p->rng_fault_state = True;
2446         return WERR_NOT_SUPPORTED;
2447 }
2448
2449 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2450 {
2451         p->rng_fault_state = True;
2452         return WERR_NOT_SUPPORTED;
2453 }
2454
2455 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2456 {
2457         p->rng_fault_state = True;
2458         return WERR_NOT_SUPPORTED;
2459 }
2460
2461 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2462 {
2463         p->rng_fault_state = True;
2464         return WERR_NOT_SUPPORTED;
2465 }
2466
2467 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2468 {
2469         p->rng_fault_state = True;
2470         return WERR_NOT_SUPPORTED;
2471 }
2472
2473 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2474 {
2475         p->rng_fault_state = True;
2476         return WERR_NOT_SUPPORTED;
2477 }
2478
2479 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2480 {
2481         p->rng_fault_state = True;
2482         return WERR_NOT_SUPPORTED;
2483 }
2484
2485 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2486 {
2487         p->rng_fault_state = True;
2488         return WERR_NOT_SUPPORTED;
2489 }
2490
2491 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2492 {
2493         p->rng_fault_state = True;
2494         return WERR_NOT_SUPPORTED;
2495 }
2496
2497 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2498 {
2499         p->rng_fault_state = True;
2500         return WERR_NOT_SUPPORTED;
2501 }
2502
2503 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2504 {
2505         p->rng_fault_state = True;
2506         return WERR_NOT_SUPPORTED;
2507 }
2508
2509 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2510 {
2511         p->rng_fault_state = True;
2512         return WERR_NOT_SUPPORTED;
2513 }
2514
2515 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2516 {
2517         p->rng_fault_state = True;
2518         return WERR_NOT_SUPPORTED;
2519 }
2520
2521 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2522 {
2523         p->rng_fault_state = True;
2524         return WERR_NOT_SUPPORTED;
2525 }
2526
2527 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2528 {
2529         p->rng_fault_state = True;
2530         return WERR_NOT_SUPPORTED;
2531 }
2532
2533 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2534 {
2535         p->rng_fault_state = True;
2536         return WERR_NOT_SUPPORTED;
2537 }
2538
2539 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *R)
2540 {
2541         p->rng_fault_state = True;
2542         return WERR_NOT_SUPPORTED;
2543 }
2544
2545 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2546 {
2547         p->rng_fault_state = True;
2548         return WERR_NOT_SUPPORTED;
2549 }
2550
2551 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2552 {
2553         p->rng_fault_state = True;
2554         return WERR_NOT_SUPPORTED;
2555 }
2556
2557 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2558 {
2559         p->rng_fault_state = True;
2560         return WERR_NOT_SUPPORTED;
2561 }
2562
2563 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2564 {
2565         p->rng_fault_state = True;
2566         return WERR_NOT_SUPPORTED;
2567 }
2568
2569 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2570 {
2571         p->rng_fault_state = True;
2572         return WERR_NOT_SUPPORTED;
2573 }
2574
2575 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2576 {
2577         p->rng_fault_state = True;
2578         return WERR_NOT_SUPPORTED;
2579 }
2580
2581 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2582 {
2583         p->rng_fault_state = True;
2584         return WERR_NOT_SUPPORTED;
2585 }