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