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