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