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