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.
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.
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.
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/>.
24 /* This is the implementation of the srvsvc pipe. */
27 #include "system/passwd.h"
28 #include "lib/util/server_id.h"
30 #include "librpc/gen_ndr/ndr_srvsvc.h"
31 #include "librpc/gen_ndr/ndr_srvsvc_scompat.h"
32 #include "../libcli/security/security.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "dbwrap/dbwrap.h"
37 #include "../lib/util/util_pw.h"
38 #include "locking/share_mode_lock.h"
39 #include "smbd/smbd.h"
40 #include "smbd/globals.h"
44 #include "lib/global_contexts.h"
45 #include "source3/lib/substitute.h"
47 extern const struct generic_mapping file_generic_mapping;
50 #define DBGC_CLASS DBGC_RPC_SRV
52 #define MAX_SERVER_DISK_ENTRIES 15
54 /* Use for enumerating connections, pipes, & files */
56 struct file_enum_count {
59 struct srvsvc_NetFileCtr3 *ctr3;
63 struct sess_file_info {
64 struct srvsvc_NetSessCtr1 *ctr;
65 struct sessionid *session_list;
66 uint32_t resume_handle;
70 struct share_file_stat {
71 struct srvsvc_NetConnInfo1 *netconn_arr;
72 struct server_id *svrid_arr;
73 const char *in_sharepath;
74 uint32_t resp_entries;
75 uint32_t total_entries;
78 struct share_conn_stat {
80 const char *sharename;
81 struct server_id *svrid_arr;
85 /*******************************************************************
86 ********************************************************************/
88 static int enum_file_fn(struct file_id id,
89 const struct share_mode_data *d,
90 const struct share_mode_entry *e,
93 struct file_enum_count *fenum =
94 (struct file_enum_count *)private_data;
95 struct srvsvc_NetFileCtr3 *ctr3 = fenum->ctr3;
96 struct srvsvc_NetFileInfo3 *f;
97 struct file_id *fids = NULL;
98 char *fullpath = NULL;
100 const char *username;
102 /* If the pid was not found delete the entry from connections.tdb */
104 if ( !process_exists(e->pid) ) {
108 username = uidtoname(e->uid);
110 if ((fenum->username != NULL)
111 && !strequal(username, fenum->username)) {
118 struct srvsvc_NetFileInfo3,
121 DBG_ERR("realloc failed for %"PRIu32" items\n", ctr3->count+1);
126 fids = talloc_realloc(
127 fenum->ctx, fenum->fids, struct file_id, ctr3->count+1);
129 DBG_ERR("realloc failed for %"PRIu32" items\n", ctr3->count+1);
132 fids[ctr3->count] = id;
135 if ( strcmp(d->base_name, "." ) == 0 ) {
136 fullpath = talloc_asprintf(
141 fullpath = talloc_asprintf(
146 (d->stream_name != NULL) ? d->stream_name : "");
151 string_replace( fullpath, '/', '\\' );
153 /* mask out create (what ever that is) */
154 permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
156 /* now fill in the srvsvc_NetFileInfo3 struct */
158 ctr3->array[ctr3->count] = (struct srvsvc_NetFileInfo3) {
159 .fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) |
161 .permissions = permissions,
171 /*******************************************************************
172 ********************************************************************/
174 static WERROR net_enum_files(TALLOC_CTX *ctx,
175 const char *username,
176 struct srvsvc_NetFileCtr3 **ctr3,
179 struct file_enum_count f_enum_cnt = {
180 .ctx = ctx, .username = username, .ctr3 = *ctr3,
184 share_entry_forall(enum_file_fn, (void *)&f_enum_cnt );
186 *ctr3 = f_enum_cnt.ctr3;
188 /* need to count the number of locks on a file */
190 for (i=0; i<(*ctr3)->count; i++) {
191 struct files_struct fsp = { .file_id = f_enum_cnt.fids[i], };
192 struct byte_range_lock *brl = NULL;
194 brl = brl_get_locks(ctx, &fsp);
199 (*ctr3)->array[i].num_locks = brl_num_locks(brl);
207 /*******************************************************************
208 Utility function to get the 'type' of a share from an snum.
209 ********************************************************************/
210 static enum srvsvc_ShareType get_share_type(int snum)
212 /* work out the share type */
213 enum srvsvc_ShareType type = STYPE_DISKTREE;
215 if (lp_printable(snum)) {
216 type = lp_administrative_share(snum)
217 ? STYPE_PRINTQ_HIDDEN : STYPE_PRINTQ;
219 if (strequal(lp_fstype(snum), "IPC")) {
220 type = lp_administrative_share(snum)
221 ? STYPE_IPC_HIDDEN : STYPE_IPC;
226 /*******************************************************************
227 Fill in a share info level 0 structure.
228 ********************************************************************/
230 static void init_srv_share_info_0(struct pipes_struct *p,
231 struct srvsvc_NetShareInfo0 *r, int snum)
233 const struct loadparm_substitution *lp_sub =
234 loadparm_s3_global_substitution();
236 r->name = lp_servicename(talloc_tos(), lp_sub, snum);
239 /*******************************************************************
240 Fill in a share info level 1 structure.
241 ********************************************************************/
243 static void init_srv_share_info_1(struct pipes_struct *p,
244 struct srvsvc_NetShareInfo1 *r,
247 const struct loadparm_substitution *lp_sub =
248 loadparm_s3_global_substitution();
249 char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
250 char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
253 remark = talloc_sub_full(
254 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
255 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
256 p->session_info->unix_token->uid, get_current_username(),
261 r->type = get_share_type(snum);
262 r->comment = remark ? remark : "";
265 /*******************************************************************
266 Fill in a share info level 2 structure.
267 ********************************************************************/
269 static void init_srv_share_info_2(struct pipes_struct *p,
270 struct srvsvc_NetShareInfo2 *r,
273 const struct loadparm_substitution *lp_sub =
274 loadparm_s3_global_substitution();
277 int max_connections = lp_max_connections(snum);
278 uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
279 char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
281 remark = lp_comment(p->mem_ctx, lp_sub, snum);
283 remark = talloc_sub_full(
284 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
285 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
286 p->session_info->unix_token->uid, get_current_username(),
289 path = talloc_asprintf(p->mem_ctx,
290 "C:%s", lp_path(talloc_tos(), lp_sub, snum));
294 * Change / to \\ so that win2k will see it as a valid path.
295 * This was added to enable use of browsing in win2k add
299 string_replace(path, '/', '\\');
303 r->type = get_share_type(snum);
304 r->comment = remark ? remark : "";
306 r->max_users = max_uses;
307 r->current_users = 0; /* computed later */
308 r->path = path ? path : "";
312 /*******************************************************************
313 Map any generic bits to file specific bits.
314 ********************************************************************/
316 static void map_generic_share_sd_bits(struct security_descriptor *psd)
319 struct security_acl *ps_dacl = NULL;
328 for (i = 0; i < ps_dacl->num_aces; i++) {
329 struct security_ace *psa = &ps_dacl->aces[i];
330 uint32_t orig_mask = psa->access_mask;
332 se_map_generic(&psa->access_mask, &file_generic_mapping);
333 psa->access_mask |= orig_mask;
337 /*******************************************************************
338 Fill in a share info level 501 structure.
339 ********************************************************************/
341 static void init_srv_share_info_501(struct pipes_struct *p,
342 struct srvsvc_NetShareInfo501 *r, int snum)
344 const struct loadparm_substitution *lp_sub =
345 loadparm_s3_global_substitution();
346 const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
347 char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
350 remark = talloc_sub_full(
351 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
352 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
353 p->session_info->unix_token->uid, get_current_username(),
358 r->type = get_share_type(snum);
359 r->comment = remark ? remark : "";
362 * According to [MS-SRVS] 2.2.4.25, the flags field is the same as in
365 r->csc_policy = (lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT);
368 /*******************************************************************
369 Fill in a share info level 502 structure.
370 ********************************************************************/
372 static void init_srv_share_info_502(struct pipes_struct *p,
373 struct srvsvc_NetShareInfo502 *r, int snum)
375 const struct loadparm_substitution *lp_sub =
376 loadparm_s3_global_substitution();
377 const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
379 struct security_descriptor *sd = NULL;
380 struct sec_desc_buf *sd_buf = NULL;
382 TALLOC_CTX *ctx = p->mem_ctx;
383 char *remark = lp_comment(ctx, lp_sub, snum);
386 remark = talloc_sub_full(
387 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
388 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
389 p->session_info->unix_token->uid, get_current_username(),
392 path = talloc_asprintf(ctx, "C:%s", lp_path(talloc_tos(), lp_sub, snum));
395 * Change / to \\ so that win2k will see it as a valid path. This was added to
396 * enable use of browsing in win2k add share dialog.
398 string_replace(path, '/', '\\');
401 sd = get_share_security(ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
403 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
406 r->type = get_share_type(snum);
407 r->comment = remark ? remark : "";
409 r->max_users = (uint32_t)-1;
410 r->current_users = 1; /* ??? */
411 r->path = path ? path : "";
416 /***************************************************************************
417 Fill in a share info level 1004 structure.
418 ***************************************************************************/
420 static void init_srv_share_info_1004(struct pipes_struct *p,
421 struct srvsvc_NetShareInfo1004 *r,
424 const struct loadparm_substitution *lp_sub =
425 loadparm_s3_global_substitution();
426 char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
429 remark = talloc_sub_full(
430 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
431 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
432 p->session_info->unix_token->uid, get_current_username(),
436 r->comment = remark ? remark : "";
439 /***************************************************************************
440 Fill in a share info level 1005 structure.
441 ***************************************************************************/
443 static void init_srv_share_info_1005(struct pipes_struct *p,
444 struct srvsvc_NetShareInfo1005 *r,
447 uint32_t dfs_flags = 0;
449 if (lp_host_msdfs() && lp_msdfs_root(snum)) {
450 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
453 dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
455 r->dfs_flags = dfs_flags;
458 /***************************************************************************
459 Fill in a share info level 1006 structure.
460 ***************************************************************************/
462 static void init_srv_share_info_1006(struct pipes_struct *p,
463 struct srvsvc_NetShareInfo1006 *r,
466 r->max_users = (uint32_t)-1;
469 /***************************************************************************
470 Fill in a share info level 1007 structure.
471 ***************************************************************************/
473 static void init_srv_share_info_1007(struct pipes_struct *p,
474 struct srvsvc_NetShareInfo1007 *r,
478 r->alternate_directory_name = "";
481 /*******************************************************************
482 Fill in a share info level 1501 structure.
483 ********************************************************************/
485 static void init_srv_share_info_1501(struct pipes_struct *p,
486 struct sec_desc_buf **r,
489 const struct loadparm_substitution *lp_sub =
490 loadparm_s3_global_substitution();
491 struct security_descriptor *sd;
492 struct sec_desc_buf *sd_buf = NULL;
494 TALLOC_CTX *ctx = p->mem_ctx;
496 sd = get_share_security(ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
498 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
504 /*******************************************************************
505 True if it ends in '$'.
506 ********************************************************************/
508 static bool is_hidden_share(int snum)
510 const struct loadparm_substitution *lp_sub =
511 loadparm_s3_global_substitution();
512 const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
514 return (net_name[strlen(net_name) - 1] == '$') ? True : False;
517 /*******************************************************************
518 Verify user is allowed to view share, access based enumeration
519 ********************************************************************/
520 static bool is_enumeration_allowed(struct pipes_struct *p,
523 const struct loadparm_substitution *lp_sub =
524 loadparm_s3_global_substitution();
526 if (!lp_access_based_share_enum(snum)) {
530 if (!user_ok_token(p->session_info->unix_info->unix_name,
531 p->session_info->info->domain_name,
532 p->session_info->security_token, snum)) {
536 return share_access_check(p->session_info->security_token,
537 lp_servicename(talloc_tos(), lp_sub, snum),
538 FILE_READ_DATA, NULL);
541 /****************************************************************************
542 Count an entry against the respective service.
543 ****************************************************************************/
545 static int count_for_all_fn(struct smbXsrv_tcon_global0 *tcon, void *udp)
547 union srvsvc_NetShareCtr *ctr = NULL;
548 struct srvsvc_NetShareInfo2 *info2 = NULL;
549 int share_entries = 0;
552 ctr = (union srvsvc_NetShareCtr *) udp;
555 share_entries = ctr->ctr2->count;
556 info2 = &ctr->ctr2->array[0];
558 for (i = 0; i < share_entries; i++, info2++) {
559 if (strequal(tcon->share_name, info2->name)) {
560 info2->current_users++;
568 /****************************************************************************
569 Count the entries belonging to all services in the connection db.
570 ****************************************************************************/
572 static void count_connections_for_all_shares(union srvsvc_NetShareCtr *ctr)
575 status = smbXsrv_tcon_global_traverse(count_for_all_fn, ctr);
577 if (!NT_STATUS_IS_OK(status)) {
578 DEBUG(0,("count_connections_for_all_shares: traverse of "
579 "smbXsrv_tcon_global.tdb failed - %s\n",
584 /*******************************************************************
585 Fill in a share info structure.
586 ********************************************************************/
588 static WERROR init_srv_share_info_ctr(struct pipes_struct *p,
589 struct srvsvc_NetShareInfoCtr *info_ctr,
590 uint32_t *resume_handle_p,
591 uint32_t *total_entries,
594 const struct loadparm_substitution *lp_sub =
595 loadparm_s3_global_substitution();
596 uint32_t num_entries = 0;
597 uint32_t alloc_entries = 0;
598 int num_services = 0;
600 TALLOC_CTX *ctx = p->mem_ctx;
602 uint32_t valid_share_count = 0;
604 union srvsvc_NetShareCtr ctr;
605 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
607 DEBUG(5,("init_srv_share_info_ctr\n"));
609 /* Ensure all the usershares are loaded. */
611 delete_and_reload_printers();
612 load_usershare_shares(NULL, connections_snum_used);
613 load_registry_shares();
614 num_services = lp_numservices();
617 allowed = talloc_zero_array(ctx, bool, num_services);
618 W_ERROR_HAVE_NO_MEMORY(allowed);
620 /* Count the number of entries. */
621 for (snum = 0; snum < num_services; snum++) {
622 if (lp_browseable(snum) && lp_snum_ok(snum) &&
623 is_enumeration_allowed(p, snum) &&
624 (all_shares || !is_hidden_share(snum)) ) {
625 DEBUG(10, ("counting service %s\n",
626 lp_servicename(talloc_tos(), lp_sub, snum) ? lp_servicename(talloc_tos(), lp_sub, snum) : "(null)"));
627 allowed[snum] = true;
630 DEBUG(10, ("NOT counting service %s\n",
631 lp_servicename(talloc_tos(), lp_sub, snum) ? lp_servicename(talloc_tos(), lp_sub, snum) : "(null)"));
635 if (!num_entries || (resume_handle >= num_entries)) {
639 /* Calculate alloc entries. */
640 alloc_entries = num_entries - resume_handle;
641 switch (info_ctr->level) {
643 ctr.ctr0 = talloc_zero(ctx, struct srvsvc_NetShareCtr0);
644 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
646 ctr.ctr0->count = alloc_entries;
647 ctr.ctr0->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
648 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
650 for (snum = 0; snum < num_services; snum++) {
652 (resume_handle <= (i + valid_share_count++)) ) {
653 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
660 ctr.ctr1 = talloc_zero(ctx, struct srvsvc_NetShareCtr1);
661 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
663 ctr.ctr1->count = alloc_entries;
664 ctr.ctr1->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
665 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
667 for (snum = 0; snum < num_services; snum++) {
669 (resume_handle <= (i + valid_share_count++)) ) {
670 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
677 ctr.ctr2 = talloc_zero(ctx, struct srvsvc_NetShareCtr2);
678 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
680 ctr.ctr2->count = alloc_entries;
681 ctr.ctr2->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
682 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
684 for (snum = 0; snum < num_services; snum++) {
686 (resume_handle <= (i + valid_share_count++)) ) {
687 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
691 count_connections_for_all_shares(&ctr);
695 ctr.ctr501 = talloc_zero(ctx, struct srvsvc_NetShareCtr501);
696 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
698 ctr.ctr501->count = alloc_entries;
699 ctr.ctr501->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
700 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
702 for (snum = 0; snum < num_services; snum++) {
704 (resume_handle <= (i + valid_share_count++)) ) {
705 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
712 ctr.ctr502 = talloc_zero(ctx, struct srvsvc_NetShareCtr502);
713 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
715 ctr.ctr502->count = alloc_entries;
716 ctr.ctr502->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
717 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
719 for (snum = 0; snum < num_services; snum++) {
721 (resume_handle <= (i + valid_share_count++)) ) {
722 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
729 ctr.ctr1004 = talloc_zero(ctx, struct srvsvc_NetShareCtr1004);
730 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
732 ctr.ctr1004->count = alloc_entries;
733 ctr.ctr1004->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
734 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
736 for (snum = 0; snum < num_services; snum++) {
738 (resume_handle <= (i + valid_share_count++)) ) {
739 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
746 ctr.ctr1005 = talloc_zero(ctx, struct srvsvc_NetShareCtr1005);
747 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
749 ctr.ctr1005->count = alloc_entries;
750 ctr.ctr1005->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
751 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
753 for (snum = 0; snum < num_services; snum++) {
755 (resume_handle <= (i + valid_share_count++)) ) {
756 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
763 ctr.ctr1006 = talloc_zero(ctx, struct srvsvc_NetShareCtr1006);
764 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
766 ctr.ctr1006->count = alloc_entries;
767 ctr.ctr1006->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
768 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
770 for (snum = 0; snum < num_services; snum++) {
772 (resume_handle <= (i + valid_share_count++)) ) {
773 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
780 ctr.ctr1007 = talloc_zero(ctx, struct srvsvc_NetShareCtr1007);
781 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
783 ctr.ctr1007->count = alloc_entries;
784 ctr.ctr1007->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
785 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
787 for (snum = 0; snum < num_services; snum++) {
789 (resume_handle <= (i + valid_share_count++)) ) {
790 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
797 ctr.ctr1501 = talloc_zero(ctx, struct srvsvc_NetShareCtr1501);
798 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
800 ctr.ctr1501->count = alloc_entries;
801 ctr.ctr1501->array = talloc_zero_array(ctx, struct sec_desc_buf, alloc_entries);
802 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
804 for (snum = 0; snum < num_services; snum++) {
806 (resume_handle <= (i + valid_share_count++)) ) {
807 struct sec_desc_buf *sd_buf = NULL;
808 init_srv_share_info_1501(p, &sd_buf, snum);
809 ctr.ctr1501->array[i++] = *sd_buf;
816 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
818 return WERR_INVALID_LEVEL;
821 *total_entries = alloc_entries;
822 if (resume_handle_p) {
824 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
826 *resume_handle_p = num_entries;
835 /*******************************************************************
836 fill in a sess info level 0 structure.
837 ********************************************************************/
839 static WERROR init_srv_sess_info_0(struct pipes_struct *p,
840 struct srvsvc_NetSessCtr0 *ctr0,
841 uint32_t *resume_handle_p,
842 uint32_t *total_entries)
844 struct sessionid *session_list;
845 uint32_t num_entries = 0;
846 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
847 *total_entries = list_sessions(p->mem_ctx, &session_list);
849 DEBUG(5,("init_srv_sess_info_0\n"));
852 if (resume_handle_p) {
853 *resume_handle_p = 0;
858 for (; resume_handle < *total_entries; resume_handle++) {
860 ctr0->array = talloc_realloc(p->mem_ctx,
862 struct srvsvc_NetSessInfo0,
864 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
866 ctr0->array[num_entries].client =
867 session_list[resume_handle].remote_machine;
872 ctr0->count = num_entries;
874 if (resume_handle_p) {
875 if (*resume_handle_p >= *total_entries) {
876 *resume_handle_p = 0;
878 *resume_handle_p = resume_handle;
885 /***********************************************************************
886 * find out the session on which this file is open and bump up its count
887 **********************************************************************/
889 static int count_sess_files_fn(struct file_id fid,
890 const struct share_mode_data *d,
891 const struct share_mode_entry *e,
894 struct sess_file_info *info = data;
895 uint32_t rh = info->resume_handle;
898 for (i=0; i < info->num_entries; i++) {
899 /* rh+info->num_entries is safe, as we've
901 *total_entries > resume_handle &&
902 info->num_entries = *total_entries - resume_handle;
903 inside init_srv_sess_info_1() below.
905 struct sessionid *sess = &info->session_list[rh + i];
906 if ((e->uid == sess->uid) &&
907 server_id_equal(&e->pid, &sess->pid)) {
909 info->ctr->array[i].num_open++;
916 /*******************************************************************
917 * count the num of open files on all sessions
918 *******************************************************************/
920 static void net_count_files_for_all_sess(struct srvsvc_NetSessCtr1 *ctr1,
921 struct sessionid *session_list,
922 uint32_t resume_handle,
923 uint32_t num_entries)
925 struct sess_file_info s_file_info;
927 s_file_info.ctr = ctr1;
928 s_file_info.session_list = session_list;
929 s_file_info.resume_handle = resume_handle;
930 s_file_info.num_entries = num_entries;
932 share_entry_forall(count_sess_files_fn, &s_file_info);
935 /*******************************************************************
936 fill in a sess info level 1 structure.
937 ********************************************************************/
939 static WERROR init_srv_sess_info_1(struct pipes_struct *p,
940 struct srvsvc_NetSessCtr1 *ctr1,
941 uint32_t *resume_handle_p,
942 uint32_t *total_entries)
944 struct sessionid *session_list;
945 uint32_t num_entries = 0;
946 time_t now = time(NULL);
947 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
952 if (resume_handle_p) {
953 *resume_handle_p = 0;
958 *total_entries = list_sessions(p->mem_ctx, &session_list);
960 if (resume_handle >= *total_entries) {
961 if (resume_handle_p) {
962 *resume_handle_p = 0;
967 /* We know num_entries must be positive, due to
968 the check resume_handle >= *total_entries above. */
970 num_entries = *total_entries - resume_handle;
972 ctr1->array = talloc_zero_array(p->mem_ctx,
973 struct srvsvc_NetSessInfo1,
976 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
978 for (num_entries = 0; resume_handle < *total_entries; num_entries++, resume_handle++) {
979 uint32_t connect_time;
982 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
983 guest = strequal( session_list[resume_handle].username, lp_guest_account() );
985 ctr1->array[num_entries].client = session_list[resume_handle].remote_machine;
986 ctr1->array[num_entries].user = session_list[resume_handle].username;
987 ctr1->array[num_entries].num_open = 0;/* computed later */
988 ctr1->array[num_entries].time = connect_time;
989 ctr1->array[num_entries].idle_time = 0;
990 ctr1->array[num_entries].user_flags = guest;
993 ctr1->count = num_entries;
995 /* count open files on all sessions in single tdb traversal */
996 net_count_files_for_all_sess(ctr1, session_list,
997 resume_handle_p ? *resume_handle_p : 0,
1000 if (resume_handle_p) {
1001 if (*resume_handle_p >= *total_entries) {
1002 *resume_handle_p = 0;
1004 *resume_handle_p = resume_handle;
1011 /*******************************************************************
1012 find the share connection on which this open exists.
1013 ********************************************************************/
1015 static int share_file_fn(struct file_id fid,
1016 const struct share_mode_data *d,
1017 const struct share_mode_entry *e,
1020 struct share_file_stat *sfs = data;
1022 uint32_t offset = sfs->total_entries - sfs->resp_entries;
1024 if (strequal(d->servicepath, sfs->in_sharepath)) {
1025 for (i=0; i < sfs->resp_entries; i++) {
1026 if (server_id_equal(
1027 &e->pid, &sfs->svrid_arr[offset + i])) {
1028 sfs->netconn_arr[i].num_open ++;
1036 /*******************************************************************
1037 count number of open files on given share connections.
1038 ********************************************************************/
1040 static void count_share_opens(struct srvsvc_NetConnInfo1 *arr,
1041 struct server_id *svrid_arr, char *sharepath,
1042 uint32_t resp_entries, uint32_t total_entries)
1044 struct share_file_stat sfs;
1046 sfs.netconn_arr = arr;
1047 sfs.svrid_arr = svrid_arr;
1048 sfs.in_sharepath = sharepath;
1049 sfs.resp_entries = resp_entries;
1050 sfs.total_entries = total_entries;
1052 share_entry_forall(share_file_fn, &sfs);
1055 /****************************************************************************
1056 process an entry from the connection db.
1057 ****************************************************************************/
1059 static int share_conn_fn(struct smbXsrv_tcon_global0 *tcon,
1062 struct share_conn_stat *scs = data;
1064 if (!process_exists(tcon->server_id)) {
1068 if (strequal(tcon->share_name, scs->sharename)) {
1069 scs->svrid_arr = talloc_realloc(scs->ctx, scs->svrid_arr,
1072 if (!scs->svrid_arr) {
1076 scs->svrid_arr[scs->count] = tcon->server_id;
1083 /****************************************************************************
1084 Count the connections to a share. Build an array of serverid's owning these
1086 ****************************************************************************/
1088 static uint32_t count_share_conns(TALLOC_CTX *ctx, const char *sharename,
1089 struct server_id **arr)
1091 struct share_conn_stat scs;
1095 scs.sharename = sharename;
1096 scs.svrid_arr = NULL;
1099 status = smbXsrv_tcon_global_traverse(share_conn_fn, &scs);
1101 if (!NT_STATUS_IS_OK(status)) {
1102 DEBUG(0,("count_share_conns: traverse of "
1103 "smbXsrv_tcon_global.tdb failed - %s\n",
1104 nt_errstr(status)));
1108 *arr = scs.svrid_arr;
1112 /*******************************************************************
1113 fill in a conn info level 0 structure.
1114 ********************************************************************/
1116 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
1117 uint32_t *resume_handle_p,
1118 uint32_t *total_entries)
1120 uint32_t num_entries = 0;
1121 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
1123 DEBUG(5,("init_srv_conn_info_0\n"));
1126 if (resume_handle_p) {
1127 *resume_handle_p = 0;
1136 for (; resume_handle < *total_entries; resume_handle++) {
1138 ctr0->array = talloc_realloc(talloc_tos(),
1140 struct srvsvc_NetConnInfo0,
1143 return WERR_NOT_ENOUGH_MEMORY;
1146 ctr0->array[num_entries].conn_id = *total_entries;
1148 /* move on to creating next connection */
1152 ctr0->count = num_entries;
1153 *total_entries = num_entries;
1155 if (resume_handle_p) {
1156 if (*resume_handle_p >= *total_entries) {
1157 *resume_handle_p = 0;
1159 *resume_handle_p = resume_handle;
1166 /*******************************************************************
1167 fill in a conn info level 1 structure.
1168 ********************************************************************/
1170 static WERROR init_srv_conn_info_1(const char *name,
1171 struct srvsvc_NetConnCtr1 *ctr1,
1172 uint32_t *resume_handle_p,
1173 uint32_t *total_entries)
1175 const struct loadparm_substitution *lp_sub =
1176 loadparm_s3_global_substitution();
1177 uint32_t num_entries = 0;
1179 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
1180 char *share_name = NULL;
1181 struct server_id *svrid_arr = NULL;
1183 DEBUG(5,("init_srv_conn_info_1\n"));
1186 if (resume_handle_p) {
1187 *resume_handle_p = 0;
1192 /* check if this is a server name or a share name */
1193 if (name && (strlen(name) > 2) && (name[0] == '\\') &&
1194 (name[1] == '\\')) {
1196 /* 'name' is a server name - this part is unimplemented */
1199 /* 'name' is a share name */
1200 snum = find_service(talloc_tos(), name, &share_name);
1203 return WERR_NOT_ENOUGH_MEMORY;
1207 return WERR_INVALID_NAME;
1211 * count the num of connections to this share. Also,
1212 * build a list of serverid's that own these
1213 * connections. The serverid list is used later to
1214 * identify the share connection on which an open exists.
1217 *total_entries = count_share_conns(talloc_tos(),
1222 if (resume_handle >= *total_entries) {
1223 if (resume_handle_p) {
1224 *resume_handle_p = 0;
1230 * We know num_entries must be positive, due to
1231 * the check resume_handle >= *total_entries above.
1234 num_entries = *total_entries - resume_handle;
1238 ctr1->array = talloc_zero_array(talloc_tos(),
1239 struct srvsvc_NetConnInfo1,
1242 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
1244 for (num_entries = 0; resume_handle < *total_entries;
1245 num_entries++, resume_handle++) {
1247 ctr1->array[num_entries].conn_id = *total_entries;
1248 ctr1->array[num_entries].conn_type = 0x3;
1251 * if these are connections to a share, we are going to
1252 * compute the opens on them later. If it's for the server,
1253 * it's unimplemented.
1257 ctr1->array[num_entries].num_open = 1;
1260 ctr1->array[num_entries].num_users = 1;
1261 ctr1->array[num_entries].conn_time = 3;
1262 ctr1->array[num_entries].user = "dummy_user";
1263 ctr1->array[num_entries].share = "IPC$";
1266 /* now compute open files on the share connections */
1271 * the locking tdb, which has the open files information,
1272 * does not store share name or share (service) number, but
1273 * just the share path. So, we can compute open files only
1274 * on the share path. If more than one shares are defined
1275 * on a share path, open files on all of them are included
1278 * To have the correct behavior in case multiple shares
1279 * are defined on the same path, changes to tdb records
1280 * would be required. That would be lot more effort, so
1281 * this seems a good stopgap fix.
1284 count_share_opens(ctr1->array, svrid_arr,
1285 lp_path(talloc_tos(), lp_sub, snum),
1286 num_entries, *total_entries);
1290 ctr1->count = num_entries;
1291 *total_entries = num_entries;
1293 if (resume_handle_p) {
1294 *resume_handle_p = resume_handle;
1300 /*******************************************************************
1302 *******************************************************************/
1304 WERROR _srvsvc_NetFileEnum(struct pipes_struct *p,
1305 struct srvsvc_NetFileEnum *r)
1307 TALLOC_CTX *ctx = NULL;
1308 struct srvsvc_NetFileCtr3 *ctr3;
1309 uint32_t resume_hnd = 0;
1312 switch (r->in.info_ctr->level) {
1316 return WERR_INVALID_LEVEL;
1319 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1320 p->session_info->security_token)) {
1321 DEBUG(1, ("Enumerating files only allowed for "
1322 "administrators\n"));
1323 return WERR_ACCESS_DENIED;
1327 ctr3 = r->in.info_ctr->ctr.ctr3;
1329 werr = WERR_INVALID_PARAMETER;
1333 /* TODO -- Windows enumerates
1335 (c) open directories and files */
1337 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1338 if (!W_ERROR_IS_OK(werr)) {
1342 *r->out.totalentries = ctr3->count;
1343 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1344 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1352 /*******************************************************************
1353 _srvsvc_NetSrvGetInfo
1354 ********************************************************************/
1356 WERROR _srvsvc_NetSrvGetInfo(struct pipes_struct *p,
1357 struct srvsvc_NetSrvGetInfo *r)
1359 const struct loadparm_substitution *lp_sub =
1360 loadparm_s3_global_substitution();
1361 WERROR status = WERR_OK;
1363 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1365 if (!pipe_access_check(p)) {
1366 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1367 return WERR_ACCESS_DENIED;
1370 switch (r->in.level) {
1372 /* Technically level 102 should only be available to
1373 Administrators but there isn't anything super-secret
1374 here, as most of it is made up. */
1377 struct srvsvc_NetSrvInfo102 *info102;
1379 info102 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1381 return WERR_NOT_ENOUGH_MEMORY;
1384 info102->platform_id = PLATFORM_ID_NT;
1385 info102->server_name = lp_netbios_name();
1386 info102->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1387 info102->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1388 info102->server_type = lp_default_server_announce();
1389 info102->comment = string_truncate(lp_server_string(talloc_tos(), lp_sub),
1390 MAX_SERVER_STRING_LENGTH);
1391 info102->users = 0xffffffff;
1392 info102->disc = 0xf;
1393 info102->hidden = 0;
1394 info102->announce = 240;
1395 info102->anndelta = 3000;
1396 info102->licenses = 100000;
1397 info102->userpath = "C:\\";
1399 r->out.info->info102 = info102;
1403 struct srvsvc_NetSrvInfo101 *info101;
1405 info101 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1407 return WERR_NOT_ENOUGH_MEMORY;
1410 info101->platform_id = PLATFORM_ID_NT;
1411 info101->server_name = lp_netbios_name();
1412 info101->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1413 info101->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1414 info101->server_type = lp_default_server_announce();
1415 info101->comment = string_truncate(lp_server_string(talloc_tos(), lp_sub),
1416 MAX_SERVER_STRING_LENGTH);
1418 r->out.info->info101 = info101;
1422 struct srvsvc_NetSrvInfo100 *info100;
1424 info100 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1426 return WERR_NOT_ENOUGH_MEMORY;
1429 info100->platform_id = PLATFORM_ID_NT;
1430 info100->server_name = lp_netbios_name();
1432 r->out.info->info100 = info100;
1437 status = WERR_INVALID_LEVEL;
1441 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1446 /*******************************************************************
1447 _srvsvc_NetSrvSetInfo
1448 ********************************************************************/
1450 WERROR _srvsvc_NetSrvSetInfo(struct pipes_struct *p,
1451 struct srvsvc_NetSrvSetInfo *r)
1453 WERROR status = WERR_OK;
1455 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1457 /* Set up the net server set info structure. */
1459 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1464 /*******************************************************************
1466 ********************************************************************/
1468 WERROR _srvsvc_NetConnEnum(struct pipes_struct *p,
1469 struct srvsvc_NetConnEnum *r)
1473 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1475 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1476 p->session_info->security_token)) {
1477 DEBUG(1, ("Enumerating connections only allowed for "
1478 "administrators\n"));
1479 return WERR_ACCESS_DENIED;
1482 switch (r->in.info_ctr->level) {
1484 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1485 r->in.resume_handle,
1486 r->out.totalentries);
1489 werr = init_srv_conn_info_1(r->in.path,
1490 r->in.info_ctr->ctr.ctr1,
1491 r->in.resume_handle,
1492 r->out.totalentries);
1495 return WERR_INVALID_LEVEL;
1498 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1503 /*******************************************************************
1505 ********************************************************************/
1507 WERROR _srvsvc_NetSessEnum(struct pipes_struct *p,
1508 struct srvsvc_NetSessEnum *r)
1512 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1514 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1515 p->session_info->security_token)) {
1516 DEBUG(1, ("Enumerating sessions only allowed for "
1517 "administrators\n"));
1518 return WERR_ACCESS_DENIED;
1521 switch (r->in.info_ctr->level) {
1523 werr = init_srv_sess_info_0(p,
1524 r->in.info_ctr->ctr.ctr0,
1525 r->in.resume_handle,
1526 r->out.totalentries);
1529 werr = init_srv_sess_info_1(p,
1530 r->in.info_ctr->ctr.ctr1,
1531 r->in.resume_handle,
1532 r->out.totalentries);
1535 return WERR_INVALID_LEVEL;
1538 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1543 /*******************************************************************
1545 ********************************************************************/
1547 WERROR _srvsvc_NetSessDel(struct pipes_struct *p,
1548 struct srvsvc_NetSessDel *r)
1550 struct sessionid *session_list;
1551 int num_sessions, snum;
1552 const char *username;
1553 const char *machine;
1554 bool not_root = False;
1557 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1559 werr = WERR_ACCESS_DENIED;
1561 /* fail out now if you are not root or not a domain admin */
1563 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1564 ( ! nt_token_check_domain_rid(p->session_info->security_token,
1565 DOMAIN_RID_ADMINS))) {
1570 username = r->in.user;
1571 machine = r->in.client;
1573 /* strip leading backslashes if any */
1574 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1578 num_sessions = find_sessions(p->mem_ctx, username, machine,
1581 for (snum = 0; snum < num_sessions; snum++) {
1585 if (p->session_info->unix_token->uid != sec_initial_uid()) {
1590 ntstat = messaging_send(p->msg_ctx,
1591 session_list[snum].pid,
1592 MSG_SHUTDOWN, &data_blob_null);
1594 if (NT_STATUS_IS_OK(ntstat))
1601 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1608 /*******************************************************************
1609 _srvsvc_NetShareEnumAll
1610 ********************************************************************/
1612 WERROR _srvsvc_NetShareEnumAll(struct pipes_struct *p,
1613 struct srvsvc_NetShareEnumAll *r)
1617 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1619 if (!pipe_access_check(p)) {
1620 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1621 return WERR_ACCESS_DENIED;
1624 /* Create the list of shares for the response. */
1625 werr = init_srv_share_info_ctr(p,
1627 r->in.resume_handle,
1628 r->out.totalentries,
1631 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1636 /*******************************************************************
1637 _srvsvc_NetShareEnum
1638 ********************************************************************/
1640 WERROR _srvsvc_NetShareEnum(struct pipes_struct *p,
1641 struct srvsvc_NetShareEnum *r)
1645 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1647 if (!pipe_access_check(p)) {
1648 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1649 return WERR_ACCESS_DENIED;
1652 /* Create the list of shares for the response. */
1653 werr = init_srv_share_info_ctr(p,
1655 r->in.resume_handle,
1656 r->out.totalentries,
1659 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1664 /*******************************************************************
1665 _srvsvc_NetShareGetInfo
1666 ********************************************************************/
1668 WERROR _srvsvc_NetShareGetInfo(struct pipes_struct *p,
1669 struct srvsvc_NetShareGetInfo *r)
1671 WERROR status = WERR_OK;
1672 char *share_name = NULL;
1674 union srvsvc_NetShareInfo *info = r->out.info;
1676 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1678 if (!r->in.share_name) {
1679 return WERR_INVALID_NAME;
1682 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1684 return WERR_NOT_ENOUGH_MEMORY;
1687 return WERR_INVALID_NAME;
1690 switch (r->in.level) {
1692 info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1693 W_ERROR_HAVE_NO_MEMORY(info->info0);
1694 init_srv_share_info_0(p, info->info0, snum);
1697 info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1698 W_ERROR_HAVE_NO_MEMORY(info->info1);
1699 init_srv_share_info_1(p, info->info1, snum);
1702 info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1703 W_ERROR_HAVE_NO_MEMORY(info->info2);
1704 init_srv_share_info_2(p, info->info2, snum);
1705 info->info2->current_users =
1706 count_current_connections(info->info2->name, false);
1709 info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1710 W_ERROR_HAVE_NO_MEMORY(info->info501);
1711 init_srv_share_info_501(p, info->info501, snum);
1714 info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1715 W_ERROR_HAVE_NO_MEMORY(info->info502);
1716 init_srv_share_info_502(p, info->info502, snum);
1719 info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1720 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1721 init_srv_share_info_1004(p, info->info1004, snum);
1724 info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1725 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1726 init_srv_share_info_1005(p, info->info1005, snum);
1729 info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1730 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1731 init_srv_share_info_1006(p, info->info1006, snum);
1734 info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1735 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1736 init_srv_share_info_1007(p, info->info1007, snum);
1739 init_srv_share_info_1501(p, &info->info1501, snum);
1742 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1744 status = WERR_INVALID_LEVEL;
1748 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1753 /*******************************************************************
1754 _srvsvc_NetShareSetInfo. Modify share details.
1755 ********************************************************************/
1757 WERROR _srvsvc_NetShareSetInfo(struct pipes_struct *p,
1758 struct srvsvc_NetShareSetInfo *r)
1760 const struct loadparm_substitution *lp_sub =
1761 loadparm_s3_global_substitution();
1762 char *command = NULL;
1763 char *share_name = NULL;
1764 char *comment = NULL;
1765 const char *pathname = NULL;
1770 struct security_descriptor *psd = NULL;
1771 bool is_disk_op = False;
1772 const char *csc_policy = NULL;
1773 bool csc_policy_changed = false;
1774 const char *csc_policies[] = {"manual", "documents", "programs",
1776 uint32_t client_csc_policy;
1777 int max_connections = 0;
1778 TALLOC_CTX *ctx = p->mem_ctx;
1779 union srvsvc_NetShareInfo *info = r->in.info;
1781 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1783 if (!r->in.share_name) {
1784 return WERR_INVALID_NAME;
1787 if (r->out.parm_error) {
1788 *r->out.parm_error = 0;
1791 if ( strequal(r->in.share_name,"IPC$")
1792 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1793 || strequal(r->in.share_name,"global") )
1795 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s cannot be "
1796 "modified by a remote user.\n",
1797 r->in.share_name ));
1798 return WERR_ACCESS_DENIED;
1801 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1803 return WERR_NOT_ENOUGH_MEMORY;
1806 /* Does this share exist ? */
1808 return WERR_NERR_NETNAMENOTFOUND;
1810 /* No change to printer shares. */
1811 if (lp_printable(snum))
1812 return WERR_ACCESS_DENIED;
1814 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1816 /* fail out now if you are not root and not a disk op */
1818 if ( p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op ) {
1819 DEBUG(2,("_srvsvc_NetShareSetInfo: uid %u doesn't have the "
1820 "SeDiskOperatorPrivilege privilege needed to modify "
1822 (unsigned int)p->session_info->unix_token->uid,
1824 return WERR_ACCESS_DENIED;
1827 max_connections = lp_max_connections(snum);
1828 csc_policy = csc_policies[lp_csc_policy(snum)];
1830 switch (r->in.level) {
1832 pathname = lp_path(ctx, lp_sub, snum);
1833 comment = talloc_strdup(ctx, info->info1->comment);
1834 type = info->info1->type;
1838 comment = talloc_strdup(ctx, info->info2->comment);
1839 pathname = info->info2->path;
1840 type = info->info2->type;
1841 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1842 0 : info->info2->max_users;
1846 /* not supported on set but here for completeness */
1848 comment = talloc_strdup(ctx, info->info501->comment);
1849 type = info->info501->type;
1854 comment = talloc_strdup(ctx, info->info502->comment);
1855 pathname = info->info502->path;
1856 type = info->info502->type;
1857 psd = info->info502->sd_buf.sd;
1858 map_generic_share_sd_bits(psd);
1861 pathname = lp_path(ctx, lp_sub, snum);
1862 comment = talloc_strdup(ctx, info->info1004->comment);
1863 type = STYPE_DISKTREE;
1866 /* XP re-sets the csc policy even if it wasn't changed by the
1867 user, so we must compare it to see if it's what is set in
1868 smb.conf, so that we can contine other ops like setting
1870 client_csc_policy = (info->info1005->dfs_flags &
1871 SHARE_1005_CSC_POLICY_MASK) >>
1872 SHARE_1005_CSC_POLICY_SHIFT;
1874 if (client_csc_policy == lp_csc_policy(snum))
1877 csc_policy = csc_policies[client_csc_policy];
1878 csc_policy_changed = true;
1881 pathname = lp_path(ctx, lp_sub, snum);
1882 comment = lp_comment(ctx, lp_sub, snum);
1883 type = STYPE_DISKTREE;
1887 return WERR_ACCESS_DENIED;
1889 pathname = lp_path(ctx, lp_sub, snum);
1890 comment = lp_comment(ctx, lp_sub, snum);
1891 psd = info->info1501->sd;
1892 map_generic_share_sd_bits(psd);
1893 type = STYPE_DISKTREE;
1896 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1898 return WERR_INVALID_LEVEL;
1901 /* We can only modify disk shares. */
1902 if (type != STYPE_DISKTREE) {
1903 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s is not a "
1906 return WERR_ACCESS_DENIED;
1909 if (comment == NULL) {
1910 return WERR_NOT_ENOUGH_MEMORY;
1913 /* Check if the pathname is valid. */
1914 if (!(path = valid_share_pathname(p->mem_ctx, pathname ))) {
1915 DEBUG(5,("_srvsvc_NetShareSetInfo: invalid pathname %s\n",
1917 return WERR_BAD_PATHNAME;
1920 /* Ensure share name, pathname and comment don't contain '"' characters. */
1921 string_replace(share_name, '"', ' ');
1922 string_replace(path, '"', ' ');
1923 string_replace(comment, '"', ' ');
1925 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1926 lp_change_share_command(talloc_tos(), lp_sub) ? lp_change_share_command(talloc_tos(), lp_sub) : "NULL" ));
1928 /* Only call modify function if something changed. */
1930 if (strcmp(path, lp_path(talloc_tos(), lp_sub, snum))
1931 || strcmp(comment, lp_comment(talloc_tos(), lp_sub, snum))
1932 || (lp_max_connections(snum) != max_connections)
1933 || csc_policy_changed) {
1935 if (!lp_change_share_command(talloc_tos(), lp_sub) || !*lp_change_share_command(talloc_tos(), lp_sub)) {
1936 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1937 return WERR_ACCESS_DENIED;
1940 command = talloc_asprintf(p->mem_ctx,
1941 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d \"%s\"",
1942 lp_change_share_command(talloc_tos(), lp_sub),
1943 get_dyn_CONFIGFILE(),
1950 return WERR_NOT_ENOUGH_MEMORY;
1953 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1955 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1960 ret = smbrun(command, NULL, NULL);
1962 reload_services(NULL, NULL, false);
1964 /* Tell everyone we updated smb.conf. */
1965 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED,
1972 /********* END SeDiskOperatorPrivilege BLOCK *********/
1974 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1977 TALLOC_FREE(command);
1980 return WERR_ACCESS_DENIED;
1982 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1986 /* Replace SD if changed. */
1988 struct security_descriptor *old_sd;
1992 old_sd = get_share_security(p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
1994 if (old_sd && !security_descriptor_equal(old_sd, psd)) {
1995 status = set_share_security(share_name, psd);
1996 if (!NT_STATUS_IS_OK(status)) {
1997 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
2003 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
2008 /*******************************************************************
2009 _srvsvc_NetShareAdd.
2010 Call 'add_share_command "sharename" "pathname"
2011 "comment" "max connections = "
2012 ********************************************************************/
2014 WERROR _srvsvc_NetShareAdd(struct pipes_struct *p,
2015 struct srvsvc_NetShareAdd *r)
2017 char *command = NULL;
2018 char *share_name_in = NULL;
2019 char *share_name = NULL;
2020 char *comment = NULL;
2021 char *pathname = NULL;
2026 struct security_descriptor *psd = NULL;
2028 int max_connections = 0;
2030 TALLOC_CTX *ctx = p->mem_ctx;
2031 const struct loadparm_substitution *lp_sub =
2032 loadparm_s3_global_substitution();
2034 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
2036 if (r->out.parm_error) {
2037 *r->out.parm_error = 0;
2040 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2042 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op )
2043 return WERR_ACCESS_DENIED;
2045 if (!lp_add_share_command(talloc_tos(), lp_sub) || !*lp_add_share_command(talloc_tos(), lp_sub)) {
2046 DBG_WARNING("_srvsvc_NetShareAdd: No \"add share command\" parameter set in smb.conf.\n");
2047 return WERR_ACCESS_DENIED;
2050 switch (r->in.level) {
2052 /* No path. Not enough info in a level 0 to do anything. */
2053 return WERR_ACCESS_DENIED;
2055 /* Not enough info in a level 1 to do anything. */
2056 return WERR_ACCESS_DENIED;
2058 share_name_in = talloc_strdup(ctx, r->in.info->info2->name);
2059 comment = talloc_strdup(ctx, r->in.info->info2->comment);
2060 pathname = talloc_strdup(ctx, r->in.info->info2->path);
2061 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
2062 0 : r->in.info->info2->max_users;
2063 type = r->in.info->info2->type;
2066 /* No path. Not enough info in a level 501 to do anything. */
2067 return WERR_ACCESS_DENIED;
2069 share_name_in = talloc_strdup(ctx, r->in.info->info502->name);
2070 comment = talloc_strdup(ctx, r->in.info->info502->comment);
2071 pathname = talloc_strdup(ctx, r->in.info->info502->path);
2072 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
2073 0 : r->in.info->info502->max_users;
2074 type = r->in.info->info502->type;
2075 psd = r->in.info->info502->sd_buf.sd;
2076 map_generic_share_sd_bits(psd);
2079 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
2085 return WERR_ACCESS_DENIED;
2087 /* DFS only level. */
2088 return WERR_ACCESS_DENIED;
2090 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
2092 return WERR_INVALID_LEVEL;
2095 /* check for invalid share names */
2097 if (!share_name_in || !validate_net_name(share_name_in,
2098 INVALID_SHARENAME_CHARS,
2099 strlen(share_name_in))) {
2100 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
2101 share_name_in ? share_name_in : ""));
2102 return WERR_INVALID_NAME;
2105 if (strequal(share_name_in,"IPC$") || strequal(share_name_in,"global")
2106 || (lp_enable_asu_support() &&
2107 strequal(share_name_in,"ADMIN$"))) {
2108 return WERR_ACCESS_DENIED;
2111 snum = find_service(ctx, share_name_in, &share_name);
2113 return WERR_NOT_ENOUGH_MEMORY;
2116 /* Share already exists. */
2118 return WERR_FILE_EXISTS;
2121 /* We can only add disk shares. */
2122 if (type != STYPE_DISKTREE) {
2123 return WERR_ACCESS_DENIED;
2126 /* Check if the pathname is valid. */
2127 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
2128 return WERR_BAD_PATHNAME;
2131 ret = sys_lstat(path, &st, false);
2132 if (ret == -1 && (errno != EACCES)) {
2134 * If path has any other than permission
2135 * problem, return WERR_FILE_NOT_FOUND (as Windows
2138 return WERR_FILE_NOT_FOUND;
2141 /* Ensure share name, pathname and comment don't contain '"' characters. */
2142 string_replace(share_name_in, '"', ' ');
2143 string_replace(share_name, '"', ' ');
2144 string_replace(path, '"', ' ');
2146 string_replace(comment, '"', ' ');
2149 command = talloc_asprintf(ctx,
2150 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
2151 lp_add_share_command(talloc_tos(), lp_sub),
2152 get_dyn_CONFIGFILE(),
2155 comment ? comment : "",
2158 return WERR_NOT_ENOUGH_MEMORY;
2161 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
2163 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
2168 /* FIXME: use libnetconf here - gd */
2170 ret = smbrun(command, NULL, NULL);
2172 /* Tell everyone we updated smb.conf. */
2173 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
2179 /********* END SeDiskOperatorPrivilege BLOCK *********/
2181 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
2184 TALLOC_FREE(command);
2187 return WERR_ACCESS_DENIED;
2191 /* Note we use share_name here, not share_name_in as
2192 we need a canonicalized name for setting security. */
2193 status = set_share_security(share_name, psd);
2194 if (!NT_STATUS_IS_OK(status)) {
2195 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
2201 * We don't call reload_services() here, the message will
2202 * cause this to be done before the next packet is read
2203 * from the client. JRA.
2206 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
2211 /*******************************************************************
2213 Call "delete share command" with the share name as
2215 ********************************************************************/
2217 WERROR _srvsvc_NetShareDel(struct pipes_struct *p,
2218 struct srvsvc_NetShareDel *r)
2220 char *command = NULL;
2221 char *share_name = NULL;
2225 TALLOC_CTX *ctx = p->mem_ctx;
2226 const struct loadparm_substitution *lp_sub =
2227 loadparm_s3_global_substitution();
2229 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
2231 if (!r->in.share_name) {
2232 return WERR_NERR_NETNAMENOTFOUND;
2235 if ( strequal(r->in.share_name,"IPC$")
2236 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
2237 || strequal(r->in.share_name,"global") )
2239 return WERR_ACCESS_DENIED;
2242 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
2244 return WERR_NOT_ENOUGH_MEMORY;
2248 return WERR_BAD_NET_NAME;
2251 /* No change to printer shares. */
2252 if (lp_printable(snum))
2253 return WERR_ACCESS_DENIED;
2255 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2257 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op )
2258 return WERR_ACCESS_DENIED;
2260 if (!lp_delete_share_command(talloc_tos(), lp_sub) || !*lp_delete_share_command(talloc_tos(), lp_sub)) {
2261 DBG_WARNING("_srvsvc_NetShareDel: No \"delete share command\" parameter set in smb.conf.\n");
2262 return WERR_ACCESS_DENIED;
2265 command = talloc_asprintf(ctx,
2267 lp_delete_share_command(talloc_tos(), lp_sub),
2268 get_dyn_CONFIGFILE(),
2271 return WERR_NOT_ENOUGH_MEMORY;
2274 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
2276 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
2281 ret = smbrun(command, NULL, NULL);
2283 /* Tell everyone we updated smb.conf. */
2284 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
2290 /********* END SeDiskOperatorPrivilege BLOCK *********/
2292 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
2295 return WERR_ACCESS_DENIED;
2297 /* Delete the SD in the database. */
2298 delete_share_security(share_name);
2300 lp_killservice(snum);
2305 /*******************************************************************
2306 _srvsvc_NetShareDelSticky
2307 ********************************************************************/
2309 WERROR _srvsvc_NetShareDelSticky(struct pipes_struct *p,
2310 struct srvsvc_NetShareDelSticky *r)
2312 struct srvsvc_NetShareDel q;
2314 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
2316 q.in.server_unc = r->in.server_unc;
2317 q.in.share_name = r->in.share_name;
2318 q.in.reserved = r->in.reserved;
2320 return _srvsvc_NetShareDel(p, &q);
2323 /*******************************************************************
2324 _srvsvc_NetRemoteTOD
2325 ********************************************************************/
2327 WERROR _srvsvc_NetRemoteTOD(struct pipes_struct *p,
2328 struct srvsvc_NetRemoteTOD *r)
2330 struct srvsvc_NetRemoteTODInfo *tod;
2332 time_t unixdate = time(NULL);
2334 /* We do this call first as if we do it *after* the gmtime call
2335 it overwrites the pointed-to values. JRA */
2337 uint32_t zone = get_time_zone(unixdate)/60;
2339 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2341 if ( !(tod = talloc_zero(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
2342 return WERR_NOT_ENOUGH_MEMORY;
2346 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2348 t = gmtime(&unixdate);
2351 tod->elapsed = unixdate;
2353 tod->hours = t->tm_hour;
2354 tod->mins = t->tm_min;
2355 tod->secs = t->tm_sec;
2357 tod->timezone = zone;
2358 tod->tinterval = 10000;
2359 tod->day = t->tm_mday;
2360 tod->month = t->tm_mon + 1;
2361 tod->year = 1900+t->tm_year;
2362 tod->weekday = t->tm_wday;
2364 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2369 /***********************************************************************************
2370 _srvsvc_NetGetFileSecurity
2371 Win9x NT tools get security descriptor.
2372 ***********************************************************************************/
2374 WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
2375 struct srvsvc_NetGetFileSecurity *r)
2377 TALLOC_CTX *frame = talloc_stackframe();
2378 const struct loadparm_substitution *lp_sub =
2379 loadparm_s3_global_substitution();
2380 struct smb_filename *smb_fname = NULL;
2382 char *servicename = NULL;
2386 struct conn_struct_tos *c = NULL;
2387 connection_struct *conn = NULL;
2388 struct sec_desc_buf *sd_buf = NULL;
2389 files_struct *fsp = NULL;
2391 uint32_t ucf_flags = 0;
2396 werr = WERR_NERR_NETNAMENOTFOUND;
2399 snum = find_service(frame, r->in.share, &servicename);
2401 werr = WERR_NOT_ENOUGH_MEMORY;
2405 DEBUG(10, ("Could not find service %s\n", servicename));
2406 werr = WERR_NERR_NETNAMENOTFOUND;
2410 nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
2412 lp_path(frame, lp_sub, snum),
2415 if (!NT_STATUS_IS_OK(nt_status)) {
2416 DEBUG(10, ("create_conn_struct failed: %s\n",
2417 nt_errstr(nt_status)));
2418 werr = ntstatus_to_werror(nt_status);
2423 nt_status = filename_convert(frame,
2429 if (!NT_STATUS_IS_OK(nt_status)) {
2430 werr = ntstatus_to_werror(nt_status);
2434 nt_status = SMB_VFS_CREATE_FILE(
2437 smb_fname, /* fname */
2438 FILE_READ_ATTRIBUTES, /* access_mask */
2439 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2440 FILE_OPEN, /* create_disposition*/
2441 0, /* create_options */
2442 0, /* file_attributes */
2443 INTERNAL_OPEN_ONLY, /* oplock_request */
2445 0, /* allocation_size */
2446 0, /* private_flags */
2451 NULL, NULL); /* create context */
2453 if (!NT_STATUS_IS_OK(nt_status)) {
2454 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2455 smb_fname_str_dbg(smb_fname)));
2456 werr = ntstatus_to_werror(nt_status);
2460 sd_buf = talloc_zero(p->mem_ctx, struct sec_desc_buf);
2462 werr = WERR_NOT_ENOUGH_MEMORY;
2466 nt_status = SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp),
2469 |SECINFO_DACL), sd_buf, &sd_buf->sd);
2471 if (!NT_STATUS_IS_OK(nt_status)) {
2472 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2473 "for file %s\n", smb_fname_str_dbg(smb_fname)));
2474 werr = ntstatus_to_werror(nt_status);
2475 TALLOC_FREE(sd_buf);
2479 if (sd_buf->sd->dacl) {
2480 sd_buf->sd->dacl->revision = NT4_ACL_REVISION;
2483 sd_size = ndr_size_security_descriptor(sd_buf->sd, 0);
2485 sd_buf->sd_size = sd_size;
2487 *r->out.sd_buf = sd_buf;
2494 close_file(NULL, fsp, NORMAL_CLOSE);
2501 /***********************************************************************************
2502 _srvsvc_NetSetFileSecurity
2503 Win9x NT tools set security descriptor.
2504 ***********************************************************************************/
2506 WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
2507 struct srvsvc_NetSetFileSecurity *r)
2509 TALLOC_CTX *frame = talloc_stackframe();
2510 const struct loadparm_substitution *lp_sub =
2511 loadparm_s3_global_substitution();
2512 struct smb_filename *smb_fname = NULL;
2513 char *servicename = NULL;
2514 files_struct *fsp = NULL;
2518 struct conn_struct_tos *c = NULL;
2519 connection_struct *conn = NULL;
2521 struct security_descriptor *psd = NULL;
2522 uint32_t security_info_sent = 0;
2523 uint32_t ucf_flags = 0;
2528 werr = WERR_NERR_NETNAMENOTFOUND;
2532 snum = find_service(frame, r->in.share, &servicename);
2534 werr = WERR_NOT_ENOUGH_MEMORY;
2539 DEBUG(10, ("Could not find service %s\n", servicename));
2540 werr = WERR_NERR_NETNAMENOTFOUND;
2544 nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
2546 lp_path(frame, lp_sub, snum),
2549 if (!NT_STATUS_IS_OK(nt_status)) {
2550 DEBUG(10, ("create_conn_struct failed: %s\n",
2551 nt_errstr(nt_status)));
2552 werr = ntstatus_to_werror(nt_status);
2557 nt_status = filename_convert(frame,
2563 if (!NT_STATUS_IS_OK(nt_status)) {
2564 werr = ntstatus_to_werror(nt_status);
2568 nt_status = SMB_VFS_CREATE_FILE(
2571 smb_fname, /* fname */
2572 FILE_WRITE_ATTRIBUTES, /* access_mask */
2573 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2574 FILE_OPEN, /* create_disposition*/
2575 0, /* create_options */
2576 0, /* file_attributes */
2577 INTERNAL_OPEN_ONLY, /* oplock_request */
2579 0, /* allocation_size */
2580 0, /* private_flags */
2585 NULL, NULL); /* create context */
2587 if (!NT_STATUS_IS_OK(nt_status)) {
2588 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2589 smb_fname_str_dbg(smb_fname)));
2590 werr = ntstatus_to_werror(nt_status);
2594 psd = r->in.sd_buf->sd;
2595 security_info_sent = r->in.securityinformation;
2597 nt_status = set_sd(fsp, psd, security_info_sent);
2599 if (!NT_STATUS_IS_OK(nt_status) ) {
2600 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2601 "on file %s\n", r->in.share));
2602 werr = WERR_ACCESS_DENIED;
2611 close_file(NULL, fsp, NORMAL_CLOSE);
2618 /***********************************************************************************
2619 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2620 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2621 These disks would the disks listed by this function.
2622 Users could then create shares relative to these disks. Watch out for moving these disks around.
2623 "Nigel Williams" <nigel@veritas.com>.
2624 ***********************************************************************************/
2626 static const char *server_disks[] = {"C:"};
2628 static uint32_t get_server_disk_count(void)
2630 return sizeof(server_disks)/sizeof(server_disks[0]);
2633 static uint32_t init_server_disk_enum(uint32_t *resume)
2635 uint32_t server_disk_count = get_server_disk_count();
2637 /*resume can be an offset into the list for now*/
2639 if(*resume & 0x80000000)
2642 if(*resume > server_disk_count)
2643 *resume = server_disk_count;
2645 return server_disk_count - *resume;
2648 static const char *next_server_disk_enum(uint32_t *resume)
2652 if(init_server_disk_enum(resume) == 0)
2655 disk = server_disks[*resume];
2659 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2664 /********************************************************************
2666 ********************************************************************/
2668 WERROR _srvsvc_NetDiskEnum(struct pipes_struct *p,
2669 struct srvsvc_NetDiskEnum *r)
2672 const char *disk_name;
2673 TALLOC_CTX *ctx = p->mem_ctx;
2675 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2679 *r->out.totalentries = init_server_disk_enum(&resume);
2681 r->out.info->disks = talloc_zero_array(ctx, struct srvsvc_NetDiskInfo0,
2682 MAX_SERVER_DISK_ENTRIES);
2683 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2685 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2687 r->out.info->count = 0;
2689 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2691 r->out.info->count++;
2693 /*copy disk name into a unicode string*/
2695 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2696 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2699 /* add a terminating null string. Is this there if there is more data to come? */
2701 r->out.info->count++;
2703 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2704 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2706 if (r->out.resume_handle) {
2707 *r->out.resume_handle = resume;
2713 /********************************************************************
2714 _srvsvc_NetNameValidate
2715 ********************************************************************/
2717 WERROR _srvsvc_NetNameValidate(struct pipes_struct *p,
2718 struct srvsvc_NetNameValidate *r)
2720 switch (r->in.name_type) {
2722 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2723 strlen_m(r->in.name)))
2725 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2727 return WERR_INVALID_NAME;
2732 return WERR_INVALID_LEVEL;
2738 /*******************************************************************
2739 ********************************************************************/
2741 struct enum_file_close_state {
2742 struct srvsvc_NetFileClose *r;
2743 struct messaging_context *msg_ctx;
2746 static int enum_file_close_fn(struct file_id id,
2747 const struct share_mode_data *d,
2748 const struct share_mode_entry *e,
2751 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2752 struct enum_file_close_state *state =
2753 (struct enum_file_close_state *)private_data;
2754 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2756 if (fid != state->r->in.fid) {
2757 return 0; /* Not this file. */
2760 if (!process_exists(e->pid) ) {
2764 /* Ok - send the close message. */
2765 DBG_DEBUG("request to close file %s, %s\n", d->servicepath,
2766 share_mode_str(talloc_tos(), 0, &id, e));
2768 share_mode_entry_to_message(msg, &id, e);
2770 state->r->out.result = ntstatus_to_werror(
2771 messaging_send_buf(state->msg_ctx,
2772 e->pid, MSG_SMB_CLOSE_FILE,
2773 (uint8_t *)msg, sizeof(msg)));
2778 /********************************************************************
2779 Close a file given a 32-bit file id.
2780 ********************************************************************/
2782 WERROR _srvsvc_NetFileClose(struct pipes_struct *p,
2783 struct srvsvc_NetFileClose *r)
2785 struct enum_file_close_state state;
2788 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2790 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2792 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op) {
2793 return WERR_ACCESS_DENIED;
2796 /* enum_file_close_fn sends the close message to
2797 * the relevant smbd process. */
2799 r->out.result = WERR_FILE_NOT_FOUND;
2801 state.msg_ctx = p->msg_ctx;
2802 share_entry_forall(enum_file_close_fn, &state);
2803 return r->out.result;
2806 /********************************************************************
2807 ********************************************************************/
2809 WERROR _srvsvc_NetCharDevEnum(struct pipes_struct *p,
2810 struct srvsvc_NetCharDevEnum *r)
2812 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2813 return WERR_NOT_SUPPORTED;
2816 WERROR _srvsvc_NetCharDevGetInfo(struct pipes_struct *p,
2817 struct srvsvc_NetCharDevGetInfo *r)
2819 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2820 return WERR_NOT_SUPPORTED;
2823 WERROR _srvsvc_NetCharDevControl(struct pipes_struct *p,
2824 struct srvsvc_NetCharDevControl *r)
2826 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2827 return WERR_NOT_SUPPORTED;
2830 WERROR _srvsvc_NetCharDevQEnum(struct pipes_struct *p,
2831 struct srvsvc_NetCharDevQEnum *r)
2833 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2834 return WERR_NOT_SUPPORTED;
2837 WERROR _srvsvc_NetCharDevQGetInfo(struct pipes_struct *p,
2838 struct srvsvc_NetCharDevQGetInfo *r)
2840 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2841 return WERR_NOT_SUPPORTED;
2844 WERROR _srvsvc_NetCharDevQSetInfo(struct pipes_struct *p,
2845 struct srvsvc_NetCharDevQSetInfo *r)
2847 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2848 return WERR_NOT_SUPPORTED;
2851 WERROR _srvsvc_NetCharDevQPurge(struct pipes_struct *p,
2852 struct srvsvc_NetCharDevQPurge *r)
2854 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2855 return WERR_NOT_SUPPORTED;
2858 WERROR _srvsvc_NetCharDevQPurgeSelf(struct pipes_struct *p,
2859 struct srvsvc_NetCharDevQPurgeSelf *r)
2861 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2862 return WERR_NOT_SUPPORTED;
2865 WERROR _srvsvc_NetFileGetInfo(struct pipes_struct *p,
2866 struct srvsvc_NetFileGetInfo *r)
2868 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2869 return WERR_NOT_SUPPORTED;
2872 WERROR _srvsvc_NetShareCheck(struct pipes_struct *p,
2873 struct srvsvc_NetShareCheck *r)
2875 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2876 return WERR_NOT_SUPPORTED;
2879 WERROR _srvsvc_NetServerStatisticsGet(struct pipes_struct *p,
2880 struct srvsvc_NetServerStatisticsGet *r)
2882 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2883 return WERR_NOT_SUPPORTED;
2886 WERROR _srvsvc_NetTransportAdd(struct pipes_struct *p,
2887 struct srvsvc_NetTransportAdd *r)
2889 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2890 return WERR_NOT_SUPPORTED;
2893 WERROR _srvsvc_NetTransportEnum(struct pipes_struct *p,
2894 struct srvsvc_NetTransportEnum *r)
2896 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2897 return WERR_NOT_SUPPORTED;
2900 WERROR _srvsvc_NetTransportDel(struct pipes_struct *p,
2901 struct srvsvc_NetTransportDel *r)
2903 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2904 return WERR_NOT_SUPPORTED;
2907 WERROR _srvsvc_NetSetServiceBits(struct pipes_struct *p,
2908 struct srvsvc_NetSetServiceBits *r)
2910 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2911 return WERR_NOT_SUPPORTED;
2914 WERROR _srvsvc_NetPathType(struct pipes_struct *p,
2915 struct srvsvc_NetPathType *r)
2917 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2918 return WERR_NOT_SUPPORTED;
2921 WERROR _srvsvc_NetPathCanonicalize(struct pipes_struct *p,
2922 struct srvsvc_NetPathCanonicalize *r)
2924 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2925 return WERR_NOT_SUPPORTED;
2928 WERROR _srvsvc_NetPathCompare(struct pipes_struct *p,
2929 struct srvsvc_NetPathCompare *r)
2931 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2932 return WERR_NOT_SUPPORTED;
2935 WERROR _srvsvc_NETRPRNAMECANONICALIZE(struct pipes_struct *p,
2936 struct srvsvc_NETRPRNAMECANONICALIZE *r)
2938 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2939 return WERR_NOT_SUPPORTED;
2942 WERROR _srvsvc_NetPRNameCompare(struct pipes_struct *p,
2943 struct srvsvc_NetPRNameCompare *r)
2945 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2946 return WERR_NOT_SUPPORTED;
2949 WERROR _srvsvc_NetShareDelStart(struct pipes_struct *p,
2950 struct srvsvc_NetShareDelStart *r)
2952 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2953 return WERR_NOT_SUPPORTED;
2956 WERROR _srvsvc_NetShareDelCommit(struct pipes_struct *p,
2957 struct srvsvc_NetShareDelCommit *r)
2959 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2960 return WERR_NOT_SUPPORTED;
2963 WERROR _srvsvc_NetServerTransportAddEx(struct pipes_struct *p,
2964 struct srvsvc_NetServerTransportAddEx *r)
2966 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2967 return WERR_NOT_SUPPORTED;
2970 WERROR _srvsvc_NetServerSetServiceBitsEx(struct pipes_struct *p,
2971 struct srvsvc_NetServerSetServiceBitsEx *r)
2973 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2974 return WERR_NOT_SUPPORTED;
2977 WERROR _srvsvc_NETRDFSGETVERSION(struct pipes_struct *p,
2978 struct srvsvc_NETRDFSGETVERSION *r)
2980 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2981 return WERR_NOT_SUPPORTED;
2984 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(struct pipes_struct *p,
2985 struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2987 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2988 return WERR_NOT_SUPPORTED;
2991 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(struct pipes_struct *p,
2992 struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2994 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2995 return WERR_NOT_SUPPORTED;
2998 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(struct pipes_struct *p,
2999 struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
3001 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3002 return WERR_NOT_SUPPORTED;
3005 WERROR _srvsvc_NETRDFSSETSERVERINFO(struct pipes_struct *p,
3006 struct srvsvc_NETRDFSSETSERVERINFO *r)
3008 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3009 return WERR_NOT_SUPPORTED;
3012 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(struct pipes_struct *p,
3013 struct srvsvc_NETRDFSCREATEEXITPOINT *r)
3015 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3016 return WERR_NOT_SUPPORTED;
3019 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(struct pipes_struct *p,
3020 struct srvsvc_NETRDFSDELETEEXITPOINT *r)
3022 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3023 return WERR_NOT_SUPPORTED;
3026 WERROR _srvsvc_NETRDFSMODIFYPREFIX(struct pipes_struct *p,
3027 struct srvsvc_NETRDFSMODIFYPREFIX *r)
3029 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3030 return WERR_NOT_SUPPORTED;
3033 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(struct pipes_struct *p,
3034 struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
3036 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3037 return WERR_NOT_SUPPORTED;
3040 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(struct pipes_struct *p,
3041 struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
3043 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3044 return WERR_NOT_SUPPORTED;
3047 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(struct pipes_struct *p,
3048 struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
3050 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3051 return WERR_NOT_SUPPORTED;
3054 /* include the generated boilerplate */
3055 #include "librpc/gen_ndr/ndr_srvsvc_scompat.c"