r23801: The FSF has moved around a lot. This fixes their Mass Ave address.
[gd/samba/.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         TALLOC_CTX *ctx = get_talloc_ctx();
1053         WERROR status;
1054
1055         /* TODO -- Windows enumerates 
1056            (b) active pipes
1057            (c) open directories and files */
1058
1059         ctr->ctr3 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetFileCtr3);
1060         
1061         status = net_enum_files( ctx, &ctr->ctr3->array, num_entries, resume_hnd );
1062         if ( !W_ERROR_IS_OK(status))
1063                 return status;
1064                 
1065         status = net_enum_pipes( ctx, &ctr->ctr3->array, num_entries, resume_hnd );
1066         if ( !W_ERROR_IS_OK(status))
1067                 return status;
1068
1069         ctr->ctr3->count = *num_entries;
1070         
1071         return WERR_OK;
1072 }
1073
1074 /*******************************************************************
1075 *******************************************************************/
1076
1077 WERROR _srvsvc_NetFileEnum(pipes_struct *p, struct srvsvc_NetFileEnum *r)
1078 {
1079         switch ( *r->in.level ) {
1080         case 3:
1081                 return net_file_enum_3(p, r->in.ctr, r->in.resume_handle, r->out.totalentries );        
1082         default:
1083                 return WERR_UNKNOWN_LEVEL;
1084         }
1085         
1086         return WERR_OK;
1087 }
1088
1089 /*******************************************************************
1090 net server get info
1091 ********************************************************************/
1092
1093 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p, struct srvsvc_NetSrvGetInfo *r)
1094 {
1095         WERROR status = WERR_OK;
1096
1097         ZERO_STRUCTP(r->out.info);
1098
1099         DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1100
1101         if (!pipe_access_check(p)) {
1102                 DEBUG(3, ("access denied to srv_net_srv_get_info\n"));
1103                 return WERR_ACCESS_DENIED;
1104         }
1105
1106         switch (r->in.level) {
1107
1108                 /* Technically level 102 should only be available to
1109                    Administrators but there isn't anything super-secret
1110                    here, as most of it is made up. */
1111
1112         case 102:
1113                 r->out.info->info102 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1114
1115                 r->out.info->info102->platform_id = 500;
1116                 r->out.info->info102->version_major = lp_major_announce_version();
1117                 r->out.info->info102->version_minor = lp_minor_announce_version();
1118                 r->out.info->info102->server_name = global_myname(); 
1119                 r->out.info->info102->server_type = lp_default_server_announce();
1120                 r->out.info->info102->userpath = "C:\\";
1121                 r->out.info->info102->licenses = 10000;
1122                 r->out.info->info102->anndelta = 3000;
1123                 r->out.info->info102->disc = 0xf;
1124                 r->out.info->info102->users = 0xffffffff;
1125                 r->out.info->info102->hidden = 0;
1126                 r->out.info->info102->announce = 240;
1127                 r->out.info->info102->comment = lp_serverstring();
1128                 break;
1129         case 101:
1130                 r->out.info->info101 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1131                         r->out.info->info101->platform_id = 500;
1132                         r->out.info->info101->server_name = global_myname();
1133                         r->out.info->info101->version_major = lp_major_announce_version();
1134                         r->out.info->info101->version_minor = lp_minor_announce_version();
1135                         r->out.info->info101->server_type = lp_default_server_announce();
1136                         r->out.info->info101->comment = lp_serverstring();
1137                 break;
1138         case 100:
1139                 r->out.info->info100 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1140                 r->out.info->info100->platform_id = 500;
1141                 r->out.info->info100->server_name = global_myname();
1142                 break;
1143         default:
1144                 return WERR_UNKNOWN_LEVEL;
1145                 break;
1146         }
1147
1148         DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1149
1150         return status;
1151 }
1152
1153 /*******************************************************************
1154 net server set info
1155 ********************************************************************/
1156
1157 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p, struct srvsvc_NetSrvSetInfo *r)
1158 {
1159         /* Set up the net server set info structure. */
1160         if (r->out.parm_error) {
1161                 *r->out.parm_error = 0;
1162         }
1163         return WERR_OK;
1164 }
1165
1166 /*******************************************************************
1167 net conn enum
1168 ********************************************************************/
1169
1170 WERROR _srvsvc_NetConnEnum(pipes_struct *p, struct srvsvc_NetConnEnum *r)
1171 {
1172         DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
1173
1174         ZERO_STRUCTP(r->out.ctr);
1175
1176         /* set up the */
1177         return init_srv_conn_info_ctr(p, r->out.ctr, *r->in.level, r->in.resume_handle, r->out.totalentries);
1178 }
1179
1180 /*******************************************************************
1181 net sess enum
1182 ********************************************************************/
1183
1184 WERROR _srvsvc_NetSessEnum(pipes_struct *p, struct srvsvc_NetSessEnum *r)
1185 {
1186         DEBUG(5,("_srv_net_sess_enum: %d\n", __LINE__));
1187
1188         ZERO_STRUCTP(r->out.ctr);
1189
1190         /* set up the */
1191         return init_srv_sess_info_ctr(p, r->out.ctr,
1192                                 *r->in.level, 
1193                                 r->in.resume_handle,
1194                                 r->out.totalentries);
1195 }
1196
1197 /*******************************************************************
1198 net sess del
1199 ********************************************************************/
1200
1201 WERROR _srvsvc_NetSessDel(pipes_struct *p, struct srvsvc_NetSessDel *r)
1202 {
1203         struct sessionid *session_list;
1204         int num_sessions, snum;
1205         WERROR status;
1206
1207         char *machine = talloc_strdup(p->mem_ctx, r->in.server_unc);
1208
1209         /* strip leading backslashes if any */
1210         while (machine[0] == '\\') {
1211                 memmove(machine, &machine[1], strlen(machine));
1212         }
1213
1214         num_sessions = list_sessions(p->mem_ctx, &session_list);
1215
1216         DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
1217
1218         status = WERR_ACCESS_DENIED;
1219
1220         /* fail out now if you are not root or not a domain admin */
1221
1222         if ((p->pipe_user.ut.uid != sec_initial_uid()) && 
1223                 ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
1224
1225                 goto done;
1226         }
1227
1228         for (snum = 0; snum < num_sessions; snum++) {
1229
1230                 if ((strequal(session_list[snum].username, r->in.user) || r->in.user[0] == '\0' ) &&
1231                      strequal(session_list[snum].remote_machine, machine)) {
1232                         NTSTATUS ntstat;
1233
1234                         ntstat = messaging_send(smbd_messaging_context(),
1235                                                 session_list[snum].pid,
1236                                                 MSG_SHUTDOWN, &data_blob_null);
1237                 
1238                         if (NT_STATUS_IS_OK(ntstat))
1239                                 status = WERR_OK;
1240                 }
1241         }
1242
1243         DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
1244
1245 done:
1246         return status;
1247 }
1248
1249 /*******************************************************************
1250  Net share enum all.
1251 ********************************************************************/
1252
1253 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p, struct srvsvc_NetShareEnumAll *r)
1254 {
1255         DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1256
1257         if (!pipe_access_check(p)) {
1258                 DEBUG(3, ("access denied to srv_net_share_enum_all\n"));
1259                 return WERR_ACCESS_DENIED;
1260         }
1261
1262         /* Create the list of shares for the response. */
1263         return init_srv_share_info_ctr(p, r->out.ctr, *r->in.level,
1264                                               r->in.resume_handle, r->out.totalentries, True);
1265 }
1266
1267 /*******************************************************************
1268  Net share enum.
1269 ********************************************************************/
1270
1271 WERROR _srvsvc_NetShareEnum(pipes_struct *p, struct srvsvc_NetShareEnum *r)
1272 {
1273         DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1274
1275         if (!pipe_access_check(p)) {
1276                 DEBUG(3, ("access denied to srv_net_share_enum\n"));
1277                 return WERR_ACCESS_DENIED;
1278         }
1279
1280         /* Create the list of shares for the response. */
1281         return init_srv_share_info_ctr(p, r->out.ctr, *r->in.level,
1282                                               r->in.resume_handle, r->out.totalentries, False);
1283 }
1284
1285 /*******************************************************************
1286  Net share get info.
1287 ********************************************************************/
1288
1289 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p, struct srvsvc_NetShareGetInfo *r)
1290 {
1291         const struct share_params *params;
1292
1293         params = get_share_params(p->mem_ctx, r->in.share_name);
1294
1295         if (params != NULL) {
1296                 switch (r->in.level) {
1297                 case 0:
1298                         r->out.info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1299                         init_srv_share_info_0(p, r->out.info->info0, params);
1300                         break;
1301                 case 1:
1302                         r->out.info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1303                         init_srv_share_info_1(p, r->out.info->info1, params);
1304                         break;
1305                 case 2:
1306                         r->out.info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1307                         init_srv_share_info_2(p, r->out.info->info2, params);
1308                         break;
1309                 case 501:
1310                         r->out.info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1311                         init_srv_share_info_501(p, r->out.info->info501, params);
1312                         break;
1313                 case 502:
1314                         r->out.info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1315                         init_srv_share_info_502(p, r->out.info->info502, params);
1316                         break;
1317
1318                         /* here for completeness */
1319                 case 1004:
1320                         r->out.info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1321                         init_srv_share_info_1004(p, r->out.info->info1004, params);
1322                         break;
1323                 case 1005:
1324                         r->out.info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1325                         init_srv_share_info_1005(p, r->out.info->info1005, params);
1326                         break;
1327
1328                         /* here for completeness 1006 - 1501 */
1329                 case 1006:
1330                         r->out.info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1331                         init_srv_share_info_1006(p, r->out.info->info1006,
1332                                                  params);
1333                         break;
1334                 case 1007:
1335                         r->out.info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1336                         init_srv_share_info_1007(p, r->out.info->info1007,
1337                                                  params);
1338                         break;
1339                 case 1501:
1340                         r->out.info->info1501 = talloc(p->mem_ctx, struct sec_desc_buf);
1341                         init_srv_share_info_1501(p, r->out.info->info1501,
1342                                                  params);
1343                         break;
1344                 default:
1345                         DEBUG(5,("init_srv_net_share_get_info: unsupported "
1346                                  "switch value %d\n", r->in.level));
1347                         return WERR_UNKNOWN_LEVEL;
1348                         break;
1349                 }
1350         } else {
1351                 return WERR_INVALID_NAME;
1352         }
1353
1354         return WERR_OK;
1355 }
1356
1357 /*******************************************************************
1358  Check a given DOS pathname is valid for a share.
1359 ********************************************************************/
1360
1361 char *valid_share_pathname(char *dos_pathname)
1362 {
1363         char *ptr;
1364
1365         /* Convert any '\' paths to '/' */
1366         unix_format(dos_pathname);
1367         unix_clean_name(dos_pathname);
1368
1369         /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1370         ptr = dos_pathname;
1371         if (strlen(dos_pathname) > 2 && ptr[1] == ':' && ptr[0] != '/')
1372                 ptr += 2;
1373
1374         /* Only absolute paths allowed. */
1375         if (*ptr != '/')
1376                 return NULL;
1377
1378         return ptr;
1379 }
1380
1381 static void setval_helper(struct registry_key *key, const char *name,
1382                           const char *value, WERROR *err)
1383 {
1384         struct registry_value val;
1385
1386         if (!W_ERROR_IS_OK(*err)) {
1387                 return;
1388         }
1389
1390         ZERO_STRUCT(val);
1391         val.type = REG_SZ;
1392         val.v.sz.str = CONST_DISCARD(char *, value);
1393         val.v.sz.len = strlen(value)+1;
1394
1395         *err = reg_setvalue(key, name, &val);
1396 }
1397
1398 static WERROR add_share(const char *share_name, const char *path,
1399                         const char *comment, uint32 max_connections,
1400                         const struct nt_user_token *token,
1401                         BOOL is_disk_op)
1402 {
1403         if (lp_add_share_cmd() && *lp_add_share_cmd()) {
1404                 char *command;
1405                 int ret;
1406
1407                 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1408                              lp_add_share_cmd(), dyn_CONFIGFILE, share_name,
1409                              path, comment, max_connections) == -1) {
1410                         return WERR_NOMEM;
1411                 }
1412
1413                 DEBUG(10,("add_share: Running [%s]\n", command ));
1414
1415                 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1416         
1417                 if ( is_disk_op )
1418                         become_root();
1419
1420                 if ( (ret = smbrun(command, NULL)) == 0 ) {
1421                         /* Tell everyone we updated smb.conf. */
1422                         message_send_all(smbd_messaging_context(),
1423                                          MSG_SMB_CONF_UPDATED,
1424                                          NULL, 0, NULL);
1425                 }
1426
1427                 if ( is_disk_op )
1428                         unbecome_root();
1429                 
1430                 /********* END SeDiskOperatorPrivilege BLOCK *********/
1431
1432                 DEBUG(3,("_srv_net_share_add: Running [%s] returned (%d)\n",
1433                          command, ret ));
1434
1435                 /*
1436                  * No fallback to registry shares, the user did define a add
1437                  * share command, so fail here.
1438                  */
1439
1440                 SAFE_FREE(command);
1441                 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1442         }
1443
1444         if (lp_registry_shares()) {
1445                 char *keyname;
1446                 struct registry_key *key;
1447                 enum winreg_CreateAction action;
1448                 WERROR err;
1449                 TALLOC_CTX *mem_ctx;
1450
1451                 if (!(keyname = talloc_asprintf(NULL, "%s\\%s", KEY_SMBCONF,
1452                                                 share_name))) {
1453                         return WERR_NOMEM;
1454                 }
1455
1456                 mem_ctx = (TALLOC_CTX *)keyname;
1457
1458                 err = reg_create_path(mem_ctx, keyname, REG_KEY_WRITE,
1459                                       is_disk_op ? get_root_nt_token():token,
1460                                       &action, &key);
1461
1462                 if (action != REG_CREATED_NEW_KEY) {
1463                         err = WERR_ALREADY_EXISTS;
1464                 }
1465
1466                 if (!W_ERROR_IS_OK(err)) {
1467                         TALLOC_FREE(mem_ctx);
1468                         return err;
1469                 }
1470
1471                 setval_helper(key, "path", path, &err);
1472                 if ((comment != NULL) && (comment[0] != '\0')) {
1473                         setval_helper(key, "comment", comment, &err);
1474                 }
1475                 if (max_connections != 0) {
1476                         char tmp[16];
1477                         snprintf(tmp, sizeof(tmp), "%d", max_connections);
1478                         setval_helper(key, "max connections", tmp, &err);
1479                 }
1480
1481                 if (!W_ERROR_IS_OK(err)) {
1482                         /*
1483                          * Hmmmm. We'd need transactions on the registry to
1484                          * get this right....
1485                          */
1486                         reg_delete_path(is_disk_op ? get_root_nt_token():token,
1487                                         keyname);
1488                 }
1489                 TALLOC_FREE(mem_ctx);
1490                 return err;
1491         }
1492
1493         return WERR_ACCESS_DENIED;
1494 }
1495
1496 static WERROR delete_share(const char *sharename, 
1497                            const struct nt_user_token *token,
1498                            BOOL is_disk_op)
1499 {
1500         if (lp_delete_share_cmd() && *lp_delete_share_cmd()) {
1501                 char *command;
1502                 int ret;
1503
1504                 if (asprintf(&command, "%s \"%s\" \"%s\"",
1505                              lp_delete_share_cmd(), dyn_CONFIGFILE,
1506                              sharename)) {
1507                         return WERR_NOMEM;
1508                 }
1509
1510                 DEBUG(10,("delete_share: Running [%s]\n", command ));
1511
1512                 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1513         
1514                 if ( is_disk_op )
1515                         become_root();
1516
1517                 if ( (ret = smbrun(command, NULL)) == 0 ) {
1518                         /* Tell everyone we updated smb.conf. */
1519                         message_send_all(smbd_messaging_context(),
1520                                          MSG_SMB_CONF_UPDATED,
1521                                          NULL, 0, NULL);
1522                 }
1523
1524                 if ( is_disk_op )
1525                         unbecome_root();
1526
1527                 /********* END SeDiskOperatorPrivilege BLOCK *********/
1528
1529                 SAFE_FREE(command);
1530
1531                 DEBUG(3,("_srv_net_share_del: Running [%s] returned (%d)\n",
1532                          command, ret ));
1533                 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1534         }
1535
1536         if (lp_registry_shares()) {
1537                 char *keyname;
1538                 WERROR err;
1539
1540                 if (asprintf(&keyname, "%s\\%s", KEY_SMBCONF,
1541                              sharename) == -1) {
1542                         return WERR_NOMEM;
1543                 }
1544
1545                 err = reg_delete_path(is_disk_op ? get_root_nt_token():token,
1546                                       keyname);
1547                 SAFE_FREE(keyname);
1548                 return err;
1549         }
1550
1551         return WERR_ACCESS_DENIED;
1552 }
1553
1554 static WERROR change_share(const char *share_name, const char *path,
1555                            const char *comment, uint32 max_connections,
1556                            const struct nt_user_token *token,
1557                            BOOL is_disk_op)
1558 {
1559         if (lp_change_share_cmd() && *lp_change_share_cmd()) {
1560                 char *command;
1561                 int ret;
1562
1563                 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1564                              lp_change_share_cmd(), dyn_CONFIGFILE, share_name,
1565                              path, comment, max_connections) == -1) {
1566                         return WERR_NOMEM;
1567                 }
1568
1569                 DEBUG(10,("_srv_net_share_set_info: Running [%s]\n", command));
1570                                 
1571                 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1572         
1573                 if ( is_disk_op )
1574                         become_root();
1575                         
1576                 if ( (ret = smbrun(command, NULL)) == 0 ) {
1577                         /* Tell everyone we updated smb.conf. */
1578                         message_send_all(smbd_messaging_context(),
1579                                          MSG_SMB_CONF_UPDATED,
1580                                          NULL, 0, NULL);
1581                 }
1582                 
1583                 if ( is_disk_op )
1584                         unbecome_root();
1585                         
1586                 /********* END SeDiskOperatorPrivilege BLOCK *********/
1587
1588                 DEBUG(3,("_srv_net_share_set_info: Running [%s] returned "
1589                          "(%d)\n", command, ret ));
1590
1591                 SAFE_FREE(command);
1592
1593                 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1594         }
1595
1596         if (lp_registry_shares()) {
1597                 char *keyname;
1598                 struct registry_key *key;
1599                 WERROR err;
1600                 TALLOC_CTX *mem_ctx;
1601
1602                 if (!(keyname = talloc_asprintf(NULL, "%s\\%s", KEY_SMBCONF,
1603                                                 share_name))) {
1604                         return WERR_NOMEM;
1605                 }
1606
1607                 mem_ctx = (TALLOC_CTX *)keyname;
1608
1609                 err = reg_open_path(mem_ctx, keyname, REG_KEY_WRITE,
1610                                     is_disk_op ? get_root_nt_token():token,
1611                                     &key);
1612                 if (!W_ERROR_IS_OK(err)) {
1613                         TALLOC_FREE(mem_ctx);
1614                         return err;
1615                 }
1616
1617                 setval_helper(key, "path", path, &err);
1618
1619                 reg_deletevalue(key, "comment");
1620                 if ((comment != NULL) && (comment[0] != '\0')) {
1621                         setval_helper(key, "comment", comment, &err);
1622                 }
1623
1624                 reg_deletevalue(key, "max connections");
1625                 if (max_connections != 0) {
1626                         char tmp[16];
1627                         snprintf(tmp, sizeof(tmp), "%d", max_connections);
1628                         setval_helper(key, "max connections", tmp, &err);
1629                 }
1630
1631                 TALLOC_FREE(mem_ctx);
1632                 return err;
1633         }               
1634
1635         return WERR_ACCESS_DENIED;
1636 }
1637
1638 /*******************************************************************
1639  Net share set info. Modify share details.
1640 ********************************************************************/
1641
1642 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p, struct srvsvc_NetShareSetInfo *r)
1643 {
1644         pstring comment;
1645         pstring pathname;
1646         int type;
1647         int snum;
1648         char *path;
1649         SEC_DESC *psd = NULL;
1650         SE_PRIV se_diskop = SE_DISK_OPERATOR;
1651         BOOL is_disk_op = False;
1652         int max_connections = 0;
1653         fstring tmp_share_name;
1654
1655         DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1656
1657         if (r->out.parm_error) {
1658                 *r->out.parm_error = 0;
1659         }
1660
1661         if ( strequal(r->in.share_name,"IPC$") 
1662                 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1663                 || strequal(r->in.share_name,"global") )
1664         {
1665                 return WERR_ACCESS_DENIED;
1666         }
1667
1668         fstrcpy(tmp_share_name, r->in.share_name);
1669         snum = find_service(tmp_share_name);
1670
1671         /* Does this share exist ? */
1672         if (snum < 0)
1673                 return WERR_NET_NAME_NOT_FOUND;
1674
1675         /* No change to printer shares. */
1676         if (lp_print_ok(snum))
1677                 return WERR_ACCESS_DENIED;
1678
1679         is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1680                                           &se_diskop );
1681         
1682         /* fail out now if you are not root and not a disk op */
1683         
1684         if ( p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
1685                 return WERR_ACCESS_DENIED;
1686
1687         switch (r->in.level) {
1688         case 1:
1689                 pstrcpy(pathname, lp_pathname(snum));
1690                 pstrcpy(comment, r->in.info.info1->comment);
1691                 type = r->in.info.info1->type;
1692                 psd = NULL;
1693                 break;
1694         case 2:
1695                 pstrcpy(comment, r->in.info.info2->comment);
1696                 pstrcpy(pathname, r->in.info.info2->path);
1697                 type = r->in.info.info2->type;
1698                 max_connections = (r->in.info.info2->max_users == 0xffffffff) ?
1699                         0 : r->in.info.info2->max_users;
1700                 psd = NULL;
1701                 break;
1702         case 502:
1703                 pstrcpy(comment, r->in.info.info502->comment);
1704                 pstrcpy(pathname, r->in.info.info502->path);
1705                 type = r->in.info.info502->type;
1706                 psd = r->in.info.info502->sd;
1707                 map_generic_share_sd_bits(psd);
1708                 break;
1709         case 1004:
1710                 pstrcpy(pathname, lp_pathname(snum));
1711                 pstrcpy(comment, r->in.info.info1004->comment);
1712                 type = STYPE_DISKTREE;
1713                 break;
1714         case 1005:
1715                 /* XP re-sets the csc policy even if it wasn't changed by the
1716                    user, so we must compare it to see if it's what is set in
1717                    smb.conf, so that we can contine other ops like setting
1718                    ACLs on a share */
1719                 if (((r->in.info.info1005->dfs_flags &
1720                       SHARE_1005_CSC_POLICY_MASK) >>
1721                      SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1722                         return WERR_OK;
1723                 else {
1724                         DEBUG(3, ("_srv_net_share_set_info: client is trying "
1725                                   "to change csc policy from the network; "
1726                                   "must be done with smb.conf\n"));
1727                         return WERR_ACCESS_DENIED;
1728                 }
1729         case 1006:
1730         case 1007:
1731                 return WERR_ACCESS_DENIED;
1732         case 1501:
1733                 pstrcpy(pathname, lp_pathname(snum));
1734                 pstrcpy(comment, lp_comment(snum));
1735                 psd = r->in.info.info1501->sd;
1736                 map_generic_share_sd_bits(psd);
1737                 type = STYPE_DISKTREE;
1738                 break;
1739         default:
1740                 DEBUG(5,("_srv_net_share_set_info: unsupported switch value "
1741                          "%d\n", r->in.level));
1742                 return WERR_UNKNOWN_LEVEL;
1743         }
1744
1745         /* We can only modify disk shares. */
1746         if (type != STYPE_DISKTREE)
1747                 return WERR_ACCESS_DENIED;
1748                 
1749         /* Check if the pathname is valid. */
1750         if (!(path = valid_share_pathname( pathname )))
1751                 return WERR_OBJECT_PATH_INVALID;
1752
1753         /* Ensure share name, pathname and comment don't contain '"'
1754          * characters. */
1755         string_replace(tmp_share_name, '"', ' ');
1756         string_replace(path, '"', ' ');
1757         string_replace(comment, '"', ' ');
1758
1759         DEBUG(10,("_srv_net_share_set_info: change share command = %s\n",
1760                   lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1761
1762         /* Only call modify function if something changed. */
1763         
1764         if (strcmp(path, lp_pathname(snum))
1765             || strcmp(comment, lp_comment(snum)) 
1766             || (lp_max_connections(snum) != max_connections) ) {
1767                 WERROR err;
1768
1769                 err = change_share(tmp_share_name, path, comment,
1770                                    max_connections, p->pipe_user.nt_user_token,
1771                                    is_disk_op);
1772
1773                 if (!W_ERROR_IS_OK(err)) {
1774                         return err;
1775                 }
1776         }
1777
1778         /* Replace SD if changed. */
1779         if (psd) {
1780                 SEC_DESC *old_sd;
1781                 size_t sd_size;
1782
1783                 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum),
1784                                             &sd_size);
1785
1786                 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1787                         if (!set_share_security(r->in.share_name, psd)) {
1788                                 DEBUG(0,("_srv_net_share_set_info: Failed to "
1789                                          "change security info in share %s.\n",
1790                                          r->in.share_name ));
1791                         }
1792                 }
1793         }
1794                         
1795         DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1796
1797         return WERR_OK;
1798 }
1799
1800
1801 /*******************************************************************
1802  Net share add. Call 'add_share_command "sharename" "pathname" 
1803  "comment" "max connections = "
1804 ********************************************************************/
1805
1806 WERROR _srvsvc_NetShareAdd(pipes_struct *p, struct srvsvc_NetShareAdd *r)
1807 {
1808         pstring share_name;
1809         pstring comment;
1810         pstring pathname;
1811         char *path;
1812         int type;
1813         SEC_DESC *psd = NULL;
1814         SE_PRIV se_diskop = SE_DISK_OPERATOR;
1815         BOOL is_disk_op;
1816         uint32 max_connections = 0;
1817         WERROR err;
1818
1819         DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1820
1821         if (r->out.parm_error) {
1822                 *r->out.parm_error = 0;
1823         }
1824
1825         is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1826                                           &se_diskop );
1827
1828         if (p->pipe_user.ut.uid != sec_initial_uid()  && !is_disk_op ) 
1829                 return WERR_ACCESS_DENIED;
1830
1831         switch (r->in.level) {
1832         case 0:
1833                 /* No path. Not enough info in a level 0 to do anything. */
1834                 return WERR_ACCESS_DENIED;
1835         case 1:
1836                 /* Not enough info in a level 1 to do anything. */
1837                 return WERR_ACCESS_DENIED;
1838         case 2:
1839                 pstrcpy(share_name, r->in.info.info2->name);
1840                 pstrcpy(comment, r->in.info.info2->comment);
1841                 pstrcpy(pathname, r->in.info.info2->path);
1842                 max_connections = (r->in.info.info2->max_users == 0xffffffff) ?
1843                         0 : r->in.info.info2->max_users;
1844                 type = r->in.info.info2->type;
1845                 break;
1846         case 501:
1847                 /* No path. Not enough info in a level 501 to do anything. */
1848                 return WERR_ACCESS_DENIED;
1849         case 502:
1850                 pstrcpy(share_name, r->in.info.info502->name);
1851                 pstrcpy(comment, r->in.info.info502->comment);
1852                 pstrcpy(pathname, r->in.info.info502->path);
1853                 type = r->in.info.info502->type;
1854                 psd = r->in.info.info502->sd;
1855                 map_generic_share_sd_bits(psd);
1856                 break;
1857
1858                 /* none of the following contain share names.  NetShareAdd
1859                  * does not have a separate parameter for the share name */ 
1860
1861         case 1004:
1862         case 1005:
1863         case 1006:
1864         case 1007:
1865                 return WERR_ACCESS_DENIED;
1866         case 1501:
1867                 /* DFS only level. */
1868                 return WERR_ACCESS_DENIED;
1869         default:
1870                 DEBUG(5,("_srv_net_share_add: unsupported switch value %d\n",
1871                          r->in.level));
1872                 return WERR_UNKNOWN_LEVEL;
1873         }
1874
1875         /* check for invalid share names */
1876
1877         if ( !validate_net_name( share_name, INVALID_SHARENAME_CHARS,
1878                                  sizeof(share_name) ) ) {
1879                 DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n",
1880                          share_name));
1881                 return WERR_INVALID_NAME;
1882         }
1883
1884         if ( strequal(share_name,"IPC$") || strequal(share_name,"global")
1885              || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") ) )
1886         {
1887                 return WERR_ACCESS_DENIED;
1888         }
1889
1890         if (get_share_params(p->mem_ctx, share_name) != NULL) {
1891                 /* Share already exists. */
1892                 return WERR_ALREADY_EXISTS;
1893         }
1894
1895         /* We can only add disk shares. */
1896         if (type != STYPE_DISKTREE)
1897                 return WERR_ACCESS_DENIED;
1898                 
1899         /* Check if the pathname is valid. */
1900         if (!(path = valid_share_pathname( pathname )))
1901                 return WERR_OBJECT_PATH_INVALID;
1902
1903         /* Ensure share name, pathname and comment don't contain '"'
1904          * characters. */
1905
1906         string_replace(share_name, '"', ' ');
1907         string_replace(path, '"', ' ');
1908         string_replace(comment, '"', ' ');
1909
1910         err = add_share(share_name, path, comment, max_connections,
1911                         p->pipe_user.nt_user_token, is_disk_op);
1912
1913         if (!W_ERROR_IS_OK(err)) {
1914                 return err;
1915         }
1916
1917         if (psd) {
1918                 if (!set_share_security(share_name, psd)) {
1919                         DEBUG(0,("_srv_net_share_add: Failed to add security "
1920                                  "info to share %s.\n", share_name ));
1921                 }
1922         }
1923
1924         /*
1925          * We don't call reload_services() here, the message will
1926          * cause this to be done before the next packet is read
1927          * from the client. JRA.
1928          */
1929
1930         DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1931
1932         return WERR_OK;
1933 }
1934
1935 /*******************************************************************
1936  Net share delete. Call "delete share command" with the share name as
1937  a parameter.
1938 ********************************************************************/
1939
1940 WERROR _srvsvc_NetShareDel(pipes_struct *p, struct srvsvc_NetShareDel *r)
1941 {
1942         struct share_params *params;
1943         SE_PRIV se_diskop = SE_DISK_OPERATOR;
1944         BOOL is_disk_op;
1945         WERROR err;
1946
1947         DEBUG(5,("_srv_net_share_del: %d\n", __LINE__));
1948
1949         if ( strequal(r->in.share_name, "IPC$") 
1950              || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1951              || strequal(r->in.share_name, "global") )
1952         {
1953                 return WERR_ACCESS_DENIED;
1954         }
1955
1956         if (!(params = get_share_params(p->mem_ctx, r->in.share_name))) {
1957                 return WERR_NO_SUCH_SHARE;
1958         }
1959
1960         /* No change to printer shares. */
1961         if (lp_print_ok(params->service))
1962                 return WERR_ACCESS_DENIED;
1963
1964         is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1965                                           &se_diskop );
1966
1967         if (p->pipe_user.ut.uid != sec_initial_uid()  && !is_disk_op ) 
1968                 return WERR_ACCESS_DENIED;
1969
1970         err = delete_share(lp_servicename(params->service),
1971                            p->pipe_user.nt_user_token, is_disk_op);
1972
1973         if (!W_ERROR_IS_OK(err)) {
1974                 return err;
1975         }
1976
1977         /* Delete the SD in the database. */
1978         delete_share_security(params);
1979
1980         lp_killservice(params->service);
1981
1982         return WERR_OK;
1983 }
1984
1985 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p, struct srvsvc_NetShareDelSticky *r)
1986 {
1987         struct srvsvc_NetShareDel s;
1988
1989         DEBUG(5,("_srv_net_share_del_stick: %d\n", __LINE__));
1990
1991         s.in.server_unc = r->in.server_unc;
1992         s.in.share_name = r->in.share_name;
1993         s.in.reserved = r->in.reserved;
1994
1995         return _srvsvc_NetShareDel(p, &s);
1996 }
1997
1998 /*******************************************************************
1999 time of day
2000 ********************************************************************/
2001
2002 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p, struct srvsvc_NetRemoteTOD *r)
2003 {
2004         struct tm *t;
2005         time_t unixdate = time(NULL);
2006         WERROR status = WERR_OK;
2007
2008         /* We do this call first as if we do it *after* the gmtime call
2009            it overwrites the pointed-to values. JRA */
2010
2011         uint32 zone = get_time_zone(unixdate)/60;
2012
2013         DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
2014
2015         t = gmtime(&unixdate);
2016
2017         /* set up the */
2018         r->out.info->elapsed = unixdate;
2019         r->out.info->msecs = 0;
2020         r->out.info->hours = t->tm_hour;
2021         r->out.info->mins = t->tm_min;
2022         r->out.info->secs = t->tm_sec;
2023         r->out.info->hunds = 0;
2024         r->out.info->timezone = zone;
2025         r->out.info->tinterval = 10000;
2026         r->out.info->day = t->tm_mday;
2027         r->out.info->month = t->tm_mon + 1;
2028         r->out.info->year = 1900+t->tm_year;
2029         r->out.info->weekday = t->tm_wday;
2030         
2031         DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
2032
2033         return status;
2034 }
2035
2036 /***********************************************************************************
2037  Win9x NT tools get security descriptor.
2038 ***********************************************************************************/
2039
2040 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecurity *r)
2041 {
2042         SEC_DESC *psd = NULL;
2043         size_t sd_size;
2044         DATA_BLOB null_pw;
2045         files_struct *fsp = NULL;
2046         SMB_STRUCT_STAT st;
2047         NTSTATUS nt_status;
2048         connection_struct *conn = NULL;
2049         BOOL became_user = False; 
2050         WERROR status = WERR_OK;
2051         pstring tmp_file;
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         pstrcpy(tmp_file, r->in.file);
2077         nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
2078         if (!NT_STATUS_IS_OK(nt_status)) {
2079                 DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", r->in.file));
2080                 status = WERR_ACCESS_DENIED;
2081                 goto error_exit;
2082         }
2083
2084         nt_status = check_name(conn, r->in.file);
2085         if (!NT_STATUS_IS_OK(nt_status)) {
2086                 DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", r->in.file));
2087                 status = WERR_ACCESS_DENIED;
2088                 goto error_exit;
2089         }
2090
2091         nt_status = open_file_stat(conn, NULL, r->in.file, &st, &fsp);
2092         if (!NT_STATUS_IS_OK(nt_status)) {
2093                 /* Perhaps it is a directory */
2094                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2095                         nt_status = open_directory(conn, NULL, r->in.file, &st,
2096                                         READ_CONTROL_ACCESS,
2097                                         FILE_SHARE_READ|FILE_SHARE_WRITE,
2098                                         FILE_OPEN,
2099                                         0,
2100                                         FILE_ATTRIBUTE_DIRECTORY,
2101                                         NULL, &fsp);
2102
2103                 if (!NT_STATUS_IS_OK(nt_status)) {
2104                         DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", r->in.file));
2105                         status = WERR_ACCESS_DENIED;
2106                         goto error_exit;
2107                 }
2108         }
2109
2110         sd_size = SMB_VFS_GET_NT_ACL(fsp, fsp->fsp_name, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
2111
2112         if (sd_size == 0) {
2113                 DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", r->in.file));
2114                 status = WERR_ACCESS_DENIED;
2115                 goto error_exit;
2116         }
2117
2118         r->out.sd_buf->sd_size= sd_size;
2119         r->out.sd_buf->sd = psd;
2120
2121         psd->dacl->revision = (uint16) NT4_ACL_REVISION;
2122
2123         close_file(fsp, NORMAL_CLOSE);
2124         unbecome_user();
2125         close_cnum(conn, p->pipe_user.vuid);
2126         return status;
2127
2128 error_exit:
2129
2130         if(fsp) {
2131                 close_file(fsp, NORMAL_CLOSE);
2132         }
2133
2134         if (became_user)
2135                 unbecome_user();
2136
2137         if (conn) 
2138                 close_cnum(conn, p->pipe_user.vuid);
2139
2140         return status;
2141 }
2142
2143 /***********************************************************************************
2144  Win9x NT tools set security descriptor.
2145 ***********************************************************************************/
2146
2147 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecurity *r)
2148 {
2149         DATA_BLOB null_pw;
2150         files_struct *fsp = NULL;
2151         SMB_STRUCT_STAT st;
2152         NTSTATUS nt_status;
2153         connection_struct *conn = NULL;
2154         BOOL became_user = False;
2155         WERROR status = WERR_OK;
2156         pstring tmp_file;
2157
2158         ZERO_STRUCT(st);
2159
2160         /* Null password is ok - we are already an authenticated user... */
2161         null_pw = data_blob_null;
2162
2163         become_root();
2164         conn = make_connection(r->in.share, null_pw, "A:", p->pipe_user.vuid, &nt_status);
2165         unbecome_root();
2166
2167         if (conn == NULL) {
2168                 DEBUG(3,("_srv_net_file_set_secdesc: Unable to connect to %s\n", r->in.share));
2169                 status = ntstatus_to_werror(nt_status);
2170                 goto error_exit;
2171         }
2172
2173         if (!become_user(conn, conn->vuid)) {
2174                 DEBUG(0,("_srv_net_file_set_secdesc: Can't become connected user!\n"));
2175                 status = WERR_ACCESS_DENIED;
2176                 goto error_exit;
2177         }
2178         became_user = True;
2179
2180         pstrcpy(tmp_file, r->in.file);
2181         nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
2182         if (!NT_STATUS_IS_OK(nt_status)) {
2183                 DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", r->in.file));
2184                 status = WERR_ACCESS_DENIED;
2185                 goto error_exit;
2186         }
2187
2188         nt_status = check_name(conn, r->in.file);
2189         if (!NT_STATUS_IS_OK(nt_status)) {
2190                 DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", r->in.file));
2191                 status = WERR_ACCESS_DENIED;
2192                 goto error_exit;
2193         }
2194
2195
2196         nt_status = open_file_stat(conn, NULL, r->in.file, &st, &fsp);
2197
2198         if (!NT_STATUS_IS_OK(nt_status)) {
2199                 /* Perhaps it is a directory */
2200                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2201                         nt_status = open_directory(conn, NULL, r->in.file, &st,
2202                                                 FILE_READ_ATTRIBUTES,
2203                                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
2204                                                 FILE_OPEN,
2205                                                 0,
2206                                                 FILE_ATTRIBUTE_DIRECTORY,
2207                                                 NULL, &fsp);
2208
2209                 if (!NT_STATUS_IS_OK(nt_status)) {
2210                         DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", r->in.file));
2211                         status = WERR_ACCESS_DENIED;
2212                         goto error_exit;
2213                 }
2214         }
2215
2216         nt_status = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, r->in.securityinformation, r->in.sd_buf.sd);
2217
2218         if (!NT_STATUS_IS_OK(nt_status)) {
2219                 DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", r->in.file));
2220                 status = WERR_ACCESS_DENIED;
2221                 goto error_exit;
2222         }
2223
2224         close_file(fsp, NORMAL_CLOSE);
2225         unbecome_user();
2226         close_cnum(conn, p->pipe_user.vuid);
2227         return status;
2228
2229 error_exit:
2230
2231         if(fsp) {
2232                 close_file(fsp, NORMAL_CLOSE);
2233         }
2234
2235         if (became_user) {
2236                 unbecome_user();
2237         }
2238
2239         if (conn) {
2240                 close_cnum(conn, p->pipe_user.vuid);
2241         }
2242
2243         return status;
2244 }
2245
2246 /***********************************************************************************
2247  It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2248  We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2249  These disks would the disks listed by this function.
2250  Users could then create shares relative to these disks.  Watch out for moving these disks around.
2251  "Nigel Williams" <nigel@veritas.com>.
2252 ***********************************************************************************/
2253
2254 static const char *server_disks[] = {"C:"};
2255
2256 static uint32 get_server_disk_count(void)
2257 {
2258         return sizeof(server_disks)/sizeof(server_disks[0]);
2259 }
2260
2261 static uint32 init_server_disk_enum(uint32 *resume)
2262 {
2263         uint32 server_disk_count = get_server_disk_count();
2264
2265         /*resume can be an offset into the list for now*/
2266
2267         if(*resume & 0x80000000)
2268                 *resume = 0;
2269
2270         if(*resume > server_disk_count)
2271                 *resume = server_disk_count;
2272
2273         return server_disk_count - *resume;
2274 }
2275
2276 static const char *next_server_disk_enum(uint32 *resume)
2277 {
2278         const char *disk;
2279
2280         if(init_server_disk_enum(resume) == 0)
2281                 return NULL;
2282
2283         disk = server_disks[*resume];
2284
2285         (*resume)++;
2286
2287         DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2288
2289         return disk;
2290 }
2291
2292 WERROR _srvsvc_NetDiskEnum(pipes_struct *p, struct srvsvc_NetDiskEnum *r)
2293 {
2294         uint32 i;
2295         const char *disk_name;
2296
2297         WERROR status = WERR_OK;
2298
2299         *r->out.totalentries = init_server_disk_enum(r->in.resume_handle);
2300         r->out.info->count = 0;
2301
2302         if(!(r->out.info->disks =  TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetDiskInfo0, MAX_SERVER_DISK_ENTRIES))) {
2303                 return WERR_NOMEM;
2304         }
2305
2306         /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2307
2308         for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(r->in.resume_handle)); i++) {
2309
2310                 r->out.info->count++;
2311                 (*r->out.totalentries)++;
2312
2313                 /*copy disk name into a unicode string*/
2314
2315                 r->out.info->disks[i].disk = disk_name; 
2316         }
2317
2318         /* add a terminating null string.  Is this there if there is more data to come? */
2319
2320         r->out.info->count++;
2321         (*r->out.totalentries)++;
2322
2323         r->out.info->disks[i].disk = "";
2324
2325         return status;
2326 }
2327
2328 /********************************************************************
2329 ********************************************************************/
2330
2331 WERROR _srvsvc_NetNameValidate(pipes_struct *p, struct srvsvc_NetNameValidate *r)
2332 {
2333         int len;
2334
2335         if ((r->in.flags != 0x0) && (r->in.flags != 0x80000000)) {
2336                 return WERR_INVALID_PARAM;
2337         }
2338
2339         switch ( r->in.name_type ) {
2340         case 0x9:
2341                 len = strlen_m(r->in.name);
2342
2343                 if ((r->in.flags == 0x0) && (len > 81)) {
2344                         DEBUG(5,("_srv_net_name_validate: share name too long (%s > 81 chars)\n", r->in.name));
2345                         return WERR_INVALID_NAME;
2346                 }
2347                 if ((r->in.flags == 0x80000000) && (len > 13)) {
2348                         DEBUG(5,("_srv_net_name_validate: share name too long (%s > 13 chars)\n", r->in.name));
2349                         return WERR_INVALID_NAME;
2350                 }
2351
2352                 if ( ! validate_net_name( r->in.name, INVALID_SHARENAME_CHARS, sizeof(r->in.name) ) ) {
2353                         DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", r->in.name));
2354                         return WERR_INVALID_NAME;
2355                 }
2356                 break;
2357
2358         default:
2359                 return WERR_UNKNOWN_LEVEL;
2360         }
2361
2362         return WERR_OK;
2363 }
2364
2365
2366 /********************************************************************
2367 ********************************************************************/
2368
2369 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2370 {
2371         return WERR_ACCESS_DENIED;
2372 }
2373
2374 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2375 {
2376         p->rng_fault_state = True;
2377         return WERR_NOT_SUPPORTED;
2378 }
2379
2380 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2381 {
2382         p->rng_fault_state = True;
2383         return WERR_NOT_SUPPORTED;
2384 }
2385
2386 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2387 {
2388         p->rng_fault_state = True;
2389         return WERR_NOT_SUPPORTED;
2390 }
2391
2392 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2393 {
2394         p->rng_fault_state = True;
2395         return WERR_NOT_SUPPORTED;
2396 }
2397
2398 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2399 {
2400         p->rng_fault_state = True;
2401         return WERR_NOT_SUPPORTED;
2402 }
2403
2404 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2405 {
2406         p->rng_fault_state = True;
2407         return WERR_NOT_SUPPORTED;
2408 }
2409
2410 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2411 {
2412         p->rng_fault_state = True;
2413         return WERR_NOT_SUPPORTED;
2414 }
2415
2416 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2417 {
2418         p->rng_fault_state = True;
2419         return WERR_NOT_SUPPORTED;
2420 }
2421
2422 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2423 {
2424         p->rng_fault_state = True;
2425         return WERR_NOT_SUPPORTED;
2426 }
2427
2428 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2429 {
2430         p->rng_fault_state = True;
2431         return WERR_NOT_SUPPORTED;
2432 }
2433
2434 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2435 {
2436         p->rng_fault_state = True;
2437         return WERR_NOT_SUPPORTED;
2438 }
2439
2440 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2441 {
2442         p->rng_fault_state = True;
2443         return WERR_NOT_SUPPORTED;
2444 }
2445
2446 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2447 {
2448         p->rng_fault_state = True;
2449         return WERR_NOT_SUPPORTED;
2450 }
2451
2452 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2453 {
2454         p->rng_fault_state = True;
2455         return WERR_NOT_SUPPORTED;
2456 }
2457
2458 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2459 {
2460         p->rng_fault_state = True;
2461         return WERR_NOT_SUPPORTED;
2462 }
2463
2464 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2465 {
2466         p->rng_fault_state = True;
2467         return WERR_NOT_SUPPORTED;
2468 }
2469
2470 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2471 {
2472         p->rng_fault_state = True;
2473         return WERR_NOT_SUPPORTED;
2474 }
2475
2476 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2477 {
2478         p->rng_fault_state = True;
2479         return WERR_NOT_SUPPORTED;
2480 }
2481
2482 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2483 {
2484         p->rng_fault_state = True;
2485         return WERR_NOT_SUPPORTED;
2486 }
2487
2488 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2489 {
2490         p->rng_fault_state = True;
2491         return WERR_NOT_SUPPORTED;
2492 }
2493
2494 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2495 {
2496         p->rng_fault_state = True;
2497         return WERR_NOT_SUPPORTED;
2498 }
2499
2500 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2501 {
2502         p->rng_fault_state = True;
2503         return WERR_NOT_SUPPORTED;
2504 }
2505
2506 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2507 {
2508         p->rng_fault_state = True;
2509         return WERR_NOT_SUPPORTED;
2510 }
2511
2512 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2513 {
2514         p->rng_fault_state = True;
2515         return WERR_NOT_SUPPORTED;
2516 }
2517
2518 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2519 {
2520         p->rng_fault_state = True;
2521         return WERR_NOT_SUPPORTED;
2522 }
2523
2524 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2525 {
2526         p->rng_fault_state = True;
2527         return WERR_NOT_SUPPORTED;
2528 }
2529
2530 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2531 {
2532         p->rng_fault_state = True;
2533         return WERR_NOT_SUPPORTED;
2534 }
2535
2536 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *R)
2537 {
2538         p->rng_fault_state = True;
2539         return WERR_NOT_SUPPORTED;
2540 }
2541
2542 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2543 {
2544         p->rng_fault_state = True;
2545         return WERR_NOT_SUPPORTED;
2546 }
2547
2548 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2549 {
2550         p->rng_fault_state = True;
2551         return WERR_NOT_SUPPORTED;
2552 }
2553
2554 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2555 {
2556         p->rng_fault_state = True;
2557         return WERR_NOT_SUPPORTED;
2558 }
2559
2560 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2561 {
2562         p->rng_fault_state = True;
2563         return WERR_NOT_SUPPORTED;
2564 }
2565
2566 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2567 {
2568         p->rng_fault_state = True;
2569         return WERR_NOT_SUPPORTED;
2570 }
2571
2572 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2573 {
2574         p->rng_fault_state = True;
2575         return WERR_NOT_SUPPORTED;
2576 }
2577
2578 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2579 {
2580         p->rng_fault_state = True;
2581         return WERR_NOT_SUPPORTED;
2582 }