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