smbd: use metadata_fsp() with SMB_VFS_FGET_NT_ACL()
[samba.git] / source3 / rpc_server / srvsvc / 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 #include "system/passwd.h"
28 #include "lib/util/server_id.h"
29 #include "ntdomain.h"
30 #include "librpc/gen_ndr/ndr_srvsvc.h"
31 #include "librpc/gen_ndr/ndr_srvsvc_scompat.h"
32 #include "../libcli/security/security.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "dbwrap/dbwrap.h"
36 #include "session.h"
37 #include "../lib/util/util_pw.h"
38 #include "locking/share_mode_lock.h"
39 #include "smbd/smbd.h"
40 #include "smbd/globals.h"
41 #include "auth.h"
42 #include "messages.h"
43 #include "serverid.h"
44 #include "lib/global_contexts.h"
45 #include "source3/lib/substitute.h"
46
47 extern const struct generic_mapping file_generic_mapping;
48
49 #undef DBGC_CLASS
50 #define DBGC_CLASS DBGC_RPC_SRV
51
52 #define MAX_SERVER_DISK_ENTRIES 15
53
54 /* Use for enumerating connections, pipes, & files */
55
56 struct file_enum_count {
57         TALLOC_CTX *ctx;
58         const char *username;
59         struct srvsvc_NetFileCtr3 *ctr3;
60         struct file_id *fids;
61 };
62
63 struct sess_file_info {
64         struct srvsvc_NetSessCtr1 *ctr;
65         struct sessionid *session_list;
66         uint32_t resume_handle;
67         uint32_t num_entries;
68 };
69
70 struct share_file_stat {
71         struct srvsvc_NetConnInfo1 *netconn_arr;
72         struct server_id *svrid_arr;
73         const char *in_sharepath;
74         uint32_t resp_entries;
75         uint32_t total_entries;
76 };
77
78 struct share_conn_stat {
79         TALLOC_CTX *ctx;
80         const char *sharename;
81         struct server_id *svrid_arr;
82         int count;
83 };
84
85 /*******************************************************************
86 ********************************************************************/
87
88 static int enum_file_fn(struct file_id id,
89                         const struct share_mode_data *d,
90                         const struct share_mode_entry *e,
91                         void *private_data)
92 {
93         struct file_enum_count *fenum =
94                 (struct file_enum_count *)private_data;
95         struct srvsvc_NetFileCtr3 *ctr3 = fenum->ctr3;
96         struct srvsvc_NetFileInfo3 *f;
97         struct file_id *fids = NULL;
98         char *fullpath = NULL;
99         uint32_t permissions;
100         const char *username;
101
102         /* If the pid was not found delete the entry from connections.tdb */
103
104         if ( !process_exists(e->pid) ) {
105                 return 0;
106         }
107
108         username = uidtoname(e->uid);
109
110         if ((fenum->username != NULL)
111             && !strequal(username, fenum->username)) {
112                 return 0;
113         }
114
115         f = talloc_realloc(
116                 fenum->ctx,
117                 ctr3->array,
118                 struct srvsvc_NetFileInfo3,
119                 ctr3->count+1);
120         if ( !f ) {
121                 DBG_ERR("realloc failed for %"PRIu32" items\n", ctr3->count+1);
122                 return 0;
123         }
124         ctr3->array = f;
125
126         fids = talloc_realloc(
127                 fenum->ctx, fenum->fids, struct file_id, ctr3->count+1);
128         if (fids == NULL) {
129                 DBG_ERR("realloc failed for %"PRIu32" items\n", ctr3->count+1);
130                 return 0;
131         }
132         fids[ctr3->count] = id;
133         fenum->fids = fids;
134
135         if ( strcmp(d->base_name, "." ) == 0 ) {
136                 fullpath = talloc_asprintf(
137                         fenum->ctx,
138                         "C:%s",
139                         d->servicepath);
140         } else {
141                 fullpath = talloc_asprintf(
142                         fenum->ctx,
143                         "C:%s/%s%s",
144                         d->servicepath,
145                         d->base_name,
146                         (d->stream_name != NULL) ? d->stream_name : "");
147         }
148         if (!fullpath) {
149                 return 0;
150         }
151         string_replace( fullpath, '/', '\\' );
152
153         /* mask out create (what ever that is) */
154         permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
155
156         /* now fill in the srvsvc_NetFileInfo3 struct */
157
158         ctr3->array[ctr3->count] = (struct srvsvc_NetFileInfo3) {
159                 .fid            = (((uint32_t)(procid_to_pid(&e->pid))<<16) |
160                                    e->share_file_id),
161                 .permissions    = permissions,
162                 .path           = fullpath,
163                 .user           = username,
164         };
165
166         ctr3->count++;
167
168         return 0;
169 }
170
171 /*******************************************************************
172 ********************************************************************/
173
174 static WERROR net_enum_files(TALLOC_CTX *ctx,
175                              const char *username,
176                              struct srvsvc_NetFileCtr3 **ctr3,
177                              uint32_t resume)
178 {
179         struct file_enum_count f_enum_cnt = {
180                 .ctx = ctx, .username = username, .ctr3 = *ctr3,
181         };
182         uint32_t i;
183
184         share_entry_forall(enum_file_fn, (void *)&f_enum_cnt );
185
186         *ctr3 = f_enum_cnt.ctr3;
187
188         /* need to count the number of locks on a file */
189
190         for (i=0; i<(*ctr3)->count; i++) {
191                 struct files_struct fsp = { .file_id = f_enum_cnt.fids[i], };
192                 struct byte_range_lock *brl = NULL;
193
194                 brl = brl_get_locks(ctx, &fsp);
195                 if (brl == NULL) {
196                         continue;
197                 }
198
199                 (*ctr3)->array[i].num_locks = brl_num_locks(brl);
200
201                 TALLOC_FREE(brl);
202         }
203
204         return WERR_OK;
205 }
206
207 /*******************************************************************
208  Utility function to get the 'type' of a share from an snum.
209  ********************************************************************/
210 static enum srvsvc_ShareType get_share_type(int snum)
211 {
212         /* work out the share type */
213         enum srvsvc_ShareType type = STYPE_DISKTREE;
214
215         if (lp_printable(snum)) {
216                 type = lp_administrative_share(snum)
217                         ? STYPE_PRINTQ_HIDDEN : STYPE_PRINTQ;
218         }
219         if (strequal(lp_fstype(snum), "IPC")) {
220                 type = lp_administrative_share(snum)
221                         ? STYPE_IPC_HIDDEN : STYPE_IPC;
222         }
223         return type;
224 }
225
226 /*******************************************************************
227  Fill in a share info level 0 structure.
228  ********************************************************************/
229
230 static void init_srv_share_info_0(struct pipes_struct *p,
231                                   struct srvsvc_NetShareInfo0 *r, int snum)
232 {
233         const struct loadparm_substitution *lp_sub =
234                 loadparm_s3_global_substitution();
235
236         r->name         = lp_servicename(talloc_tos(), lp_sub, snum);
237 }
238
239 /*******************************************************************
240  Fill in a share info level 1 structure.
241  ********************************************************************/
242
243 static void init_srv_share_info_1(struct pipes_struct *p,
244                                   struct srvsvc_NetShareInfo1 *r,
245                                   int snum)
246 {
247         const struct loadparm_substitution *lp_sub =
248                 loadparm_s3_global_substitution();
249         char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
250         char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
251
252         if (remark) {
253                 remark = talloc_sub_full(
254                         p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
255                         get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
256                         p->session_info->unix_token->uid, get_current_username(),
257                         "", remark);
258         }
259
260         r->name         = net_name;
261         r->type         = get_share_type(snum);
262         r->comment      = remark ? remark : "";
263 }
264
265 /*******************************************************************
266  Fill in a share info level 2 structure.
267  ********************************************************************/
268
269 static void init_srv_share_info_2(struct pipes_struct *p,
270                                   struct srvsvc_NetShareInfo2 *r,
271                                   int snum)
272 {
273         const struct loadparm_substitution *lp_sub =
274                 loadparm_s3_global_substitution();
275         char *remark = NULL;
276         char *path = NULL;
277         int max_connections = lp_max_connections(snum);
278         uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
279         char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
280
281         remark = lp_comment(p->mem_ctx, lp_sub, snum);
282         if (remark) {
283                 remark = talloc_sub_full(
284                         p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
285                         get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
286                         p->session_info->unix_token->uid, get_current_username(),
287                         "", remark);
288         }
289         path = talloc_asprintf(p->mem_ctx,
290                         "C:%s", lp_path(talloc_tos(), lp_sub, snum));
291
292         if (path) {
293                 /*
294                  * Change / to \\ so that win2k will see it as a valid path.
295                  * This was added to enable use of browsing in win2k add
296                  * share dialog.
297                  */
298
299                 string_replace(path, '/', '\\');
300         }
301
302         r->name                 = net_name;
303         r->type                 = get_share_type(snum);
304         r->comment              = remark ? remark : "";
305         r->permissions          = 0;
306         r->max_users            = max_uses;
307         r->current_users        = 0; /* computed later */
308         r->path                 = path ? path : "";
309         r->password             = "";
310 }
311
312 /*******************************************************************
313  Map any generic bits to file specific bits.
314 ********************************************************************/
315
316 static void map_generic_share_sd_bits(struct security_descriptor *psd)
317 {
318         int i;
319         struct security_acl *ps_dacl = NULL;
320
321         if (!psd)
322                 return;
323
324         ps_dacl = psd->dacl;
325         if (!ps_dacl)
326                 return;
327
328         for (i = 0; i < ps_dacl->num_aces; i++) {
329                 struct security_ace *psa = &ps_dacl->aces[i];
330                 uint32_t orig_mask = psa->access_mask;
331
332                 se_map_generic(&psa->access_mask, &file_generic_mapping);
333                 psa->access_mask |= orig_mask;
334         }
335 }
336
337 /*******************************************************************
338  Fill in a share info level 501 structure.
339 ********************************************************************/
340
341 static void init_srv_share_info_501(struct pipes_struct *p,
342                                     struct srvsvc_NetShareInfo501 *r, int snum)
343 {
344         const struct loadparm_substitution *lp_sub =
345                 loadparm_s3_global_substitution();
346         const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
347         char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
348
349         if (remark) {
350                 remark = talloc_sub_full(
351                         p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
352                         get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
353                         p->session_info->unix_token->uid, get_current_username(),
354                         "", remark);
355         }
356
357         r->name         = net_name;
358         r->type         = get_share_type(snum);
359         r->comment      = remark ? remark : "";
360
361         /*
362          * According to [MS-SRVS] 2.2.4.25, the flags field is the same as in
363          * level 1005.
364          */
365         r->csc_policy   = (lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT);
366 }
367
368 /*******************************************************************
369  Fill in a share info level 502 structure.
370  ********************************************************************/
371
372 static void init_srv_share_info_502(struct pipes_struct *p,
373                                     struct srvsvc_NetShareInfo502 *r, int snum)
374 {
375         const struct loadparm_substitution *lp_sub =
376                 loadparm_s3_global_substitution();
377         const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
378         char *path = NULL;
379         struct security_descriptor *sd = NULL;
380         struct sec_desc_buf *sd_buf = NULL;
381         size_t sd_size = 0;
382         TALLOC_CTX *ctx = p->mem_ctx;
383         char *remark = lp_comment(ctx, lp_sub, snum);
384
385         if (remark) {
386                 remark = talloc_sub_full(
387                         p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
388                         get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
389                         p->session_info->unix_token->uid, get_current_username(),
390                         "", remark);
391         }
392         path = talloc_asprintf(ctx, "C:%s", lp_path(talloc_tos(), lp_sub, snum));
393         if (path) {
394                 /*
395                  * Change / to \\ so that win2k will see it as a valid path.  This was added to
396                  * enable use of browsing in win2k add share dialog.
397                  */
398                 string_replace(path, '/', '\\');
399         }
400
401         sd = get_share_security(ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
402
403         sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
404
405         r->name                 = net_name;
406         r->type                 = get_share_type(snum);
407         r->comment              = remark ? remark : "";
408         r->permissions          = 0;
409         r->max_users            = (uint32_t)-1;
410         r->current_users        = 1; /* ??? */
411         r->path                 = path ? path : "";
412         r->password             = "";
413         r->sd_buf               = *sd_buf;
414 }
415
416 /***************************************************************************
417  Fill in a share info level 1004 structure.
418  ***************************************************************************/
419
420 static void init_srv_share_info_1004(struct pipes_struct *p,
421                                      struct srvsvc_NetShareInfo1004 *r,
422                                      int snum)
423 {
424         const struct loadparm_substitution *lp_sub =
425                 loadparm_s3_global_substitution();
426         char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
427
428         if (remark) {
429                 remark = talloc_sub_full(
430                         p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
431                         get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
432                         p->session_info->unix_token->uid, get_current_username(),
433                         "", remark);
434         }
435
436         r->comment      = remark ? remark : "";
437 }
438
439 /***************************************************************************
440  Fill in a share info level 1005 structure.
441  ***************************************************************************/
442
443 static void init_srv_share_info_1005(struct pipes_struct *p,
444                                      struct srvsvc_NetShareInfo1005 *r,
445                                      int snum)
446 {
447         uint32_t dfs_flags = 0;
448
449         if (lp_host_msdfs() && lp_msdfs_root(snum)) {
450                 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
451         }
452
453         dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
454
455         r->dfs_flags    = dfs_flags;
456 }
457
458 /***************************************************************************
459  Fill in a share info level 1006 structure.
460  ***************************************************************************/
461
462 static void init_srv_share_info_1006(struct pipes_struct *p,
463                                      struct srvsvc_NetShareInfo1006 *r,
464                                      int snum)
465 {
466         r->max_users    = (uint32_t)-1;
467 }
468
469 /***************************************************************************
470  Fill in a share info level 1007 structure.
471  ***************************************************************************/
472
473 static void init_srv_share_info_1007(struct pipes_struct *p,
474                                      struct srvsvc_NetShareInfo1007 *r,
475                                      int snum)
476 {
477         r->flags                        = 0;
478         r->alternate_directory_name     = "";
479 }
480
481 /*******************************************************************
482  Fill in a share info level 1501 structure.
483  ********************************************************************/
484
485 static void init_srv_share_info_1501(struct pipes_struct *p,
486                                      struct sec_desc_buf **r,
487                                      int snum)
488 {
489         const struct loadparm_substitution *lp_sub =
490                 loadparm_s3_global_substitution();
491         struct security_descriptor *sd;
492         struct sec_desc_buf *sd_buf = NULL;
493         size_t sd_size;
494         TALLOC_CTX *ctx = p->mem_ctx;
495
496         sd = get_share_security(ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
497         if (sd) {
498                 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
499         }
500
501         *r = sd_buf;
502 }
503
504 /*******************************************************************
505  True if it ends in '$'.
506  ********************************************************************/
507
508 static bool is_hidden_share(int snum)
509 {
510         const struct loadparm_substitution *lp_sub =
511                 loadparm_s3_global_substitution();
512         const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
513
514         return (net_name[strlen(net_name) - 1] == '$') ? True : False;
515 }
516
517 /*******************************************************************
518  Verify user is allowed to view share, access based enumeration
519 ********************************************************************/
520 static bool is_enumeration_allowed(struct pipes_struct *p,
521                                    int snum)
522 {
523         const struct loadparm_substitution *lp_sub =
524                 loadparm_s3_global_substitution();
525
526         if (!lp_access_based_share_enum(snum)) {
527                 return true;
528         }
529
530         if (!user_ok_token(p->session_info->unix_info->unix_name,
531                            p->session_info->info->domain_name,
532                            p->session_info->security_token, snum)) {
533                 return false;
534         }
535
536         return share_access_check(p->session_info->security_token,
537                                   lp_servicename(talloc_tos(), lp_sub, snum),
538                                   FILE_READ_DATA, NULL);
539 }
540
541 /****************************************************************************
542  Count an entry against the respective service.
543 ****************************************************************************/
544
545 static int count_for_all_fn(struct smbXsrv_tcon_global0 *tcon, void *udp)
546 {
547         union srvsvc_NetShareCtr *ctr = NULL;
548         struct srvsvc_NetShareInfo2 *info2 = NULL;
549         int share_entries = 0;
550         int i = 0;
551
552         ctr = (union srvsvc_NetShareCtr *) udp;
553
554         /* for level 2 */
555         share_entries  = ctr->ctr2->count;
556         info2 = &ctr->ctr2->array[0];
557
558         for (i = 0; i < share_entries; i++, info2++) {
559                 if (strequal(tcon->share_name, info2->name)) {
560                         info2->current_users++;
561                         break;
562                 }
563         }
564
565         return 0;
566 }
567
568 /****************************************************************************
569  Count the entries belonging to all services in the connection db.
570 ****************************************************************************/
571
572 static void count_connections_for_all_shares(union srvsvc_NetShareCtr *ctr)
573 {
574         NTSTATUS status;
575         status = smbXsrv_tcon_global_traverse(count_for_all_fn, ctr);
576
577         if (!NT_STATUS_IS_OK(status)) {
578                 DEBUG(0,("count_connections_for_all_shares: traverse of "
579                         "smbXsrv_tcon_global.tdb failed - %s\n",
580                         nt_errstr(status)));
581         }
582 }
583
584 /*******************************************************************
585  Fill in a share info structure.
586  ********************************************************************/
587
588 static WERROR init_srv_share_info_ctr(struct pipes_struct *p,
589                                       struct srvsvc_NetShareInfoCtr *info_ctr,
590                                       uint32_t *resume_handle_p,
591                                       uint32_t *total_entries,
592                                       bool all_shares)
593 {
594         const struct loadparm_substitution *lp_sub =
595                 loadparm_s3_global_substitution();
596         uint32_t num_entries = 0;
597         uint32_t alloc_entries = 0;
598         int num_services = 0;
599         int snum;
600         TALLOC_CTX *ctx = p->mem_ctx;
601         uint32_t i = 0;
602         uint32_t valid_share_count = 0;
603         bool *allowed = 0;
604         union srvsvc_NetShareCtr ctr;
605         uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
606
607         DEBUG(5,("init_srv_share_info_ctr\n"));
608
609         /* Ensure all the usershares are loaded. */
610         become_root();
611         delete_and_reload_printers();
612         load_usershare_shares(NULL, connections_snum_used);
613         load_registry_shares();
614         num_services = lp_numservices();
615         unbecome_root();
616
617         allowed = talloc_zero_array(ctx, bool, num_services);
618         W_ERROR_HAVE_NO_MEMORY(allowed);
619
620         /* Count the number of entries. */
621         for (snum = 0; snum < num_services; snum++) {
622                 if (lp_browseable(snum) && lp_snum_ok(snum) &&
623                     is_enumeration_allowed(p, snum) &&
624                     (all_shares || !is_hidden_share(snum)) ) {
625                         DEBUG(10, ("counting service %s\n",
626                                 lp_servicename(talloc_tos(), lp_sub, snum) ? lp_servicename(talloc_tos(), lp_sub, snum) : "(null)"));
627                         allowed[snum] = true;
628                         num_entries++;
629                 } else {
630                         DEBUG(10, ("NOT counting service %s\n",
631                                 lp_servicename(talloc_tos(), lp_sub, snum) ? lp_servicename(talloc_tos(), lp_sub, snum) : "(null)"));
632                 }
633         }
634
635         if (!num_entries || (resume_handle >= num_entries)) {
636                 return WERR_OK;
637         }
638
639         /* Calculate alloc entries. */
640         alloc_entries = num_entries - resume_handle;
641         switch (info_ctr->level) {
642         case 0:
643                 ctr.ctr0 = talloc_zero(ctx, struct srvsvc_NetShareCtr0);
644                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
645
646                 ctr.ctr0->count = alloc_entries;
647                 ctr.ctr0->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
648                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
649
650                 for (snum = 0; snum < num_services; snum++) {
651                         if (allowed[snum] &&
652                             (resume_handle <= (i + valid_share_count++)) ) {
653                                 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
654                         }
655                 }
656
657                 break;
658
659         case 1:
660                 ctr.ctr1 = talloc_zero(ctx, struct srvsvc_NetShareCtr1);
661                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
662
663                 ctr.ctr1->count = alloc_entries;
664                 ctr.ctr1->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
665                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
666
667                 for (snum = 0; snum < num_services; snum++) {
668                         if (allowed[snum] &&
669                             (resume_handle <= (i + valid_share_count++)) ) {
670                                 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
671                         }
672                 }
673
674                 break;
675
676         case 2:
677                 ctr.ctr2 = talloc_zero(ctx, struct srvsvc_NetShareCtr2);
678                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
679
680                 ctr.ctr2->count = alloc_entries;
681                 ctr.ctr2->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
682                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
683
684                 for (snum = 0; snum < num_services; snum++) {
685                         if (allowed[snum] &&
686                             (resume_handle <= (i + valid_share_count++)) ) {
687                                 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
688                         }
689                 }
690
691                 count_connections_for_all_shares(&ctr);
692                 break;
693
694         case 501:
695                 ctr.ctr501 = talloc_zero(ctx, struct srvsvc_NetShareCtr501);
696                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
697
698                 ctr.ctr501->count = alloc_entries;
699                 ctr.ctr501->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
700                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
701
702                 for (snum = 0; snum < num_services; snum++) {
703                         if (allowed[snum] &&
704                             (resume_handle <= (i + valid_share_count++)) ) {
705                                 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
706                         }
707                 }
708
709                 break;
710
711         case 502:
712                 ctr.ctr502 = talloc_zero(ctx, struct srvsvc_NetShareCtr502);
713                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
714
715                 ctr.ctr502->count = alloc_entries;
716                 ctr.ctr502->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
717                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
718
719                 for (snum = 0; snum < num_services; snum++) {
720                         if (allowed[snum] &&
721                             (resume_handle <= (i + valid_share_count++)) ) {
722                                 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
723                         }
724                 }
725
726                 break;
727
728         case 1004:
729                 ctr.ctr1004 = talloc_zero(ctx, struct srvsvc_NetShareCtr1004);
730                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
731
732                 ctr.ctr1004->count = alloc_entries;
733                 ctr.ctr1004->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
734                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
735
736                 for (snum = 0; snum < num_services; snum++) {
737                         if (allowed[snum] &&
738                             (resume_handle <= (i + valid_share_count++)) ) {
739                                 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
740                         }
741                 }
742
743                 break;
744
745         case 1005:
746                 ctr.ctr1005 = talloc_zero(ctx, struct srvsvc_NetShareCtr1005);
747                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
748
749                 ctr.ctr1005->count = alloc_entries;
750                 ctr.ctr1005->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
751                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
752
753                 for (snum = 0; snum < num_services; snum++) {
754                         if (allowed[snum] &&
755                             (resume_handle <= (i + valid_share_count++)) ) {
756                                 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
757                         }
758                 }
759
760                 break;
761
762         case 1006:
763                 ctr.ctr1006 = talloc_zero(ctx, struct srvsvc_NetShareCtr1006);
764                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
765
766                 ctr.ctr1006->count = alloc_entries;
767                 ctr.ctr1006->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
768                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
769
770                 for (snum = 0; snum < num_services; snum++) {
771                         if (allowed[snum] &&
772                             (resume_handle <= (i + valid_share_count++)) ) {
773                                 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
774                         }
775                 }
776
777                 break;
778
779         case 1007:
780                 ctr.ctr1007 = talloc_zero(ctx, struct srvsvc_NetShareCtr1007);
781                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
782
783                 ctr.ctr1007->count = alloc_entries;
784                 ctr.ctr1007->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
785                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
786
787                 for (snum = 0; snum < num_services; snum++) {
788                         if (allowed[snum] &&
789                             (resume_handle <= (i + valid_share_count++)) ) {
790                                 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
791                         }
792                 }
793
794                 break;
795
796         case 1501:
797                 ctr.ctr1501 = talloc_zero(ctx, struct srvsvc_NetShareCtr1501);
798                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
799
800                 ctr.ctr1501->count = alloc_entries;
801                 ctr.ctr1501->array = talloc_zero_array(ctx, struct sec_desc_buf, alloc_entries);
802                 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
803
804                 for (snum = 0; snum < num_services; snum++) {
805                         if (allowed[snum] &&
806                             (resume_handle <= (i + valid_share_count++)) ) {
807                                 struct sec_desc_buf *sd_buf = NULL;
808                                 init_srv_share_info_1501(p, &sd_buf, snum);
809                                 ctr.ctr1501->array[i++] = *sd_buf;
810                         }
811                 }
812
813                 break;
814
815         default:
816                 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
817                         info_ctr->level));
818                 return WERR_INVALID_LEVEL;
819         }
820
821         *total_entries = alloc_entries;
822         if (resume_handle_p) {
823                 if (all_shares) {
824                         *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
825                 } else {
826                         *resume_handle_p = num_entries;
827                 }
828         }
829
830         info_ctr->ctr = ctr;
831
832         return WERR_OK;
833 }
834
835 /*******************************************************************
836  fill in a sess info level 0 structure.
837  ********************************************************************/
838
839 static WERROR init_srv_sess_info_0(struct pipes_struct *p,
840                                    struct srvsvc_NetSessCtr0 *ctr0,
841                                    uint32_t *resume_handle_p,
842                                    uint32_t *total_entries)
843 {
844         struct sessionid *session_list;
845         uint32_t num_entries = 0;
846         uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
847         *total_entries = list_sessions(p->mem_ctx, &session_list);
848
849         DEBUG(5,("init_srv_sess_info_0\n"));
850
851         if (ctr0 == NULL) {
852                 if (resume_handle_p) {
853                         *resume_handle_p = 0;
854                 }
855                 return WERR_OK;
856         }
857
858         for (; resume_handle < *total_entries; resume_handle++) {
859
860                 ctr0->array = talloc_realloc(p->mem_ctx,
861                                                    ctr0->array,
862                                                    struct srvsvc_NetSessInfo0,
863                                                    num_entries+1);
864                 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
865
866                 ctr0->array[num_entries].client =
867                         session_list[resume_handle].remote_machine;
868
869                 num_entries++;
870         }
871
872         ctr0->count = num_entries;
873
874         if (resume_handle_p) {
875                 if (*resume_handle_p >= *total_entries) {
876                         *resume_handle_p = 0;
877                 } else {
878                         *resume_handle_p = resume_handle;
879                 }
880         }
881
882         return WERR_OK;
883 }
884
885 /***********************************************************************
886  * find out the session on which this file is open and bump up its count
887  **********************************************************************/
888
889 static int count_sess_files_fn(struct file_id fid,
890                                const struct share_mode_data *d,
891                                const struct share_mode_entry *e,
892                                void *data)
893 {
894         struct sess_file_info *info = data;
895         uint32_t rh = info->resume_handle;
896         int i;
897
898         for (i=0; i < info->num_entries; i++) {
899                 /* rh+info->num_entries is safe, as we've
900                    ensured that:
901                    *total_entries > resume_handle &&
902                    info->num_entries = *total_entries - resume_handle;
903                    inside init_srv_sess_info_1() below.
904                 */
905                 struct sessionid *sess = &info->session_list[rh + i];
906                 if ((e->uid == sess->uid) &&
907                      server_id_equal(&e->pid, &sess->pid)) {
908
909                         info->ctr->array[i].num_open++;
910                         return 0;
911                 }
912         }
913         return 0;
914 }
915
916 /*******************************************************************
917  * count the num of open files on all sessions
918  *******************************************************************/
919
920 static void net_count_files_for_all_sess(struct srvsvc_NetSessCtr1 *ctr1,
921                                          struct sessionid *session_list,
922                                          uint32_t resume_handle,
923                                          uint32_t num_entries)
924 {
925         struct sess_file_info s_file_info;
926
927         s_file_info.ctr = ctr1;
928         s_file_info.session_list = session_list;
929         s_file_info.resume_handle = resume_handle;
930         s_file_info.num_entries = num_entries;
931
932         share_entry_forall(count_sess_files_fn, &s_file_info);
933 }
934
935 /*******************************************************************
936  fill in a sess info level 1 structure.
937  ********************************************************************/
938
939 static WERROR init_srv_sess_info_1(struct pipes_struct *p,
940                                    struct srvsvc_NetSessCtr1 *ctr1,
941                                    uint32_t *resume_handle_p,
942                                    uint32_t *total_entries)
943 {
944         struct sessionid *session_list;
945         uint32_t num_entries = 0;
946         time_t now = time(NULL);
947         uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
948
949         ZERO_STRUCTP(ctr1);
950
951         if (ctr1 == NULL) {
952                 if (resume_handle_p) {
953                         *resume_handle_p = 0;
954                 }
955                 return WERR_OK;
956         }
957
958         *total_entries = list_sessions(p->mem_ctx, &session_list);
959
960         if (resume_handle >= *total_entries) {
961                 if (resume_handle_p) {
962                         *resume_handle_p = 0;
963                 }
964                 return WERR_OK;
965         }
966
967         /* We know num_entries must be positive, due to
968            the check resume_handle >= *total_entries above. */
969
970         num_entries = *total_entries - resume_handle;
971
972         ctr1->array = talloc_zero_array(p->mem_ctx,
973                                    struct srvsvc_NetSessInfo1,
974                                    num_entries);
975
976         W_ERROR_HAVE_NO_MEMORY(ctr1->array);
977
978         for (num_entries = 0; resume_handle < *total_entries; num_entries++, resume_handle++) {
979                 uint32_t connect_time;
980                 bool guest;
981
982                 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
983                 guest = strequal( session_list[resume_handle].username, lp_guest_account() );
984
985                 ctr1->array[num_entries].client         = session_list[resume_handle].remote_machine;
986                 ctr1->array[num_entries].user           = session_list[resume_handle].username;
987                 ctr1->array[num_entries].num_open       = 0;/* computed later */
988                 ctr1->array[num_entries].time           = connect_time;
989                 ctr1->array[num_entries].idle_time      = 0;
990                 ctr1->array[num_entries].user_flags     = guest;
991         }
992
993         ctr1->count = num_entries;
994
995         /* count open files on all sessions in single tdb traversal */
996         net_count_files_for_all_sess(ctr1, session_list,
997                                      resume_handle_p ? *resume_handle_p : 0,
998                                      num_entries);
999
1000         if (resume_handle_p) {
1001                 if (*resume_handle_p >= *total_entries) {
1002                         *resume_handle_p = 0;
1003                 } else {
1004                         *resume_handle_p = resume_handle;
1005                 }
1006         }
1007
1008         return WERR_OK;
1009 }
1010
1011 /*******************************************************************
1012  find the share connection on which this open exists.
1013  ********************************************************************/
1014
1015 static int share_file_fn(struct file_id fid,
1016                          const struct share_mode_data *d,
1017                          const struct share_mode_entry *e,
1018                          void *data)
1019 {
1020         struct share_file_stat *sfs = data;
1021         uint32_t i;
1022         uint32_t offset = sfs->total_entries - sfs->resp_entries;
1023
1024         if (strequal(d->servicepath, sfs->in_sharepath)) {
1025                 for (i=0; i < sfs->resp_entries; i++) {
1026                         if (server_id_equal(
1027                                     &e->pid, &sfs->svrid_arr[offset + i])) {
1028                                 sfs->netconn_arr[i].num_open ++;
1029                                 return 0;
1030                         }
1031                 }
1032         }
1033         return 0;
1034 }
1035
1036 /*******************************************************************
1037  count number of open files on given share connections.
1038  ********************************************************************/
1039
1040 static void count_share_opens(struct srvsvc_NetConnInfo1 *arr,
1041                               struct server_id *svrid_arr, char *sharepath,
1042                               uint32_t resp_entries, uint32_t total_entries)
1043 {
1044         struct share_file_stat sfs;
1045
1046         sfs.netconn_arr = arr;
1047         sfs.svrid_arr = svrid_arr;
1048         sfs.in_sharepath = sharepath;
1049         sfs.resp_entries = resp_entries;
1050         sfs.total_entries = total_entries;
1051
1052         share_entry_forall(share_file_fn, &sfs);
1053 }
1054
1055 /****************************************************************************
1056  process an entry from the connection db.
1057 ****************************************************************************/
1058
1059 static int share_conn_fn(struct smbXsrv_tcon_global0 *tcon,
1060                           void *data)
1061 {
1062         struct share_conn_stat *scs = data;
1063
1064         if (!process_exists(tcon->server_id)) {
1065                 return 0;
1066         }
1067
1068         if (strequal(tcon->share_name, scs->sharename)) {
1069                 scs->svrid_arr = talloc_realloc(scs->ctx, scs->svrid_arr,
1070                                                 struct server_id,
1071                                                 scs->count + 1);
1072                 if (!scs->svrid_arr) {
1073                         return 0;
1074                 }
1075
1076                 scs->svrid_arr[scs->count] = tcon->server_id;
1077                 scs->count++;
1078         }
1079
1080         return 0;
1081 }
1082
1083 /****************************************************************************
1084  Count the connections to a share. Build an array of serverid's owning these
1085  connections.
1086 ****************************************************************************/
1087
1088 static uint32_t count_share_conns(TALLOC_CTX *ctx, const char *sharename,
1089                                   struct server_id **arr)
1090 {
1091         struct share_conn_stat scs;
1092         NTSTATUS status;
1093
1094         scs.ctx = ctx;
1095         scs.sharename = sharename;
1096         scs.svrid_arr = NULL;
1097         scs.count = 0;
1098
1099         status = smbXsrv_tcon_global_traverse(share_conn_fn, &scs);
1100
1101         if (!NT_STATUS_IS_OK(status)) {
1102                 DEBUG(0,("count_share_conns: traverse of "
1103                          "smbXsrv_tcon_global.tdb failed - %s\n",
1104                          nt_errstr(status)));
1105                 return 0;
1106         }
1107
1108         *arr = scs.svrid_arr;
1109         return scs.count;
1110 }
1111
1112 /*******************************************************************
1113  fill in a conn info level 0 structure.
1114  ********************************************************************/
1115
1116 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
1117                                    uint32_t *resume_handle_p,
1118                                    uint32_t *total_entries)
1119 {
1120         uint32_t num_entries = 0;
1121         uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
1122
1123         DEBUG(5,("init_srv_conn_info_0\n"));
1124
1125         if (ctr0 == NULL) {
1126                 if (resume_handle_p) {
1127                         *resume_handle_p = 0;
1128                 }
1129                 return WERR_OK;
1130         }
1131
1132         *total_entries = 1;
1133
1134         ZERO_STRUCTP(ctr0);
1135
1136         for (; resume_handle < *total_entries; resume_handle++) {
1137
1138                 ctr0->array = talloc_realloc(talloc_tos(),
1139                                                    ctr0->array,
1140                                                    struct srvsvc_NetConnInfo0,
1141                                                    num_entries+1);
1142                 if (!ctr0->array) {
1143                         return WERR_NOT_ENOUGH_MEMORY;
1144                 }
1145
1146                 ctr0->array[num_entries].conn_id = *total_entries;
1147
1148                 /* move on to creating next connection */
1149                 num_entries++;
1150         }
1151
1152         ctr0->count = num_entries;
1153         *total_entries = num_entries;
1154
1155         if (resume_handle_p) {
1156                 if (*resume_handle_p >= *total_entries) {
1157                         *resume_handle_p = 0;
1158                 } else {
1159                         *resume_handle_p = resume_handle;
1160                 }
1161         }
1162
1163         return WERR_OK;
1164 }
1165
1166 /*******************************************************************
1167  fill in a conn info level 1 structure.
1168  ********************************************************************/
1169
1170 static WERROR init_srv_conn_info_1(const char *name,
1171                                    struct srvsvc_NetConnCtr1 *ctr1,
1172                                    uint32_t *resume_handle_p,
1173                                    uint32_t *total_entries)
1174 {
1175         const struct loadparm_substitution *lp_sub =
1176                 loadparm_s3_global_substitution();
1177         uint32_t num_entries = 0;
1178         int snum = 0;
1179         uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
1180         char *share_name = NULL;
1181         struct server_id *svrid_arr = NULL;
1182
1183         DEBUG(5,("init_srv_conn_info_1\n"));
1184
1185         if (ctr1 == NULL) {
1186                 if (resume_handle_p) {
1187                         *resume_handle_p = 0;
1188                 }
1189                 return WERR_OK;
1190         }
1191
1192         /* check if this is a server name or a share name */
1193         if (name && (strlen(name) > 2)  && (name[0] == '\\') &&
1194                         (name[1] == '\\')) {
1195
1196                 /* 'name' is a server name - this part is unimplemented */
1197                 *total_entries = 1;
1198         } else {
1199                  /* 'name' is a share name */
1200                 snum = find_service(talloc_tos(), name, &share_name);
1201
1202                 if (!share_name) {
1203                         return WERR_NOT_ENOUGH_MEMORY;
1204                 }
1205
1206                 if (snum < 0) {
1207                         return WERR_INVALID_NAME;
1208                 }
1209
1210                 /*
1211                  * count the num of connections to this share. Also,
1212                  * build a list of serverid's that own these
1213                  * connections. The serverid list is used later to
1214                  * identify the share connection on which an open exists.
1215                  */
1216
1217                 *total_entries = count_share_conns(talloc_tos(),
1218                                                    share_name,
1219                                                    &svrid_arr);
1220         }
1221
1222         if (resume_handle >= *total_entries) {
1223                 if (resume_handle_p) {
1224                         *resume_handle_p = 0;
1225                 }
1226                 return WERR_OK;
1227         }
1228
1229         /*
1230          * We know num_entries must be positive, due to
1231          * the check resume_handle >= *total_entries above.
1232          */
1233
1234         num_entries = *total_entries - resume_handle;
1235
1236         ZERO_STRUCTP(ctr1);
1237
1238         ctr1->array = talloc_zero_array(talloc_tos(),
1239                                         struct srvsvc_NetConnInfo1,
1240                                         num_entries);
1241
1242         W_ERROR_HAVE_NO_MEMORY(ctr1->array);
1243
1244         for (num_entries = 0; resume_handle < *total_entries;
1245                 num_entries++, resume_handle++) {
1246
1247                 ctr1->array[num_entries].conn_id        = *total_entries;
1248                 ctr1->array[num_entries].conn_type      = 0x3;
1249
1250                 /*
1251                  * if these are connections to a share, we are going to
1252                  * compute the opens on them later. If it's for the server,
1253                  * it's unimplemented.
1254                  */
1255
1256                 if (!share_name) {
1257                         ctr1->array[num_entries].num_open = 1;
1258                 }
1259
1260                 ctr1->array[num_entries].num_users      = 1;
1261                 ctr1->array[num_entries].conn_time      = 3;
1262                 ctr1->array[num_entries].user           = "dummy_user";
1263                 ctr1->array[num_entries].share          = "IPC$";
1264         }
1265
1266         /* now compute open files on the share connections */
1267
1268         if (share_name) {
1269
1270                 /*
1271                  * the locking tdb, which has the open files information,
1272                  * does not store share name or share (service) number, but
1273                  * just the share path. So, we can compute open files only
1274                  * on the share path. If more than one shares are  defined
1275                  * on a share path, open files on all of them are included
1276                  * in the count.
1277                  *
1278                  * To have the correct behavior in case multiple shares
1279                  * are defined on the same path, changes to tdb records
1280                  * would be required. That would be lot more effort, so
1281                  * this seems a good stopgap fix.
1282                  */
1283
1284                 count_share_opens(ctr1->array, svrid_arr,
1285                                   lp_path(talloc_tos(), lp_sub, snum),
1286                                   num_entries, *total_entries);
1287
1288         }
1289
1290         ctr1->count = num_entries;
1291         *total_entries = num_entries;
1292
1293         if (resume_handle_p) {
1294                 *resume_handle_p = resume_handle;
1295         }
1296
1297         return WERR_OK;
1298 }
1299
1300 /*******************************************************************
1301  _srvsvc_NetFileEnum
1302 *******************************************************************/
1303
1304 WERROR _srvsvc_NetFileEnum(struct pipes_struct *p,
1305                            struct srvsvc_NetFileEnum *r)
1306 {
1307         TALLOC_CTX *ctx = NULL;
1308         struct srvsvc_NetFileCtr3 *ctr3;
1309         uint32_t resume_hnd = 0;
1310         WERROR werr;
1311
1312         switch (r->in.info_ctr->level) {
1313         case 3:
1314                 break;
1315         default:
1316                 return WERR_INVALID_LEVEL;
1317         }
1318
1319         if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1320                                 p->session_info->security_token)) {
1321                 DEBUG(1, ("Enumerating files only allowed for "
1322                           "administrators\n"));
1323                 return WERR_ACCESS_DENIED;
1324         }
1325
1326         ctx = talloc_tos();
1327         ctr3 = r->in.info_ctr->ctr.ctr3;
1328         if (!ctr3) {
1329                 werr = WERR_INVALID_PARAMETER;
1330                 goto done;
1331         }
1332
1333         /* TODO -- Windows enumerates
1334            (b) active pipes
1335            (c) open directories and files */
1336
1337         werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1338         if (!W_ERROR_IS_OK(werr)) {
1339                 goto done;
1340         }
1341
1342         *r->out.totalentries = ctr3->count;
1343         r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1344         r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1345
1346         werr = WERR_OK;
1347
1348  done:
1349         return werr;
1350 }
1351
1352 /*******************************************************************
1353  _srvsvc_NetSrvGetInfo
1354 ********************************************************************/
1355
1356 WERROR _srvsvc_NetSrvGetInfo(struct pipes_struct *p,
1357                              struct srvsvc_NetSrvGetInfo *r)
1358 {
1359         const struct loadparm_substitution *lp_sub =
1360                 loadparm_s3_global_substitution();
1361         WERROR status = WERR_OK;
1362
1363         DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1364
1365         if (!pipe_access_check(p)) {
1366                 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1367                 return WERR_ACCESS_DENIED;
1368         }
1369
1370         switch (r->in.level) {
1371
1372                 /* Technically level 102 should only be available to
1373                    Administrators but there isn't anything super-secret
1374                    here, as most of it is made up. */
1375
1376         case 102: {
1377                 struct srvsvc_NetSrvInfo102 *info102;
1378
1379                 info102 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1380                 if (!info102) {
1381                         return WERR_NOT_ENOUGH_MEMORY;
1382                 }
1383
1384                 info102->platform_id    = PLATFORM_ID_NT;
1385                 info102->server_name    = lp_netbios_name();
1386                 info102->version_major  = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1387                 info102->version_minor  = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1388                 info102->server_type    = lp_default_server_announce();
1389                 info102->comment        = string_truncate(lp_server_string(talloc_tos(), lp_sub),
1390                                                 MAX_SERVER_STRING_LENGTH);
1391                 info102->users          = 0xffffffff;
1392                 info102->disc           = 0xf;
1393                 info102->hidden         = 0;
1394                 info102->announce       = 240;
1395                 info102->anndelta       = 3000;
1396                 info102->licenses       = 100000;
1397                 info102->userpath       = "C:\\";
1398
1399                 r->out.info->info102 = info102;
1400                 break;
1401         }
1402         case 101: {
1403                 struct srvsvc_NetSrvInfo101 *info101;
1404
1405                 info101 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1406                 if (!info101) {
1407                         return WERR_NOT_ENOUGH_MEMORY;
1408                 }
1409
1410                 info101->platform_id    = PLATFORM_ID_NT;
1411                 info101->server_name    = lp_netbios_name();
1412                 info101->version_major  = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1413                 info101->version_minor  = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1414                 info101->server_type    = lp_default_server_announce();
1415                 info101->comment        = string_truncate(lp_server_string(talloc_tos(), lp_sub),
1416                                                 MAX_SERVER_STRING_LENGTH);
1417
1418                 r->out.info->info101 = info101;
1419                 break;
1420         }
1421         case 100: {
1422                 struct srvsvc_NetSrvInfo100 *info100;
1423
1424                 info100 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1425                 if (!info100) {
1426                         return WERR_NOT_ENOUGH_MEMORY;
1427                 }
1428
1429                 info100->platform_id    = PLATFORM_ID_NT;
1430                 info100->server_name    = lp_netbios_name();
1431
1432                 r->out.info->info100 = info100;
1433
1434                 break;
1435         }
1436         default:
1437                 status = WERR_INVALID_LEVEL;
1438                 break;
1439         }
1440
1441         DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1442
1443         return status;
1444 }
1445
1446 /*******************************************************************
1447  _srvsvc_NetSrvSetInfo
1448 ********************************************************************/
1449
1450 WERROR _srvsvc_NetSrvSetInfo(struct pipes_struct *p,
1451                              struct srvsvc_NetSrvSetInfo *r)
1452 {
1453         WERROR status = WERR_OK;
1454
1455         DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1456
1457         /* Set up the net server set info structure. */
1458
1459         DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1460
1461         return status;
1462 }
1463
1464 /*******************************************************************
1465  _srvsvc_NetConnEnum
1466 ********************************************************************/
1467
1468 WERROR _srvsvc_NetConnEnum(struct pipes_struct *p,
1469                            struct srvsvc_NetConnEnum *r)
1470 {
1471         WERROR werr;
1472
1473         DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1474
1475         if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1476                                 p->session_info->security_token)) {
1477                 DEBUG(1, ("Enumerating connections only allowed for "
1478                           "administrators\n"));
1479                 return WERR_ACCESS_DENIED;
1480         }
1481
1482         switch (r->in.info_ctr->level) {
1483                 case 0:
1484                         werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1485                                                     r->in.resume_handle,
1486                                                     r->out.totalentries);
1487                         break;
1488                 case 1:
1489                         werr = init_srv_conn_info_1(r->in.path,
1490                                                     r->in.info_ctr->ctr.ctr1,
1491                                                     r->in.resume_handle,
1492                                                     r->out.totalentries);
1493                         break;
1494                 default:
1495                         return WERR_INVALID_LEVEL;
1496         }
1497
1498         DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1499
1500         return werr;
1501 }
1502
1503 /*******************************************************************
1504  _srvsvc_NetSessEnum
1505 ********************************************************************/
1506
1507 WERROR _srvsvc_NetSessEnum(struct pipes_struct *p,
1508                            struct srvsvc_NetSessEnum *r)
1509 {
1510         WERROR werr;
1511
1512         DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1513
1514         if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1515                                 p->session_info->security_token)) {
1516                 DEBUG(1, ("Enumerating sessions only allowed for "
1517                           "administrators\n"));
1518                 return WERR_ACCESS_DENIED;
1519         }
1520
1521         switch (r->in.info_ctr->level) {
1522                 case 0:
1523                         werr = init_srv_sess_info_0(p,
1524                                                     r->in.info_ctr->ctr.ctr0,
1525                                                     r->in.resume_handle,
1526                                                     r->out.totalentries);
1527                         break;
1528                 case 1:
1529                         werr = init_srv_sess_info_1(p,
1530                                                     r->in.info_ctr->ctr.ctr1,
1531                                                     r->in.resume_handle,
1532                                                     r->out.totalentries);
1533                         break;
1534                 default:
1535                         return WERR_INVALID_LEVEL;
1536         }
1537
1538         DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1539
1540         return werr;
1541 }
1542
1543 /*******************************************************************
1544  _srvsvc_NetSessDel
1545 ********************************************************************/
1546
1547 WERROR _srvsvc_NetSessDel(struct pipes_struct *p,
1548                           struct srvsvc_NetSessDel *r)
1549 {
1550         struct sessionid *session_list;
1551         int num_sessions, snum;
1552         const char *username;
1553         const char *machine;
1554         bool not_root = False;
1555         WERROR werr;
1556
1557         DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1558
1559         werr = WERR_ACCESS_DENIED;
1560
1561         /* fail out now if you are not root or not a domain admin */
1562
1563         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1564                 ( ! nt_token_check_domain_rid(p->session_info->security_token,
1565                                               DOMAIN_RID_ADMINS))) {
1566
1567                 goto done;
1568         }
1569
1570         username = r->in.user;
1571         machine = r->in.client;
1572
1573         /* strip leading backslashes if any */
1574         if (machine && machine[0] == '\\' && machine[1] == '\\') {
1575                 machine += 2;
1576         }
1577
1578         num_sessions = find_sessions(p->mem_ctx, username, machine,
1579                                      &session_list);
1580
1581         for (snum = 0; snum < num_sessions; snum++) {
1582
1583                 NTSTATUS ntstat;
1584
1585                 if (p->session_info->unix_token->uid != sec_initial_uid()) {
1586                         not_root = True;
1587                         become_root();
1588                 }
1589
1590                 ntstat = messaging_send(p->msg_ctx,
1591                                         session_list[snum].pid,
1592                                         MSG_SHUTDOWN, &data_blob_null);
1593
1594                 if (NT_STATUS_IS_OK(ntstat))
1595                         werr = WERR_OK;
1596
1597                 if (not_root)
1598                         unbecome_root();
1599         }
1600
1601         DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1602
1603 done:
1604
1605         return werr;
1606 }
1607
1608 /*******************************************************************
1609  _srvsvc_NetShareEnumAll
1610 ********************************************************************/
1611
1612 WERROR _srvsvc_NetShareEnumAll(struct pipes_struct *p,
1613                                struct srvsvc_NetShareEnumAll *r)
1614 {
1615         WERROR werr;
1616
1617         DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1618
1619         if (!pipe_access_check(p)) {
1620                 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1621                 return WERR_ACCESS_DENIED;
1622         }
1623
1624         /* Create the list of shares for the response. */
1625         werr = init_srv_share_info_ctr(p,
1626                                        r->in.info_ctr,
1627                                        r->in.resume_handle,
1628                                        r->out.totalentries,
1629                                        true);
1630
1631         DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1632
1633         return werr;
1634 }
1635
1636 /*******************************************************************
1637  _srvsvc_NetShareEnum
1638 ********************************************************************/
1639
1640 WERROR _srvsvc_NetShareEnum(struct pipes_struct *p,
1641                             struct srvsvc_NetShareEnum *r)
1642 {
1643         WERROR werr;
1644
1645         DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1646
1647         if (!pipe_access_check(p)) {
1648                 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1649                 return WERR_ACCESS_DENIED;
1650         }
1651
1652         /* Create the list of shares for the response. */
1653         werr = init_srv_share_info_ctr(p,
1654                                        r->in.info_ctr,
1655                                        r->in.resume_handle,
1656                                        r->out.totalentries,
1657                                        false);
1658
1659         DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1660
1661         return werr;
1662 }
1663
1664 /*******************************************************************
1665  _srvsvc_NetShareGetInfo
1666 ********************************************************************/
1667
1668 WERROR _srvsvc_NetShareGetInfo(struct pipes_struct *p,
1669                                struct srvsvc_NetShareGetInfo *r)
1670 {
1671         WERROR status = WERR_OK;
1672         char *share_name = NULL;
1673         int snum;
1674         union srvsvc_NetShareInfo *info = r->out.info;
1675
1676         DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1677
1678         if (!r->in.share_name) {
1679                 return WERR_INVALID_NAME;
1680         }
1681
1682         snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1683         if (!share_name) {
1684                 return WERR_NOT_ENOUGH_MEMORY;
1685         }
1686         if (snum < 0) {
1687                 return WERR_INVALID_NAME;
1688         }
1689
1690         switch (r->in.level) {
1691                 case 0:
1692                         info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1693                         W_ERROR_HAVE_NO_MEMORY(info->info0);
1694                         init_srv_share_info_0(p, info->info0, snum);
1695                         break;
1696                 case 1:
1697                         info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1698                         W_ERROR_HAVE_NO_MEMORY(info->info1);
1699                         init_srv_share_info_1(p, info->info1, snum);
1700                         break;
1701                 case 2:
1702                         info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1703                         W_ERROR_HAVE_NO_MEMORY(info->info2);
1704                         init_srv_share_info_2(p, info->info2, snum);
1705                         info->info2->current_users =
1706                           count_current_connections(info->info2->name, false);
1707                         break;
1708                 case 501:
1709                         info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1710                         W_ERROR_HAVE_NO_MEMORY(info->info501);
1711                         init_srv_share_info_501(p, info->info501, snum);
1712                         break;
1713                 case 502:
1714                         info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1715                         W_ERROR_HAVE_NO_MEMORY(info->info502);
1716                         init_srv_share_info_502(p, info->info502, snum);
1717                         break;
1718                 case 1004:
1719                         info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1720                         W_ERROR_HAVE_NO_MEMORY(info->info1004);
1721                         init_srv_share_info_1004(p, info->info1004, snum);
1722                         break;
1723                 case 1005:
1724                         info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1725                         W_ERROR_HAVE_NO_MEMORY(info->info1005);
1726                         init_srv_share_info_1005(p, info->info1005, snum);
1727                         break;
1728                 case 1006:
1729                         info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1730                         W_ERROR_HAVE_NO_MEMORY(info->info1006);
1731                         init_srv_share_info_1006(p, info->info1006, snum);
1732                         break;
1733                 case 1007:
1734                         info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1735                         W_ERROR_HAVE_NO_MEMORY(info->info1007);
1736                         init_srv_share_info_1007(p, info->info1007, snum);
1737                         break;
1738                 case 1501:
1739                         init_srv_share_info_1501(p, &info->info1501, snum);
1740                         break;
1741                 default:
1742                         DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1743                                 r->in.level));
1744                         status = WERR_INVALID_LEVEL;
1745                         break;
1746         }
1747
1748         DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1749
1750         return status;
1751 }
1752
1753 /*******************************************************************
1754  _srvsvc_NetShareSetInfo. Modify share details.
1755 ********************************************************************/
1756
1757 WERROR _srvsvc_NetShareSetInfo(struct pipes_struct *p,
1758                                struct srvsvc_NetShareSetInfo *r)
1759 {
1760         const struct loadparm_substitution *lp_sub =
1761                 loadparm_s3_global_substitution();
1762         char *command = NULL;
1763         char *share_name = NULL;
1764         char *comment = NULL;
1765         const char *pathname = NULL;
1766         int type;
1767         int snum;
1768         int ret;
1769         char *path = NULL;
1770         struct security_descriptor *psd = NULL;
1771         bool is_disk_op = False;
1772         const char *csc_policy = NULL;
1773         bool csc_policy_changed = false;
1774         const char *csc_policies[] = {"manual", "documents", "programs",
1775                                       "disable"};
1776         uint32_t client_csc_policy;
1777         int max_connections = 0;
1778         TALLOC_CTX *ctx = p->mem_ctx;
1779         union srvsvc_NetShareInfo *info = r->in.info;
1780
1781         DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1782
1783         if (!r->in.share_name) {
1784                 return WERR_INVALID_NAME;
1785         }
1786
1787         if (r->out.parm_error) {
1788                 *r->out.parm_error = 0;
1789         }
1790
1791         if ( strequal(r->in.share_name,"IPC$")
1792                 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1793                 || strequal(r->in.share_name,"global") )
1794         {
1795                 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s cannot be "
1796                         "modified by a remote user.\n",
1797                         r->in.share_name ));
1798                 return WERR_ACCESS_DENIED;
1799         }
1800
1801         snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1802         if (!share_name) {
1803                 return WERR_NOT_ENOUGH_MEMORY;
1804         }
1805
1806         /* Does this share exist ? */
1807         if (snum < 0)
1808                 return WERR_NERR_NETNAMENOTFOUND;
1809
1810         /* No change to printer shares. */
1811         if (lp_printable(snum))
1812                 return WERR_ACCESS_DENIED;
1813
1814         is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1815
1816         /* fail out now if you are not root and not a disk op */
1817
1818         if ( p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op ) {
1819                 DEBUG(2,("_srvsvc_NetShareSetInfo: uid %u doesn't have the "
1820                         "SeDiskOperatorPrivilege privilege needed to modify "
1821                         "share %s\n",
1822                         (unsigned int)p->session_info->unix_token->uid,
1823                         share_name ));
1824                 return WERR_ACCESS_DENIED;
1825         }
1826
1827         max_connections = lp_max_connections(snum);
1828         csc_policy = csc_policies[lp_csc_policy(snum)];
1829
1830         switch (r->in.level) {
1831         case 1:
1832                 pathname = lp_path(ctx, lp_sub, snum);
1833                 comment = talloc_strdup(ctx, info->info1->comment);
1834                 type = info->info1->type;
1835                 psd = NULL;
1836                 break;
1837         case 2:
1838                 comment = talloc_strdup(ctx, info->info2->comment);
1839                 pathname = info->info2->path;
1840                 type = info->info2->type;
1841                 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1842                         0 : info->info2->max_users;
1843                 psd = NULL;
1844                 break;
1845 #if 0
1846                 /* not supported on set but here for completeness */
1847         case 501:
1848                 comment = talloc_strdup(ctx, info->info501->comment);
1849                 type = info->info501->type;
1850                 psd = NULL;
1851                 break;
1852 #endif
1853         case 502:
1854                 comment = talloc_strdup(ctx, info->info502->comment);
1855                 pathname = info->info502->path;
1856                 type = info->info502->type;
1857                 psd = info->info502->sd_buf.sd;
1858                 map_generic_share_sd_bits(psd);
1859                 break;
1860         case 1004:
1861                 pathname = lp_path(ctx, lp_sub, snum);
1862                 comment = talloc_strdup(ctx, info->info1004->comment);
1863                 type = STYPE_DISKTREE;
1864                 break;
1865         case 1005:
1866                 /* XP re-sets the csc policy even if it wasn't changed by the
1867                    user, so we must compare it to see if it's what is set in
1868                    smb.conf, so that we can contine other ops like setting
1869                    ACLs on a share */
1870                 client_csc_policy = (info->info1005->dfs_flags &
1871                                      SHARE_1005_CSC_POLICY_MASK) >>
1872                                     SHARE_1005_CSC_POLICY_SHIFT;
1873
1874                 if (client_csc_policy == lp_csc_policy(snum))
1875                         return WERR_OK;
1876                 else {
1877                         csc_policy = csc_policies[client_csc_policy];
1878                         csc_policy_changed = true;
1879                 }
1880
1881                 pathname = lp_path(ctx, lp_sub, snum);
1882                 comment = lp_comment(ctx, lp_sub, snum);
1883                 type = STYPE_DISKTREE;
1884                 break;
1885         case 1006:
1886         case 1007:
1887                 return WERR_ACCESS_DENIED;
1888         case 1501:
1889                 pathname = lp_path(ctx, lp_sub, snum);
1890                 comment = lp_comment(ctx, lp_sub, snum);
1891                 psd = info->info1501->sd;
1892                 map_generic_share_sd_bits(psd);
1893                 type = STYPE_DISKTREE;
1894                 break;
1895         default:
1896                 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1897                         r->in.level));
1898                 return WERR_INVALID_LEVEL;
1899         }
1900
1901         /* We can only modify disk shares. */
1902         if (type != STYPE_DISKTREE) {
1903                 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s is not a "
1904                         "disk share\n",
1905                         share_name ));
1906                 return WERR_ACCESS_DENIED;
1907         }
1908
1909         if (comment == NULL) {
1910                 return WERR_NOT_ENOUGH_MEMORY;
1911         }
1912
1913         /* Check if the pathname is valid. */
1914         if (!(path = valid_share_pathname(p->mem_ctx, pathname ))) {
1915                 DEBUG(5,("_srvsvc_NetShareSetInfo: invalid pathname %s\n",
1916                         pathname ));
1917                 return WERR_BAD_PATHNAME;
1918         }
1919
1920         /* Ensure share name, pathname and comment don't contain '"' characters. */
1921         string_replace(share_name, '"', ' ');
1922         string_replace(path, '"', ' ');
1923         string_replace(comment, '"', ' ');
1924
1925         DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1926                 lp_change_share_command(talloc_tos(), lp_sub) ? lp_change_share_command(talloc_tos(), lp_sub) : "NULL" ));
1927
1928         /* Only call modify function if something changed. */
1929
1930         if (strcmp(path, lp_path(talloc_tos(), lp_sub, snum))
1931                         || strcmp(comment, lp_comment(talloc_tos(), lp_sub, snum))
1932                         || (lp_max_connections(snum) != max_connections)
1933                         || csc_policy_changed) {
1934
1935                 if (!lp_change_share_command(talloc_tos(), lp_sub) || !*lp_change_share_command(talloc_tos(), lp_sub)) {
1936                         DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1937                         return WERR_ACCESS_DENIED;
1938                 }
1939
1940                 command = talloc_asprintf(p->mem_ctx,
1941                                 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d \"%s\"",
1942                                 lp_change_share_command(talloc_tos(), lp_sub),
1943                                 get_dyn_CONFIGFILE(),
1944                                 share_name,
1945                                 path,
1946                                 comment,
1947                                 max_connections,
1948                                 csc_policy);
1949                 if (!command) {
1950                         return WERR_NOT_ENOUGH_MEMORY;
1951                 }
1952
1953                 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1954
1955                 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1956
1957                 if (is_disk_op)
1958                         become_root();
1959
1960                 ret = smbrun(command, NULL, NULL);
1961                 if (ret == 0) {
1962                         reload_services(NULL, NULL, false);
1963
1964                         /* Tell everyone we updated smb.conf. */
1965                         messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED,
1966                                            NULL, 0);
1967                 }
1968
1969                 if ( is_disk_op )
1970                         unbecome_root();
1971
1972                 /********* END SeDiskOperatorPrivilege BLOCK *********/
1973
1974                 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1975                         command, ret ));
1976
1977                 TALLOC_FREE(command);
1978
1979                 if ( ret != 0 )
1980                         return WERR_ACCESS_DENIED;
1981         } else {
1982                 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1983                         share_name ));
1984         }
1985
1986         /* Replace SD if changed. */
1987         if (psd) {
1988                 struct security_descriptor *old_sd;
1989                 size_t sd_size;
1990                 NTSTATUS status;
1991
1992                 old_sd = get_share_security(p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
1993
1994                 if (old_sd && !security_descriptor_equal(old_sd, psd)) {
1995                         status = set_share_security(share_name, psd);
1996                         if (!NT_STATUS_IS_OK(status)) {
1997                                 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1998                                         share_name ));
1999                         }
2000                 }
2001         }
2002
2003         DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
2004
2005         return WERR_OK;
2006 }
2007
2008 /*******************************************************************
2009  _srvsvc_NetShareAdd.
2010  Call 'add_share_command "sharename" "pathname"
2011  "comment" "max connections = "
2012 ********************************************************************/
2013
2014 WERROR _srvsvc_NetShareAdd(struct pipes_struct *p,
2015                            struct srvsvc_NetShareAdd *r)
2016 {
2017         char *command = NULL;
2018         char *share_name_in = NULL;
2019         char *share_name = NULL;
2020         char *comment = NULL;
2021         char *pathname = NULL;
2022         int type;
2023         int snum;
2024         int ret;
2025         char *path;
2026         struct security_descriptor *psd = NULL;
2027         bool is_disk_op;
2028         int max_connections = 0;
2029         SMB_STRUCT_STAT st;
2030         TALLOC_CTX *ctx = p->mem_ctx;
2031         const struct loadparm_substitution *lp_sub =
2032                 loadparm_s3_global_substitution();
2033
2034         DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
2035
2036         if (r->out.parm_error) {
2037                 *r->out.parm_error = 0;
2038         }
2039
2040         is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2041
2042         if (p->session_info->unix_token->uid != sec_initial_uid()  && !is_disk_op )
2043                 return WERR_ACCESS_DENIED;
2044
2045         if (!lp_add_share_command(talloc_tos(), lp_sub) || !*lp_add_share_command(talloc_tos(), lp_sub)) {
2046                 DBG_WARNING("_srvsvc_NetShareAdd: No \"add share command\" parameter set in smb.conf.\n");
2047                 return WERR_ACCESS_DENIED;
2048         }
2049
2050         switch (r->in.level) {
2051         case 0:
2052                 /* No path. Not enough info in a level 0 to do anything. */
2053                 return WERR_ACCESS_DENIED;
2054         case 1:
2055                 /* Not enough info in a level 1 to do anything. */
2056                 return WERR_ACCESS_DENIED;
2057         case 2:
2058                 share_name_in = talloc_strdup(ctx, r->in.info->info2->name);
2059                 comment = talloc_strdup(ctx, r->in.info->info2->comment);
2060                 pathname = talloc_strdup(ctx, r->in.info->info2->path);
2061                 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
2062                         0 : r->in.info->info2->max_users;
2063                 type = r->in.info->info2->type;
2064                 break;
2065         case 501:
2066                 /* No path. Not enough info in a level 501 to do anything. */
2067                 return WERR_ACCESS_DENIED;
2068         case 502:
2069                 share_name_in = talloc_strdup(ctx, r->in.info->info502->name);
2070                 comment = talloc_strdup(ctx, r->in.info->info502->comment);
2071                 pathname = talloc_strdup(ctx, r->in.info->info502->path);
2072                 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
2073                         0 : r->in.info->info502->max_users;
2074                 type = r->in.info->info502->type;
2075                 psd = r->in.info->info502->sd_buf.sd;
2076                 map_generic_share_sd_bits(psd);
2077                 break;
2078
2079                 /* none of the following contain share names.  NetShareAdd does not have a separate parameter for the share name */
2080
2081         case 1004:
2082         case 1005:
2083         case 1006:
2084         case 1007:
2085                 return WERR_ACCESS_DENIED;
2086         case 1501:
2087                 /* DFS only level. */
2088                 return WERR_ACCESS_DENIED;
2089         default:
2090                 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
2091                         r->in.level));
2092                 return WERR_INVALID_LEVEL;
2093         }
2094
2095         /* check for invalid share names */
2096
2097         if (!share_name_in || !validate_net_name(share_name_in,
2098                                 INVALID_SHARENAME_CHARS,
2099                                 strlen(share_name_in))) {
2100                 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
2101                                         share_name_in ? share_name_in : ""));
2102                 return WERR_INVALID_NAME;
2103         }
2104
2105         if (strequal(share_name_in,"IPC$") || strequal(share_name_in,"global")
2106                         || (lp_enable_asu_support() &&
2107                                         strequal(share_name_in,"ADMIN$"))) {
2108                 return WERR_ACCESS_DENIED;
2109         }
2110
2111         snum = find_service(ctx, share_name_in, &share_name);
2112         if (!share_name) {
2113                 return WERR_NOT_ENOUGH_MEMORY;
2114         }
2115
2116         /* Share already exists. */
2117         if (snum >= 0) {
2118                 return WERR_FILE_EXISTS;
2119         }
2120
2121         /* We can only add disk shares. */
2122         if (type != STYPE_DISKTREE) {
2123                 return WERR_ACCESS_DENIED;
2124         }
2125
2126         /* Check if the pathname is valid. */
2127         if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
2128                 return WERR_BAD_PATHNAME;
2129         }
2130
2131         ret = sys_lstat(path, &st, false);
2132         if (ret == -1 && (errno != EACCES)) {
2133                 /*
2134                  * If path has any other than permission
2135                  * problem, return WERR_FILE_NOT_FOUND (as Windows
2136                  * does.
2137                  */
2138                 return WERR_FILE_NOT_FOUND;
2139         }
2140
2141         /* Ensure share name, pathname and comment don't contain '"' characters. */
2142         string_replace(share_name_in, '"', ' ');
2143         string_replace(share_name, '"', ' ');
2144         string_replace(path, '"', ' ');
2145         if (comment) {
2146                 string_replace(comment, '"', ' ');
2147         }
2148
2149         command = talloc_asprintf(ctx,
2150                         "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
2151                         lp_add_share_command(talloc_tos(), lp_sub),
2152                         get_dyn_CONFIGFILE(),
2153                         share_name_in,
2154                         path,
2155                         comment ? comment : "",
2156                         max_connections);
2157         if (!command) {
2158                 return WERR_NOT_ENOUGH_MEMORY;
2159         }
2160
2161         DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
2162
2163         /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
2164
2165         if ( is_disk_op )
2166                 become_root();
2167
2168         /* FIXME: use libnetconf here - gd */
2169
2170         ret = smbrun(command, NULL, NULL);
2171         if (ret == 0) {
2172                 /* Tell everyone we updated smb.conf. */
2173                 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
2174         }
2175
2176         if ( is_disk_op )
2177                 unbecome_root();
2178
2179         /********* END SeDiskOperatorPrivilege BLOCK *********/
2180
2181         DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
2182                 command, ret ));
2183
2184         TALLOC_FREE(command);
2185
2186         if ( ret != 0 )
2187                 return WERR_ACCESS_DENIED;
2188
2189         if (psd) {
2190                 NTSTATUS status;
2191                 /* Note we use share_name here, not share_name_in as
2192                    we need a canonicalized name for setting security. */
2193                 status = set_share_security(share_name, psd);
2194                 if (!NT_STATUS_IS_OK(status)) {
2195                         DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
2196                                 share_name ));
2197                 }
2198         }
2199
2200         /*
2201          * We don't call reload_services() here, the message will
2202          * cause this to be done before the next packet is read
2203          * from the client. JRA.
2204          */
2205
2206         DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
2207
2208         return WERR_OK;
2209 }
2210
2211 /*******************************************************************
2212  _srvsvc_NetShareDel
2213  Call "delete share command" with the share name as
2214  a parameter.
2215 ********************************************************************/
2216
2217 WERROR _srvsvc_NetShareDel(struct pipes_struct *p,
2218                            struct srvsvc_NetShareDel *r)
2219 {
2220         char *command = NULL;
2221         char *share_name = NULL;
2222         int ret;
2223         int snum;
2224         bool is_disk_op;
2225         TALLOC_CTX *ctx = p->mem_ctx;
2226         const struct loadparm_substitution *lp_sub =
2227                 loadparm_s3_global_substitution();
2228
2229         DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
2230
2231         if (!r->in.share_name) {
2232                 return WERR_NERR_NETNAMENOTFOUND;
2233         }
2234
2235         if ( strequal(r->in.share_name,"IPC$")
2236                 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
2237                 || strequal(r->in.share_name,"global") )
2238         {
2239                 return WERR_ACCESS_DENIED;
2240         }
2241
2242         snum = find_service(talloc_tos(), r->in.share_name, &share_name);
2243         if (!share_name) {
2244                 return WERR_NOT_ENOUGH_MEMORY;
2245         }
2246
2247         if (snum < 0) {
2248                 return WERR_BAD_NET_NAME;
2249         }
2250
2251         /* No change to printer shares. */
2252         if (lp_printable(snum))
2253                 return WERR_ACCESS_DENIED;
2254
2255         is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2256
2257         if (p->session_info->unix_token->uid != sec_initial_uid()  && !is_disk_op )
2258                 return WERR_ACCESS_DENIED;
2259
2260         if (!lp_delete_share_command(talloc_tos(), lp_sub) || !*lp_delete_share_command(talloc_tos(), lp_sub)) {
2261                 DBG_WARNING("_srvsvc_NetShareDel: No \"delete share command\" parameter set in smb.conf.\n");
2262                 return WERR_ACCESS_DENIED;
2263         }
2264
2265         command = talloc_asprintf(ctx,
2266                         "%s \"%s\" \"%s\"",
2267                         lp_delete_share_command(talloc_tos(), lp_sub),
2268                         get_dyn_CONFIGFILE(),
2269                         share_name);
2270         if (!command) {
2271                 return WERR_NOT_ENOUGH_MEMORY;
2272         }
2273
2274         DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
2275
2276         /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
2277
2278         if ( is_disk_op )
2279                 become_root();
2280
2281         ret = smbrun(command, NULL, NULL);
2282         if (ret == 0) {
2283                 /* Tell everyone we updated smb.conf. */
2284                 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
2285         }
2286
2287         if ( is_disk_op )
2288                 unbecome_root();
2289
2290         /********* END SeDiskOperatorPrivilege BLOCK *********/
2291
2292         DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
2293
2294         if ( ret != 0 )
2295                 return WERR_ACCESS_DENIED;
2296
2297         /* Delete the SD in the database. */
2298         delete_share_security(share_name);
2299
2300         lp_killservice(snum);
2301
2302         return WERR_OK;
2303 }
2304
2305 /*******************************************************************
2306  _srvsvc_NetShareDelSticky
2307 ********************************************************************/
2308
2309 WERROR _srvsvc_NetShareDelSticky(struct pipes_struct *p,
2310                                  struct srvsvc_NetShareDelSticky *r)
2311 {
2312         struct srvsvc_NetShareDel q;
2313
2314         DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
2315
2316         q.in.server_unc         = r->in.server_unc;
2317         q.in.share_name         = r->in.share_name;
2318         q.in.reserved           = r->in.reserved;
2319
2320         return _srvsvc_NetShareDel(p, &q);
2321 }
2322
2323 /*******************************************************************
2324  _srvsvc_NetRemoteTOD
2325 ********************************************************************/
2326
2327 WERROR _srvsvc_NetRemoteTOD(struct pipes_struct *p,
2328                             struct srvsvc_NetRemoteTOD *r)
2329 {
2330         struct srvsvc_NetRemoteTODInfo *tod;
2331         struct tm *t;
2332         time_t unixdate = time(NULL);
2333
2334         /* We do this call first as if we do it *after* the gmtime call
2335            it overwrites the pointed-to values. JRA */
2336
2337         uint32_t zone = get_time_zone(unixdate)/60;
2338
2339         DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2340
2341         if ( !(tod = talloc_zero(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
2342                 return WERR_NOT_ENOUGH_MEMORY;
2343
2344         *r->out.info = tod;
2345
2346         DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2347
2348         t = gmtime(&unixdate);
2349
2350         /* set up the */
2351         tod->elapsed    = unixdate;
2352         tod->msecs      = 0;
2353         tod->hours      = t->tm_hour;
2354         tod->mins       = t->tm_min;
2355         tod->secs       = t->tm_sec;
2356         tod->hunds      = 0;
2357         tod->timezone   = zone;
2358         tod->tinterval  = 10000;
2359         tod->day        = t->tm_mday;
2360         tod->month      = t->tm_mon + 1;
2361         tod->year       = 1900+t->tm_year;
2362         tod->weekday    = t->tm_wday;
2363
2364         DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2365
2366         return WERR_OK;
2367 }
2368
2369 /***********************************************************************************
2370  _srvsvc_NetGetFileSecurity
2371  Win9x NT tools get security descriptor.
2372 ***********************************************************************************/
2373
2374 WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
2375                                   struct srvsvc_NetGetFileSecurity *r)
2376 {
2377         TALLOC_CTX *frame = talloc_stackframe();
2378         const struct loadparm_substitution *lp_sub =
2379                 loadparm_s3_global_substitution();
2380         struct smb_filename *smb_fname = NULL;
2381         size_t sd_size;
2382         char *servicename = NULL;
2383         SMB_STRUCT_STAT st;
2384         NTSTATUS nt_status;
2385         WERROR werr;
2386         struct conn_struct_tos *c = NULL;
2387         connection_struct *conn = NULL;
2388         struct sec_desc_buf *sd_buf = NULL;
2389         files_struct *fsp = NULL;
2390         int snum;
2391         uint32_t ucf_flags = 0;
2392
2393         ZERO_STRUCT(st);
2394
2395         if (!r->in.share) {
2396                 werr = WERR_NERR_NETNAMENOTFOUND;
2397                 goto error_exit;
2398         }
2399         snum = find_service(frame, r->in.share, &servicename);
2400         if (!servicename) {
2401                 werr = WERR_NOT_ENOUGH_MEMORY;
2402                 goto error_exit;
2403         }
2404         if (snum == -1) {
2405                 DEBUG(10, ("Could not find service %s\n", servicename));
2406                 werr = WERR_NERR_NETNAMENOTFOUND;
2407                 goto error_exit;
2408         }
2409
2410         nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
2411                                                snum,
2412                                                lp_path(frame, lp_sub, snum),
2413                                                p->session_info,
2414                                                &c);
2415         if (!NT_STATUS_IS_OK(nt_status)) {
2416                 DEBUG(10, ("create_conn_struct failed: %s\n",
2417                            nt_errstr(nt_status)));
2418                 werr = ntstatus_to_werror(nt_status);
2419                 goto error_exit;
2420         }
2421         conn = c->conn;
2422
2423         nt_status = filename_convert(frame,
2424                                         conn,
2425                                         r->in.file,
2426                                         ucf_flags,
2427                                         0,
2428                                         &smb_fname);
2429         if (!NT_STATUS_IS_OK(nt_status)) {
2430                 werr = ntstatus_to_werror(nt_status);
2431                 goto error_exit;
2432         }
2433
2434         nt_status = SMB_VFS_CREATE_FILE(
2435                 conn,                                   /* conn */
2436                 NULL,                                   /* req */
2437                 smb_fname,                              /* fname */
2438                 FILE_READ_ATTRIBUTES,                   /* access_mask */
2439                 FILE_SHARE_READ|FILE_SHARE_WRITE,       /* share_access */
2440                 FILE_OPEN,                              /* create_disposition*/
2441                 0,                                      /* create_options */
2442                 0,                                      /* file_attributes */
2443                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
2444                 NULL,                                   /* lease */
2445                 0,                                      /* allocation_size */
2446                 0,                                      /* private_flags */
2447                 NULL,                                   /* sd */
2448                 NULL,                                   /* ea_list */
2449                 &fsp,                                   /* result */
2450                 NULL,                                   /* pinfo */
2451                 NULL, NULL);                            /* create context */
2452
2453         if (!NT_STATUS_IS_OK(nt_status)) {
2454                 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2455                          smb_fname_str_dbg(smb_fname)));
2456                 werr = ntstatus_to_werror(nt_status);
2457                 goto error_exit;
2458         }
2459
2460         sd_buf = talloc_zero(p->mem_ctx, struct sec_desc_buf);
2461         if (!sd_buf) {
2462                 werr = WERR_NOT_ENOUGH_MEMORY;
2463                 goto error_exit;
2464         }
2465
2466         nt_status = SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp),
2467                                        (SECINFO_OWNER
2468                                         |SECINFO_GROUP
2469                                         |SECINFO_DACL), sd_buf, &sd_buf->sd);
2470
2471         if (!NT_STATUS_IS_OK(nt_status)) {
2472                 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2473                         "for file %s\n", smb_fname_str_dbg(smb_fname)));
2474                 werr = ntstatus_to_werror(nt_status);
2475                 TALLOC_FREE(sd_buf);
2476                 goto error_exit;
2477         }
2478
2479         if (sd_buf->sd->dacl) {
2480                 sd_buf->sd->dacl->revision = NT4_ACL_REVISION;
2481         }
2482
2483         sd_size = ndr_size_security_descriptor(sd_buf->sd, 0);
2484
2485         sd_buf->sd_size = sd_size;
2486
2487         *r->out.sd_buf = sd_buf;
2488
2489         werr = WERR_OK;
2490
2491 error_exit:
2492
2493         if (fsp) {
2494                 close_file(NULL, fsp, NORMAL_CLOSE);
2495         }
2496
2497         TALLOC_FREE(frame);
2498         return werr;
2499 }
2500
2501 /***********************************************************************************
2502  _srvsvc_NetSetFileSecurity
2503  Win9x NT tools set security descriptor.
2504 ***********************************************************************************/
2505
2506 WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
2507                                   struct srvsvc_NetSetFileSecurity *r)
2508 {
2509         TALLOC_CTX *frame = talloc_stackframe();
2510         const struct loadparm_substitution *lp_sub =
2511                 loadparm_s3_global_substitution();
2512         struct smb_filename *smb_fname = NULL;
2513         char *servicename = NULL;
2514         files_struct *fsp = NULL;
2515         SMB_STRUCT_STAT st;
2516         NTSTATUS nt_status;
2517         WERROR werr;
2518         struct conn_struct_tos *c = NULL;
2519         connection_struct *conn = NULL;
2520         int snum;
2521         struct security_descriptor *psd = NULL;
2522         uint32_t security_info_sent = 0;
2523         uint32_t ucf_flags = 0;
2524
2525         ZERO_STRUCT(st);
2526
2527         if (!r->in.share) {
2528                 werr = WERR_NERR_NETNAMENOTFOUND;
2529                 goto error_exit;
2530         }
2531
2532         snum = find_service(frame, r->in.share, &servicename);
2533         if (!servicename) {
2534                 werr = WERR_NOT_ENOUGH_MEMORY;
2535                 goto error_exit;
2536         }
2537
2538         if (snum == -1) {
2539                 DEBUG(10, ("Could not find service %s\n", servicename));
2540                 werr = WERR_NERR_NETNAMENOTFOUND;
2541                 goto error_exit;
2542         }
2543
2544         nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
2545                                                snum,
2546                                                lp_path(frame, lp_sub, snum),
2547                                                p->session_info,
2548                                                &c);
2549         if (!NT_STATUS_IS_OK(nt_status)) {
2550                 DEBUG(10, ("create_conn_struct failed: %s\n",
2551                            nt_errstr(nt_status)));
2552                 werr = ntstatus_to_werror(nt_status);
2553                 goto error_exit;
2554         }
2555         conn = c->conn;
2556
2557         nt_status = filename_convert(frame,
2558                                         conn,
2559                                         r->in.file,
2560                                         ucf_flags,
2561                                         0,
2562                                         &smb_fname);
2563         if (!NT_STATUS_IS_OK(nt_status)) {
2564                 werr = ntstatus_to_werror(nt_status);
2565                 goto error_exit;
2566         }
2567
2568         nt_status = SMB_VFS_CREATE_FILE(
2569                 conn,                                   /* conn */
2570                 NULL,                                   /* req */
2571                 smb_fname,                              /* fname */
2572                 FILE_WRITE_ATTRIBUTES,                  /* access_mask */
2573                 FILE_SHARE_READ|FILE_SHARE_WRITE,       /* share_access */
2574                 FILE_OPEN,                              /* create_disposition*/
2575                 0,                                      /* create_options */
2576                 0,                                      /* file_attributes */
2577                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
2578                 NULL,                                   /* lease */
2579                 0,                                      /* allocation_size */
2580                 0,                                      /* private_flags */
2581                 NULL,                                   /* sd */
2582                 NULL,                                   /* ea_list */
2583                 &fsp,                                   /* result */
2584                 NULL,                                   /* pinfo */
2585                 NULL, NULL);                            /* create context */
2586
2587         if (!NT_STATUS_IS_OK(nt_status)) {
2588                 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2589                          smb_fname_str_dbg(smb_fname)));
2590                 werr = ntstatus_to_werror(nt_status);
2591                 goto error_exit;
2592         }
2593
2594         psd = r->in.sd_buf->sd;
2595         security_info_sent = r->in.securityinformation;
2596
2597         nt_status = set_sd(fsp, psd, security_info_sent);
2598
2599         if (!NT_STATUS_IS_OK(nt_status) ) {
2600                 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2601                          "on file %s\n", r->in.share));
2602                 werr = WERR_ACCESS_DENIED;
2603                 goto error_exit;
2604         }
2605
2606         werr = WERR_OK;
2607
2608 error_exit:
2609
2610         if (fsp) {
2611                 close_file(NULL, fsp, NORMAL_CLOSE);
2612         }
2613
2614         TALLOC_FREE(frame);
2615         return werr;
2616 }
2617
2618 /***********************************************************************************
2619  It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2620  We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2621  These disks would the disks listed by this function.
2622  Users could then create shares relative to these disks.  Watch out for moving these disks around.
2623  "Nigel Williams" <nigel@veritas.com>.
2624 ***********************************************************************************/
2625
2626 static const char *server_disks[] = {"C:"};
2627
2628 static uint32_t get_server_disk_count(void)
2629 {
2630         return sizeof(server_disks)/sizeof(server_disks[0]);
2631 }
2632
2633 static uint32_t init_server_disk_enum(uint32_t *resume)
2634 {
2635         uint32_t server_disk_count = get_server_disk_count();
2636
2637         /*resume can be an offset into the list for now*/
2638
2639         if(*resume & 0x80000000)
2640                 *resume = 0;
2641
2642         if(*resume > server_disk_count)
2643                 *resume = server_disk_count;
2644
2645         return server_disk_count - *resume;
2646 }
2647
2648 static const char *next_server_disk_enum(uint32_t *resume)
2649 {
2650         const char *disk;
2651
2652         if(init_server_disk_enum(resume) == 0)
2653                 return NULL;
2654
2655         disk = server_disks[*resume];
2656
2657         (*resume)++;
2658
2659         DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2660
2661         return disk;
2662 }
2663
2664 /********************************************************************
2665  _srvsvc_NetDiskEnum
2666 ********************************************************************/
2667
2668 WERROR _srvsvc_NetDiskEnum(struct pipes_struct *p,
2669                            struct srvsvc_NetDiskEnum *r)
2670 {
2671         uint32_t i;
2672         const char *disk_name;
2673         TALLOC_CTX *ctx = p->mem_ctx;
2674         WERROR werr;
2675         uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2676
2677         werr = WERR_OK;
2678
2679         *r->out.totalentries = init_server_disk_enum(&resume);
2680
2681         r->out.info->disks = talloc_zero_array(ctx, struct srvsvc_NetDiskInfo0,
2682                                                MAX_SERVER_DISK_ENTRIES);
2683         W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2684
2685         /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2686
2687         r->out.info->count = 0;
2688
2689         for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2690
2691                 r->out.info->count++;
2692
2693                 /*copy disk name into a unicode string*/
2694
2695                 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2696                 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2697         }
2698
2699         /* add a terminating null string.  Is this there if there is more data to come? */
2700
2701         r->out.info->count++;
2702
2703         r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2704         W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2705
2706         if (r->out.resume_handle) {
2707                 *r->out.resume_handle = resume;
2708         }
2709
2710         return werr;
2711 }
2712
2713 /********************************************************************
2714  _srvsvc_NetNameValidate
2715 ********************************************************************/
2716
2717 WERROR _srvsvc_NetNameValidate(struct pipes_struct *p,
2718                                struct srvsvc_NetNameValidate *r)
2719 {
2720         switch (r->in.name_type) {
2721         case 0x9:
2722                 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2723                                        strlen_m(r->in.name)))
2724                 {
2725                         DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2726                                 r->in.name));
2727                         return WERR_INVALID_NAME;
2728                 }
2729                 break;
2730
2731         default:
2732                 return WERR_INVALID_LEVEL;
2733         }
2734
2735         return WERR_OK;
2736 }
2737
2738 /*******************************************************************
2739 ********************************************************************/
2740
2741 struct enum_file_close_state {
2742         struct srvsvc_NetFileClose *r;
2743         struct messaging_context *msg_ctx;
2744 };
2745
2746 static int enum_file_close_fn(struct file_id id,
2747                               const struct share_mode_data *d,
2748                               const struct share_mode_entry *e,
2749                               void *private_data)
2750 {
2751         char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2752         struct enum_file_close_state *state =
2753                 (struct enum_file_close_state *)private_data;
2754         uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2755
2756         if (fid != state->r->in.fid) {
2757                 return 0; /* Not this file. */
2758         }
2759
2760         if (!process_exists(e->pid) ) {
2761                 return 0;
2762         }
2763
2764         /* Ok - send the close message. */
2765         DBG_DEBUG("request to close file %s, %s\n", d->servicepath,
2766                   share_mode_str(talloc_tos(), 0, &id, e));
2767
2768         share_mode_entry_to_message(msg, &id, e);
2769
2770         state->r->out.result = ntstatus_to_werror(
2771                 messaging_send_buf(state->msg_ctx,
2772                                 e->pid, MSG_SMB_CLOSE_FILE,
2773                                 (uint8_t *)msg, sizeof(msg)));
2774
2775         return 0;
2776 }
2777
2778 /********************************************************************
2779  Close a file given a 32-bit file id.
2780 ********************************************************************/
2781
2782 WERROR _srvsvc_NetFileClose(struct pipes_struct *p,
2783                             struct srvsvc_NetFileClose *r)
2784 {
2785         struct enum_file_close_state state;
2786         bool is_disk_op;
2787
2788         DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2789
2790         is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2791
2792         if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op) {
2793                 return WERR_ACCESS_DENIED;
2794         }
2795
2796         /* enum_file_close_fn sends the close message to
2797          * the relevant smbd process. */
2798
2799         r->out.result = WERR_FILE_NOT_FOUND;
2800         state.r = r;
2801         state.msg_ctx = p->msg_ctx;
2802         share_entry_forall(enum_file_close_fn, &state);
2803         return r->out.result;
2804 }
2805
2806 /********************************************************************
2807 ********************************************************************/
2808
2809 WERROR _srvsvc_NetCharDevEnum(struct pipes_struct *p,
2810                               struct srvsvc_NetCharDevEnum *r)
2811 {
2812         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2813         return WERR_NOT_SUPPORTED;
2814 }
2815
2816 WERROR _srvsvc_NetCharDevGetInfo(struct pipes_struct *p,
2817                                  struct srvsvc_NetCharDevGetInfo *r)
2818 {
2819         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2820         return WERR_NOT_SUPPORTED;
2821 }
2822
2823 WERROR _srvsvc_NetCharDevControl(struct pipes_struct *p,
2824                                  struct srvsvc_NetCharDevControl *r)
2825 {
2826         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2827         return WERR_NOT_SUPPORTED;
2828 }
2829
2830 WERROR _srvsvc_NetCharDevQEnum(struct pipes_struct *p,
2831                                struct srvsvc_NetCharDevQEnum *r)
2832 {
2833         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2834         return WERR_NOT_SUPPORTED;
2835 }
2836
2837 WERROR _srvsvc_NetCharDevQGetInfo(struct pipes_struct *p,
2838                                   struct srvsvc_NetCharDevQGetInfo *r)
2839 {
2840         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2841         return WERR_NOT_SUPPORTED;
2842 }
2843
2844 WERROR _srvsvc_NetCharDevQSetInfo(struct pipes_struct *p,
2845                                   struct srvsvc_NetCharDevQSetInfo *r)
2846 {
2847         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2848         return WERR_NOT_SUPPORTED;
2849 }
2850
2851 WERROR _srvsvc_NetCharDevQPurge(struct pipes_struct *p,
2852                                 struct srvsvc_NetCharDevQPurge *r)
2853 {
2854         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2855         return WERR_NOT_SUPPORTED;
2856 }
2857
2858 WERROR _srvsvc_NetCharDevQPurgeSelf(struct pipes_struct *p,
2859                                     struct srvsvc_NetCharDevQPurgeSelf *r)
2860 {
2861         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2862         return WERR_NOT_SUPPORTED;
2863 }
2864
2865 WERROR _srvsvc_NetFileGetInfo(struct pipes_struct *p,
2866                               struct srvsvc_NetFileGetInfo *r)
2867 {
2868         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2869         return WERR_NOT_SUPPORTED;
2870 }
2871
2872 WERROR _srvsvc_NetShareCheck(struct pipes_struct *p,
2873                              struct srvsvc_NetShareCheck *r)
2874 {
2875         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2876         return WERR_NOT_SUPPORTED;
2877 }
2878
2879 WERROR _srvsvc_NetServerStatisticsGet(struct pipes_struct *p,
2880                                       struct srvsvc_NetServerStatisticsGet *r)
2881 {
2882         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2883         return WERR_NOT_SUPPORTED;
2884 }
2885
2886 WERROR _srvsvc_NetTransportAdd(struct pipes_struct *p,
2887                                struct srvsvc_NetTransportAdd *r)
2888 {
2889         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2890         return WERR_NOT_SUPPORTED;
2891 }
2892
2893 WERROR _srvsvc_NetTransportEnum(struct pipes_struct *p,
2894                                 struct srvsvc_NetTransportEnum *r)
2895 {
2896         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2897         return WERR_NOT_SUPPORTED;
2898 }
2899
2900 WERROR _srvsvc_NetTransportDel(struct pipes_struct *p,
2901                                struct srvsvc_NetTransportDel *r)
2902 {
2903         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2904         return WERR_NOT_SUPPORTED;
2905 }
2906
2907 WERROR _srvsvc_NetSetServiceBits(struct pipes_struct *p,
2908                                  struct srvsvc_NetSetServiceBits *r)
2909 {
2910         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2911         return WERR_NOT_SUPPORTED;
2912 }
2913
2914 WERROR _srvsvc_NetPathType(struct pipes_struct *p,
2915                            struct srvsvc_NetPathType *r)
2916 {
2917         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2918         return WERR_NOT_SUPPORTED;
2919 }
2920
2921 WERROR _srvsvc_NetPathCanonicalize(struct pipes_struct *p,
2922                                    struct srvsvc_NetPathCanonicalize *r)
2923 {
2924         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2925         return WERR_NOT_SUPPORTED;
2926 }
2927
2928 WERROR _srvsvc_NetPathCompare(struct pipes_struct *p,
2929                               struct srvsvc_NetPathCompare *r)
2930 {
2931         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2932         return WERR_NOT_SUPPORTED;
2933 }
2934
2935 WERROR _srvsvc_NETRPRNAMECANONICALIZE(struct pipes_struct *p,
2936                                       struct srvsvc_NETRPRNAMECANONICALIZE *r)
2937 {
2938         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2939         return WERR_NOT_SUPPORTED;
2940 }
2941
2942 WERROR _srvsvc_NetPRNameCompare(struct pipes_struct *p,
2943                                 struct srvsvc_NetPRNameCompare *r)
2944 {
2945         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2946         return WERR_NOT_SUPPORTED;
2947 }
2948
2949 WERROR _srvsvc_NetShareDelStart(struct pipes_struct *p,
2950                                 struct srvsvc_NetShareDelStart *r)
2951 {
2952         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2953         return WERR_NOT_SUPPORTED;
2954 }
2955
2956 WERROR _srvsvc_NetShareDelCommit(struct pipes_struct *p,
2957                                  struct srvsvc_NetShareDelCommit *r)
2958 {
2959         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2960         return WERR_NOT_SUPPORTED;
2961 }
2962
2963 WERROR _srvsvc_NetServerTransportAddEx(struct pipes_struct *p,
2964                                        struct srvsvc_NetServerTransportAddEx *r)
2965 {
2966         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2967         return WERR_NOT_SUPPORTED;
2968 }
2969
2970 WERROR _srvsvc_NetServerSetServiceBitsEx(struct pipes_struct *p,
2971                                          struct srvsvc_NetServerSetServiceBitsEx *r)
2972 {
2973         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2974         return WERR_NOT_SUPPORTED;
2975 }
2976
2977 WERROR _srvsvc_NETRDFSGETVERSION(struct pipes_struct *p,
2978                                  struct srvsvc_NETRDFSGETVERSION *r)
2979 {
2980         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2981         return WERR_NOT_SUPPORTED;
2982 }
2983
2984 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(struct pipes_struct *p,
2985                                            struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2986 {
2987         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2988         return WERR_NOT_SUPPORTED;
2989 }
2990
2991 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(struct pipes_struct *p,
2992                                            struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2993 {
2994         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2995         return WERR_NOT_SUPPORTED;
2996 }
2997
2998 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(struct pipes_struct *p,
2999                                           struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
3000 {
3001         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3002         return WERR_NOT_SUPPORTED;
3003 }
3004
3005 WERROR _srvsvc_NETRDFSSETSERVERINFO(struct pipes_struct *p,
3006                                     struct srvsvc_NETRDFSSETSERVERINFO *r)
3007 {
3008         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3009         return WERR_NOT_SUPPORTED;
3010 }
3011
3012 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(struct pipes_struct *p,
3013                                       struct srvsvc_NETRDFSCREATEEXITPOINT *r)
3014 {
3015         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3016         return WERR_NOT_SUPPORTED;
3017 }
3018
3019 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(struct pipes_struct *p,
3020                                       struct srvsvc_NETRDFSDELETEEXITPOINT *r)
3021 {
3022         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3023         return WERR_NOT_SUPPORTED;
3024 }
3025
3026 WERROR _srvsvc_NETRDFSMODIFYPREFIX(struct pipes_struct *p,
3027                                    struct srvsvc_NETRDFSMODIFYPREFIX *r)
3028 {
3029         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3030         return WERR_NOT_SUPPORTED;
3031 }
3032
3033 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(struct pipes_struct *p,
3034                                      struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
3035 {
3036         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3037         return WERR_NOT_SUPPORTED;
3038 }
3039
3040 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(struct pipes_struct *p,
3041                                             struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
3042 {
3043         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3044         return WERR_NOT_SUPPORTED;
3045 }
3046
3047 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(struct pipes_struct *p,
3048                                         struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
3049 {
3050         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3051         return WERR_NOT_SUPPORTED;
3052 }
3053
3054 /* include the generated boilerplate */
3055 #include "librpc/gen_ndr/ndr_srvsvc_scompat.c"