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