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