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