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