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