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 "smbd/smbd.h"
39 #include "smbd/globals.h"
44 extern const struct generic_mapping file_generic_mapping;
47 #define DBGC_CLASS DBGC_RPC_SRV
49 #define MAX_SERVER_DISK_ENTRIES 15
51 /* Use for enumerating connections, pipes, & files */
53 struct file_enum_count {
56 struct srvsvc_NetFileCtr3 *ctr3;
60 struct sess_file_info {
61 struct srvsvc_NetSessCtr1 *ctr;
62 struct sessionid *session_list;
63 uint32_t resume_handle;
67 struct share_file_stat {
68 struct srvsvc_NetConnInfo1 *netconn_arr;
69 struct server_id *svrid_arr;
70 const char *in_sharepath;
71 uint32_t resp_entries;
72 uint32_t total_entries;
75 struct share_conn_stat {
77 const char *sharename;
78 struct server_id *svrid_arr;
82 /*******************************************************************
83 ********************************************************************/
85 static int enum_file_fn(struct file_id id,
86 const struct share_mode_data *d,
87 const struct share_mode_entry *e,
90 struct file_enum_count *fenum =
91 (struct file_enum_count *)private_data;
92 struct srvsvc_NetFileCtr3 *ctr3 = fenum->ctr3;
93 struct srvsvc_NetFileInfo3 *f;
94 struct file_id *fids = NULL;
95 char *fullpath = NULL;
99 /* If the pid was not found delete the entry from connections.tdb */
101 if ( !process_exists(e->pid) ) {
105 username = uidtoname(e->uid);
107 if ((fenum->username != NULL)
108 && !strequal(username, fenum->username)) {
115 struct srvsvc_NetFileInfo3,
118 DBG_ERR("realloc failed for %"PRIu32" items\n", ctr3->count+1);
123 fids = talloc_realloc(
124 fenum->ctx, fenum->fids, struct file_id, ctr3->count+1);
126 DBG_ERR("realloc failed for %"PRIu32" items\n", ctr3->count+1);
129 fids[ctr3->count] = id;
132 if ( strcmp(d->base_name, "." ) == 0 ) {
133 fullpath = talloc_asprintf(
138 fullpath = talloc_asprintf(
143 (d->stream_name != NULL) ? d->stream_name : "");
148 string_replace( fullpath, '/', '\\' );
150 /* mask out create (what ever that is) */
151 permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
153 /* now fill in the srvsvc_NetFileInfo3 struct */
155 ctr3->array[ctr3->count] = (struct srvsvc_NetFileInfo3) {
156 .fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) |
158 .permissions = permissions,
168 /*******************************************************************
169 ********************************************************************/
171 static WERROR net_enum_files(TALLOC_CTX *ctx,
172 const char *username,
173 struct srvsvc_NetFileCtr3 **ctr3,
176 struct file_enum_count f_enum_cnt = {
177 .ctx = ctx, .username = username, .ctr3 = *ctr3,
181 share_entry_forall(enum_file_fn, (void *)&f_enum_cnt );
183 *ctr3 = f_enum_cnt.ctr3;
185 /* need to count the number of locks on a file */
187 for (i=0; i<(*ctr3)->count; i++) {
188 struct files_struct fsp = { .file_id = f_enum_cnt.fids[i], };
189 struct byte_range_lock *brl = NULL;
191 brl = brl_get_locks(ctx, &fsp);
196 (*ctr3)->array[i].num_locks = brl_num_locks(brl);
204 /*******************************************************************
205 Utility function to get the 'type' of a share from an snum.
206 ********************************************************************/
207 static enum srvsvc_ShareType get_share_type(int snum)
209 /* work out the share type */
210 enum srvsvc_ShareType type = STYPE_DISKTREE;
212 if (lp_printable(snum)) {
213 type = lp_administrative_share(snum)
214 ? STYPE_PRINTQ_HIDDEN : STYPE_PRINTQ;
216 if (strequal(lp_fstype(snum), "IPC")) {
217 type = lp_administrative_share(snum)
218 ? STYPE_IPC_HIDDEN : STYPE_IPC;
223 /*******************************************************************
224 Fill in a share info level 0 structure.
225 ********************************************************************/
227 static void init_srv_share_info_0(struct pipes_struct *p,
228 struct srvsvc_NetShareInfo0 *r, int snum)
230 const struct loadparm_substitution *lp_sub =
231 loadparm_s3_global_substitution();
233 r->name = lp_servicename(talloc_tos(), lp_sub, snum);
236 /*******************************************************************
237 Fill in a share info level 1 structure.
238 ********************************************************************/
240 static void init_srv_share_info_1(struct pipes_struct *p,
241 struct srvsvc_NetShareInfo1 *r,
244 const struct loadparm_substitution *lp_sub =
245 loadparm_s3_global_substitution();
246 char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
247 char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
250 remark = talloc_sub_full(
251 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
252 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
253 p->session_info->unix_token->uid, get_current_username(),
258 r->type = get_share_type(snum);
259 r->comment = remark ? remark : "";
262 /*******************************************************************
263 Fill in a share info level 2 structure.
264 ********************************************************************/
266 static void init_srv_share_info_2(struct pipes_struct *p,
267 struct srvsvc_NetShareInfo2 *r,
270 const struct loadparm_substitution *lp_sub =
271 loadparm_s3_global_substitution();
274 int max_connections = lp_max_connections(snum);
275 uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
276 char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
278 remark = lp_comment(p->mem_ctx, lp_sub, snum);
280 remark = talloc_sub_full(
281 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
282 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
283 p->session_info->unix_token->uid, get_current_username(),
286 path = talloc_asprintf(p->mem_ctx,
287 "C:%s", lp_path(talloc_tos(), lp_sub, snum));
291 * Change / to \\ so that win2k will see it as a valid path.
292 * This was added to enable use of browsing in win2k add
296 string_replace(path, '/', '\\');
300 r->type = get_share_type(snum);
301 r->comment = remark ? remark : "";
303 r->max_users = max_uses;
304 r->current_users = 0; /* computed later */
305 r->path = path ? path : "";
309 /*******************************************************************
310 Map any generic bits to file specific bits.
311 ********************************************************************/
313 static void map_generic_share_sd_bits(struct security_descriptor *psd)
316 struct security_acl *ps_dacl = NULL;
325 for (i = 0; i < ps_dacl->num_aces; i++) {
326 struct security_ace *psa = &ps_dacl->aces[i];
327 uint32_t orig_mask = psa->access_mask;
329 se_map_generic(&psa->access_mask, &file_generic_mapping);
330 psa->access_mask |= orig_mask;
334 /*******************************************************************
335 Fill in a share info level 501 structure.
336 ********************************************************************/
338 static void init_srv_share_info_501(struct pipes_struct *p,
339 struct srvsvc_NetShareInfo501 *r, int snum)
341 const struct loadparm_substitution *lp_sub =
342 loadparm_s3_global_substitution();
343 const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
344 char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
347 remark = talloc_sub_full(
348 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
349 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
350 p->session_info->unix_token->uid, get_current_username(),
355 r->type = get_share_type(snum);
356 r->comment = remark ? remark : "";
359 * According to [MS-SRVS] 2.2.4.25, the flags field is the same as in
362 r->csc_policy = (lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT);
365 /*******************************************************************
366 Fill in a share info level 502 structure.
367 ********************************************************************/
369 static void init_srv_share_info_502(struct pipes_struct *p,
370 struct srvsvc_NetShareInfo502 *r, int snum)
372 const struct loadparm_substitution *lp_sub =
373 loadparm_s3_global_substitution();
374 const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
376 struct security_descriptor *sd = NULL;
377 struct sec_desc_buf *sd_buf = NULL;
379 TALLOC_CTX *ctx = p->mem_ctx;
380 char *remark = lp_comment(ctx, lp_sub, snum);
383 remark = talloc_sub_full(
384 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
385 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
386 p->session_info->unix_token->uid, get_current_username(),
389 path = talloc_asprintf(ctx, "C:%s", lp_path(talloc_tos(), lp_sub, snum));
392 * Change / to \\ so that win2k will see it as a valid path. This was added to
393 * enable use of browsing in win2k add share dialog.
395 string_replace(path, '/', '\\');
398 sd = get_share_security(ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
400 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
403 r->type = get_share_type(snum);
404 r->comment = remark ? remark : "";
406 r->max_users = (uint32_t)-1;
407 r->current_users = 1; /* ??? */
408 r->path = path ? path : "";
413 /***************************************************************************
414 Fill in a share info level 1004 structure.
415 ***************************************************************************/
417 static void init_srv_share_info_1004(struct pipes_struct *p,
418 struct srvsvc_NetShareInfo1004 *r,
421 const struct loadparm_substitution *lp_sub =
422 loadparm_s3_global_substitution();
423 char *remark = lp_comment(p->mem_ctx, lp_sub, snum);
426 remark = talloc_sub_full(
427 p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum),
428 get_current_username(), lp_path(talloc_tos(), lp_sub, snum),
429 p->session_info->unix_token->uid, get_current_username(),
433 r->comment = remark ? remark : "";
436 /***************************************************************************
437 Fill in a share info level 1005 structure.
438 ***************************************************************************/
440 static void init_srv_share_info_1005(struct pipes_struct *p,
441 struct srvsvc_NetShareInfo1005 *r,
444 uint32_t dfs_flags = 0;
446 if (lp_host_msdfs() && lp_msdfs_root(snum)) {
447 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
450 dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
452 r->dfs_flags = dfs_flags;
455 /***************************************************************************
456 Fill in a share info level 1006 structure.
457 ***************************************************************************/
459 static void init_srv_share_info_1006(struct pipes_struct *p,
460 struct srvsvc_NetShareInfo1006 *r,
463 r->max_users = (uint32_t)-1;
466 /***************************************************************************
467 Fill in a share info level 1007 structure.
468 ***************************************************************************/
470 static void init_srv_share_info_1007(struct pipes_struct *p,
471 struct srvsvc_NetShareInfo1007 *r,
475 r->alternate_directory_name = "";
478 /*******************************************************************
479 Fill in a share info level 1501 structure.
480 ********************************************************************/
482 static void init_srv_share_info_1501(struct pipes_struct *p,
483 struct sec_desc_buf **r,
486 const struct loadparm_substitution *lp_sub =
487 loadparm_s3_global_substitution();
488 struct security_descriptor *sd;
489 struct sec_desc_buf *sd_buf = NULL;
491 TALLOC_CTX *ctx = p->mem_ctx;
493 sd = get_share_security(ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
495 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
501 /*******************************************************************
502 True if it ends in '$'.
503 ********************************************************************/
505 static bool is_hidden_share(int snum)
507 const struct loadparm_substitution *lp_sub =
508 loadparm_s3_global_substitution();
509 const char *net_name = lp_servicename(talloc_tos(), lp_sub, snum);
511 return (net_name[strlen(net_name) - 1] == '$') ? True : False;
514 /*******************************************************************
515 Verify user is allowed to view share, access based enumeration
516 ********************************************************************/
517 static bool is_enumeration_allowed(struct pipes_struct *p,
520 const struct loadparm_substitution *lp_sub =
521 loadparm_s3_global_substitution();
523 if (!lp_access_based_share_enum(snum)) {
527 if (!user_ok_token(p->session_info->unix_info->unix_name,
528 p->session_info->info->domain_name,
529 p->session_info->security_token, snum)) {
533 return share_access_check(p->session_info->security_token,
534 lp_servicename(talloc_tos(), lp_sub, snum),
535 FILE_READ_DATA, NULL);
538 /****************************************************************************
539 Count an entry against the respective service.
540 ****************************************************************************/
542 static int count_for_all_fn(struct smbXsrv_tcon_global0 *tcon, void *udp)
544 union srvsvc_NetShareCtr *ctr = NULL;
545 struct srvsvc_NetShareInfo2 *info2 = NULL;
546 int share_entries = 0;
549 ctr = (union srvsvc_NetShareCtr *) udp;
552 share_entries = ctr->ctr2->count;
553 info2 = &ctr->ctr2->array[0];
555 for (i = 0; i < share_entries; i++, info2++) {
556 if (strequal(tcon->share_name, info2->name)) {
557 info2->current_users++;
565 /****************************************************************************
566 Count the entries belonging to all services in the connection db.
567 ****************************************************************************/
569 static void count_connections_for_all_shares(union srvsvc_NetShareCtr *ctr)
572 status = smbXsrv_tcon_global_traverse(count_for_all_fn, ctr);
574 if (!NT_STATUS_IS_OK(status)) {
575 DEBUG(0,("count_connections_for_all_shares: traverse of "
576 "smbXsrv_tcon_global.tdb failed - %s\n",
581 /*******************************************************************
582 Fill in a share info structure.
583 ********************************************************************/
585 static WERROR init_srv_share_info_ctr(struct pipes_struct *p,
586 struct srvsvc_NetShareInfoCtr *info_ctr,
587 uint32_t *resume_handle_p,
588 uint32_t *total_entries,
591 const struct loadparm_substitution *lp_sub =
592 loadparm_s3_global_substitution();
593 uint32_t num_entries = 0;
594 uint32_t alloc_entries = 0;
595 int num_services = 0;
597 TALLOC_CTX *ctx = p->mem_ctx;
599 uint32_t valid_share_count = 0;
601 union srvsvc_NetShareCtr ctr;
602 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
604 DEBUG(5,("init_srv_share_info_ctr\n"));
606 /* Ensure all the usershares are loaded. */
608 delete_and_reload_printers();
609 load_usershare_shares(NULL, connections_snum_used);
610 load_registry_shares();
611 num_services = lp_numservices();
614 allowed = talloc_zero_array(ctx, bool, num_services);
615 W_ERROR_HAVE_NO_MEMORY(allowed);
617 /* Count the number of entries. */
618 for (snum = 0; snum < num_services; snum++) {
619 if (lp_browseable(snum) && lp_snum_ok(snum) &&
620 is_enumeration_allowed(p, snum) &&
621 (all_shares || !is_hidden_share(snum)) ) {
622 DEBUG(10, ("counting service %s\n",
623 lp_servicename(talloc_tos(), lp_sub, snum) ? lp_servicename(talloc_tos(), lp_sub, snum) : "(null)"));
624 allowed[snum] = true;
627 DEBUG(10, ("NOT counting service %s\n",
628 lp_servicename(talloc_tos(), lp_sub, snum) ? lp_servicename(talloc_tos(), lp_sub, snum) : "(null)"));
632 if (!num_entries || (resume_handle >= num_entries)) {
636 /* Calculate alloc entries. */
637 alloc_entries = num_entries - resume_handle;
638 switch (info_ctr->level) {
640 ctr.ctr0 = talloc_zero(ctx, struct srvsvc_NetShareCtr0);
641 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
643 ctr.ctr0->count = alloc_entries;
644 ctr.ctr0->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
645 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
647 for (snum = 0; snum < num_services; snum++) {
649 (resume_handle <= (i + valid_share_count++)) ) {
650 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
657 ctr.ctr1 = talloc_zero(ctx, struct srvsvc_NetShareCtr1);
658 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
660 ctr.ctr1->count = alloc_entries;
661 ctr.ctr1->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
662 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
664 for (snum = 0; snum < num_services; snum++) {
666 (resume_handle <= (i + valid_share_count++)) ) {
667 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
674 ctr.ctr2 = talloc_zero(ctx, struct srvsvc_NetShareCtr2);
675 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
677 ctr.ctr2->count = alloc_entries;
678 ctr.ctr2->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
679 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
681 for (snum = 0; snum < num_services; snum++) {
683 (resume_handle <= (i + valid_share_count++)) ) {
684 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
688 count_connections_for_all_shares(&ctr);
692 ctr.ctr501 = talloc_zero(ctx, struct srvsvc_NetShareCtr501);
693 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
695 ctr.ctr501->count = alloc_entries;
696 ctr.ctr501->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
697 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
699 for (snum = 0; snum < num_services; snum++) {
701 (resume_handle <= (i + valid_share_count++)) ) {
702 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
709 ctr.ctr502 = talloc_zero(ctx, struct srvsvc_NetShareCtr502);
710 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
712 ctr.ctr502->count = alloc_entries;
713 ctr.ctr502->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
714 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
716 for (snum = 0; snum < num_services; snum++) {
718 (resume_handle <= (i + valid_share_count++)) ) {
719 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
726 ctr.ctr1004 = talloc_zero(ctx, struct srvsvc_NetShareCtr1004);
727 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
729 ctr.ctr1004->count = alloc_entries;
730 ctr.ctr1004->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
731 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
733 for (snum = 0; snum < num_services; snum++) {
735 (resume_handle <= (i + valid_share_count++)) ) {
736 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
743 ctr.ctr1005 = talloc_zero(ctx, struct srvsvc_NetShareCtr1005);
744 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
746 ctr.ctr1005->count = alloc_entries;
747 ctr.ctr1005->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
748 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
750 for (snum = 0; snum < num_services; snum++) {
752 (resume_handle <= (i + valid_share_count++)) ) {
753 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
760 ctr.ctr1006 = talloc_zero(ctx, struct srvsvc_NetShareCtr1006);
761 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
763 ctr.ctr1006->count = alloc_entries;
764 ctr.ctr1006->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
765 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
767 for (snum = 0; snum < num_services; snum++) {
769 (resume_handle <= (i + valid_share_count++)) ) {
770 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
777 ctr.ctr1007 = talloc_zero(ctx, struct srvsvc_NetShareCtr1007);
778 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
780 ctr.ctr1007->count = alloc_entries;
781 ctr.ctr1007->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
782 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
784 for (snum = 0; snum < num_services; snum++) {
786 (resume_handle <= (i + valid_share_count++)) ) {
787 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
794 ctr.ctr1501 = talloc_zero(ctx, struct srvsvc_NetShareCtr1501);
795 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
797 ctr.ctr1501->count = alloc_entries;
798 ctr.ctr1501->array = talloc_zero_array(ctx, struct sec_desc_buf, alloc_entries);
799 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
801 for (snum = 0; snum < num_services; snum++) {
803 (resume_handle <= (i + valid_share_count++)) ) {
804 struct sec_desc_buf *sd_buf = NULL;
805 init_srv_share_info_1501(p, &sd_buf, snum);
806 ctr.ctr1501->array[i++] = *sd_buf;
813 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
815 return WERR_INVALID_LEVEL;
818 *total_entries = alloc_entries;
819 if (resume_handle_p) {
821 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
823 *resume_handle_p = num_entries;
832 /*******************************************************************
833 fill in a sess info level 0 structure.
834 ********************************************************************/
836 static WERROR init_srv_sess_info_0(struct pipes_struct *p,
837 struct srvsvc_NetSessCtr0 *ctr0,
838 uint32_t *resume_handle_p,
839 uint32_t *total_entries)
841 struct sessionid *session_list;
842 uint32_t num_entries = 0;
843 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
844 *total_entries = list_sessions(p->mem_ctx, &session_list);
846 DEBUG(5,("init_srv_sess_info_0\n"));
849 if (resume_handle_p) {
850 *resume_handle_p = 0;
855 for (; resume_handle < *total_entries; resume_handle++) {
857 ctr0->array = talloc_realloc(p->mem_ctx,
859 struct srvsvc_NetSessInfo0,
861 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
863 ctr0->array[num_entries].client =
864 session_list[resume_handle].remote_machine;
869 ctr0->count = num_entries;
871 if (resume_handle_p) {
872 if (*resume_handle_p >= *total_entries) {
873 *resume_handle_p = 0;
875 *resume_handle_p = resume_handle;
882 /***********************************************************************
883 * find out the session on which this file is open and bump up its count
884 **********************************************************************/
886 static int count_sess_files_fn(struct file_id fid,
887 const struct share_mode_data *d,
888 const struct share_mode_entry *e,
891 struct sess_file_info *info = data;
892 uint32_t rh = info->resume_handle;
895 for (i=0; i < info->num_entries; i++) {
896 /* rh+info->num_entries is safe, as we've
898 *total_entries > resume_handle &&
899 info->num_entries = *total_entries - resume_handle;
900 inside init_srv_sess_info_1() below.
902 struct sessionid *sess = &info->session_list[rh + i];
903 if ((e->uid == sess->uid) &&
904 server_id_equal(&e->pid, &sess->pid)) {
906 info->ctr->array[i].num_open++;
913 /*******************************************************************
914 * count the num of open files on all sessions
915 *******************************************************************/
917 static void net_count_files_for_all_sess(struct srvsvc_NetSessCtr1 *ctr1,
918 struct sessionid *session_list,
919 uint32_t resume_handle,
920 uint32_t num_entries)
922 struct sess_file_info s_file_info;
924 s_file_info.ctr = ctr1;
925 s_file_info.session_list = session_list;
926 s_file_info.resume_handle = resume_handle;
927 s_file_info.num_entries = num_entries;
929 share_entry_forall(count_sess_files_fn, &s_file_info);
932 /*******************************************************************
933 fill in a sess info level 1 structure.
934 ********************************************************************/
936 static WERROR init_srv_sess_info_1(struct pipes_struct *p,
937 struct srvsvc_NetSessCtr1 *ctr1,
938 uint32_t *resume_handle_p,
939 uint32_t *total_entries)
941 struct sessionid *session_list;
942 uint32_t num_entries = 0;
943 time_t now = time(NULL);
944 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
949 if (resume_handle_p) {
950 *resume_handle_p = 0;
955 *total_entries = list_sessions(p->mem_ctx, &session_list);
957 if (resume_handle >= *total_entries) {
958 if (resume_handle_p) {
959 *resume_handle_p = 0;
964 /* We know num_entries must be positive, due to
965 the check resume_handle >= *total_entries above. */
967 num_entries = *total_entries - resume_handle;
969 ctr1->array = talloc_zero_array(p->mem_ctx,
970 struct srvsvc_NetSessInfo1,
973 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
975 for (num_entries = 0; resume_handle < *total_entries; num_entries++, resume_handle++) {
976 uint32_t connect_time;
979 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
980 guest = strequal( session_list[resume_handle].username, lp_guest_account() );
982 ctr1->array[num_entries].client = session_list[resume_handle].remote_machine;
983 ctr1->array[num_entries].user = session_list[resume_handle].username;
984 ctr1->array[num_entries].num_open = 0;/* computed later */
985 ctr1->array[num_entries].time = connect_time;
986 ctr1->array[num_entries].idle_time = 0;
987 ctr1->array[num_entries].user_flags = guest;
990 ctr1->count = num_entries;
992 /* count open files on all sessions in single tdb traversal */
993 net_count_files_for_all_sess(ctr1, session_list,
994 resume_handle_p ? *resume_handle_p : 0,
997 if (resume_handle_p) {
998 if (*resume_handle_p >= *total_entries) {
999 *resume_handle_p = 0;
1001 *resume_handle_p = resume_handle;
1008 /*******************************************************************
1009 find the share connection on which this open exists.
1010 ********************************************************************/
1012 static int share_file_fn(struct file_id fid,
1013 const struct share_mode_data *d,
1014 const struct share_mode_entry *e,
1017 struct share_file_stat *sfs = data;
1019 uint32_t offset = sfs->total_entries - sfs->resp_entries;
1021 if (strequal(d->servicepath, sfs->in_sharepath)) {
1022 for (i=0; i < sfs->resp_entries; i++) {
1023 if (server_id_equal(
1024 &e->pid, &sfs->svrid_arr[offset + i])) {
1025 sfs->netconn_arr[i].num_open ++;
1033 /*******************************************************************
1034 count number of open files on given share connections.
1035 ********************************************************************/
1037 static void count_share_opens(struct srvsvc_NetConnInfo1 *arr,
1038 struct server_id *svrid_arr, char *sharepath,
1039 uint32_t resp_entries, uint32_t total_entries)
1041 struct share_file_stat sfs;
1043 sfs.netconn_arr = arr;
1044 sfs.svrid_arr = svrid_arr;
1045 sfs.in_sharepath = sharepath;
1046 sfs.resp_entries = resp_entries;
1047 sfs.total_entries = total_entries;
1049 share_entry_forall(share_file_fn, &sfs);
1052 /****************************************************************************
1053 process an entry from the connection db.
1054 ****************************************************************************/
1056 static int share_conn_fn(struct smbXsrv_tcon_global0 *tcon,
1059 struct share_conn_stat *scs = data;
1061 if (!process_exists(tcon->server_id)) {
1065 if (strequal(tcon->share_name, scs->sharename)) {
1066 scs->svrid_arr = talloc_realloc(scs->ctx, scs->svrid_arr,
1069 if (!scs->svrid_arr) {
1073 scs->svrid_arr[scs->count] = tcon->server_id;
1080 /****************************************************************************
1081 Count the connections to a share. Build an array of serverid's owning these
1083 ****************************************************************************/
1085 static uint32_t count_share_conns(TALLOC_CTX *ctx, const char *sharename,
1086 struct server_id **arr)
1088 struct share_conn_stat scs;
1092 scs.sharename = sharename;
1093 scs.svrid_arr = NULL;
1096 status = smbXsrv_tcon_global_traverse(share_conn_fn, &scs);
1098 if (!NT_STATUS_IS_OK(status)) {
1099 DEBUG(0,("count_share_conns: traverse of "
1100 "smbXsrv_tcon_global.tdb failed - %s\n",
1101 nt_errstr(status)));
1105 *arr = scs.svrid_arr;
1109 /*******************************************************************
1110 fill in a conn info level 0 structure.
1111 ********************************************************************/
1113 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
1114 uint32_t *resume_handle_p,
1115 uint32_t *total_entries)
1117 uint32_t num_entries = 0;
1118 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
1120 DEBUG(5,("init_srv_conn_info_0\n"));
1123 if (resume_handle_p) {
1124 *resume_handle_p = 0;
1133 for (; resume_handle < *total_entries; resume_handle++) {
1135 ctr0->array = talloc_realloc(talloc_tos(),
1137 struct srvsvc_NetConnInfo0,
1140 return WERR_NOT_ENOUGH_MEMORY;
1143 ctr0->array[num_entries].conn_id = *total_entries;
1145 /* move on to creating next connection */
1149 ctr0->count = num_entries;
1150 *total_entries = num_entries;
1152 if (resume_handle_p) {
1153 if (*resume_handle_p >= *total_entries) {
1154 *resume_handle_p = 0;
1156 *resume_handle_p = resume_handle;
1163 /*******************************************************************
1164 fill in a conn info level 1 structure.
1165 ********************************************************************/
1167 static WERROR init_srv_conn_info_1(const char *name,
1168 struct srvsvc_NetConnCtr1 *ctr1,
1169 uint32_t *resume_handle_p,
1170 uint32_t *total_entries)
1172 const struct loadparm_substitution *lp_sub =
1173 loadparm_s3_global_substitution();
1174 uint32_t num_entries = 0;
1176 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
1177 char *share_name = NULL;
1178 struct server_id *svrid_arr = NULL;
1180 DEBUG(5,("init_srv_conn_info_1\n"));
1183 if (resume_handle_p) {
1184 *resume_handle_p = 0;
1189 /* check if this is a server name or a share name */
1190 if (name && (strlen(name) > 2) && (name[0] == '\\') &&
1191 (name[1] == '\\')) {
1193 /* 'name' is a server name - this part is unimplemented */
1196 /* 'name' is a share name */
1197 snum = find_service(talloc_tos(), name, &share_name);
1200 return WERR_NOT_ENOUGH_MEMORY;
1204 return WERR_INVALID_NAME;
1208 * count the num of connections to this share. Also,
1209 * build a list of serverid's that own these
1210 * connections. The serverid list is used later to
1211 * identify the share connection on which an open exists.
1214 *total_entries = count_share_conns(talloc_tos(),
1219 if (resume_handle >= *total_entries) {
1220 if (resume_handle_p) {
1221 *resume_handle_p = 0;
1227 * We know num_entries must be positive, due to
1228 * the check resume_handle >= *total_entries above.
1231 num_entries = *total_entries - resume_handle;
1235 ctr1->array = talloc_zero_array(talloc_tos(),
1236 struct srvsvc_NetConnInfo1,
1239 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
1241 for (num_entries = 0; resume_handle < *total_entries;
1242 num_entries++, resume_handle++) {
1244 ctr1->array[num_entries].conn_id = *total_entries;
1245 ctr1->array[num_entries].conn_type = 0x3;
1248 * if these are connections to a share, we are going to
1249 * compute the opens on them later. If it's for the server,
1250 * it's unimplemented.
1254 ctr1->array[num_entries].num_open = 1;
1257 ctr1->array[num_entries].num_users = 1;
1258 ctr1->array[num_entries].conn_time = 3;
1259 ctr1->array[num_entries].user = "dummy_user";
1260 ctr1->array[num_entries].share = "IPC$";
1263 /* now compute open files on the share connections */
1268 * the locking tdb, which has the open files information,
1269 * does not store share name or share (service) number, but
1270 * just the share path. So, we can compute open files only
1271 * on the share path. If more than one shares are defined
1272 * on a share path, open files on all of them are included
1275 * To have the correct behavior in case multiple shares
1276 * are defined on the same path, changes to tdb records
1277 * would be required. That would be lot more effort, so
1278 * this seems a good stopgap fix.
1281 count_share_opens(ctr1->array, svrid_arr,
1282 lp_path(talloc_tos(), lp_sub, snum),
1283 num_entries, *total_entries);
1287 ctr1->count = num_entries;
1288 *total_entries = num_entries;
1290 if (resume_handle_p) {
1291 *resume_handle_p = resume_handle;
1297 /*******************************************************************
1299 *******************************************************************/
1301 WERROR _srvsvc_NetFileEnum(struct pipes_struct *p,
1302 struct srvsvc_NetFileEnum *r)
1304 TALLOC_CTX *ctx = NULL;
1305 struct srvsvc_NetFileCtr3 *ctr3;
1306 uint32_t resume_hnd = 0;
1309 switch (r->in.info_ctr->level) {
1313 return WERR_INVALID_LEVEL;
1316 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1317 p->session_info->security_token)) {
1318 DEBUG(1, ("Enumerating files only allowed for "
1319 "administrators\n"));
1320 return WERR_ACCESS_DENIED;
1324 ctr3 = r->in.info_ctr->ctr.ctr3;
1326 werr = WERR_INVALID_PARAMETER;
1330 /* TODO -- Windows enumerates
1332 (c) open directories and files */
1334 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1335 if (!W_ERROR_IS_OK(werr)) {
1339 *r->out.totalentries = ctr3->count;
1340 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1341 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1349 /*******************************************************************
1350 _srvsvc_NetSrvGetInfo
1351 ********************************************************************/
1353 WERROR _srvsvc_NetSrvGetInfo(struct pipes_struct *p,
1354 struct srvsvc_NetSrvGetInfo *r)
1356 const struct loadparm_substitution *lp_sub =
1357 loadparm_s3_global_substitution();
1358 WERROR status = WERR_OK;
1360 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1362 if (!pipe_access_check(p)) {
1363 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1364 return WERR_ACCESS_DENIED;
1367 switch (r->in.level) {
1369 /* Technically level 102 should only be available to
1370 Administrators but there isn't anything super-secret
1371 here, as most of it is made up. */
1374 struct srvsvc_NetSrvInfo102 *info102;
1376 info102 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1378 return WERR_NOT_ENOUGH_MEMORY;
1381 info102->platform_id = PLATFORM_ID_NT;
1382 info102->server_name = lp_netbios_name();
1383 info102->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1384 info102->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1385 info102->server_type = lp_default_server_announce();
1386 info102->comment = string_truncate(lp_server_string(talloc_tos(), lp_sub),
1387 MAX_SERVER_STRING_LENGTH);
1388 info102->users = 0xffffffff;
1389 info102->disc = 0xf;
1390 info102->hidden = 0;
1391 info102->announce = 240;
1392 info102->anndelta = 3000;
1393 info102->licenses = 100000;
1394 info102->userpath = "C:\\";
1396 r->out.info->info102 = info102;
1400 struct srvsvc_NetSrvInfo101 *info101;
1402 info101 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1404 return WERR_NOT_ENOUGH_MEMORY;
1407 info101->platform_id = PLATFORM_ID_NT;
1408 info101->server_name = lp_netbios_name();
1409 info101->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1410 info101->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1411 info101->server_type = lp_default_server_announce();
1412 info101->comment = string_truncate(lp_server_string(talloc_tos(), lp_sub),
1413 MAX_SERVER_STRING_LENGTH);
1415 r->out.info->info101 = info101;
1419 struct srvsvc_NetSrvInfo100 *info100;
1421 info100 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1423 return WERR_NOT_ENOUGH_MEMORY;
1426 info100->platform_id = PLATFORM_ID_NT;
1427 info100->server_name = lp_netbios_name();
1429 r->out.info->info100 = info100;
1434 status = WERR_INVALID_LEVEL;
1438 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1443 /*******************************************************************
1444 _srvsvc_NetSrvSetInfo
1445 ********************************************************************/
1447 WERROR _srvsvc_NetSrvSetInfo(struct pipes_struct *p,
1448 struct srvsvc_NetSrvSetInfo *r)
1450 WERROR status = WERR_OK;
1452 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1454 /* Set up the net server set info structure. */
1456 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1461 /*******************************************************************
1463 ********************************************************************/
1465 WERROR _srvsvc_NetConnEnum(struct pipes_struct *p,
1466 struct srvsvc_NetConnEnum *r)
1470 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1472 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1473 p->session_info->security_token)) {
1474 DEBUG(1, ("Enumerating connections only allowed for "
1475 "administrators\n"));
1476 return WERR_ACCESS_DENIED;
1479 switch (r->in.info_ctr->level) {
1481 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1482 r->in.resume_handle,
1483 r->out.totalentries);
1486 werr = init_srv_conn_info_1(r->in.path,
1487 r->in.info_ctr->ctr.ctr1,
1488 r->in.resume_handle,
1489 r->out.totalentries);
1492 return WERR_INVALID_LEVEL;
1495 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1500 /*******************************************************************
1502 ********************************************************************/
1504 WERROR _srvsvc_NetSessEnum(struct pipes_struct *p,
1505 struct srvsvc_NetSessEnum *r)
1509 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1511 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1512 p->session_info->security_token)) {
1513 DEBUG(1, ("Enumerating sessions only allowed for "
1514 "administrators\n"));
1515 return WERR_ACCESS_DENIED;
1518 switch (r->in.info_ctr->level) {
1520 werr = init_srv_sess_info_0(p,
1521 r->in.info_ctr->ctr.ctr0,
1522 r->in.resume_handle,
1523 r->out.totalentries);
1526 werr = init_srv_sess_info_1(p,
1527 r->in.info_ctr->ctr.ctr1,
1528 r->in.resume_handle,
1529 r->out.totalentries);
1532 return WERR_INVALID_LEVEL;
1535 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1540 /*******************************************************************
1542 ********************************************************************/
1544 WERROR _srvsvc_NetSessDel(struct pipes_struct *p,
1545 struct srvsvc_NetSessDel *r)
1547 struct sessionid *session_list;
1548 int num_sessions, snum;
1549 const char *username;
1550 const char *machine;
1551 bool not_root = False;
1554 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1556 werr = WERR_ACCESS_DENIED;
1558 /* fail out now if you are not root or not a domain admin */
1560 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1561 ( ! nt_token_check_domain_rid(p->session_info->security_token,
1562 DOMAIN_RID_ADMINS))) {
1567 username = r->in.user;
1568 machine = r->in.client;
1570 /* strip leading backslashes if any */
1571 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1575 num_sessions = find_sessions(p->mem_ctx, username, machine,
1578 for (snum = 0; snum < num_sessions; snum++) {
1582 if (p->session_info->unix_token->uid != sec_initial_uid()) {
1587 ntstat = messaging_send(p->msg_ctx,
1588 session_list[snum].pid,
1589 MSG_SHUTDOWN, &data_blob_null);
1591 if (NT_STATUS_IS_OK(ntstat))
1598 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1605 /*******************************************************************
1606 _srvsvc_NetShareEnumAll
1607 ********************************************************************/
1609 WERROR _srvsvc_NetShareEnumAll(struct pipes_struct *p,
1610 struct srvsvc_NetShareEnumAll *r)
1614 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1616 if (!pipe_access_check(p)) {
1617 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1618 return WERR_ACCESS_DENIED;
1621 /* Create the list of shares for the response. */
1622 werr = init_srv_share_info_ctr(p,
1624 r->in.resume_handle,
1625 r->out.totalentries,
1628 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1633 /*******************************************************************
1634 _srvsvc_NetShareEnum
1635 ********************************************************************/
1637 WERROR _srvsvc_NetShareEnum(struct pipes_struct *p,
1638 struct srvsvc_NetShareEnum *r)
1642 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1644 if (!pipe_access_check(p)) {
1645 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1646 return WERR_ACCESS_DENIED;
1649 /* Create the list of shares for the response. */
1650 werr = init_srv_share_info_ctr(p,
1652 r->in.resume_handle,
1653 r->out.totalentries,
1656 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1661 /*******************************************************************
1662 _srvsvc_NetShareGetInfo
1663 ********************************************************************/
1665 WERROR _srvsvc_NetShareGetInfo(struct pipes_struct *p,
1666 struct srvsvc_NetShareGetInfo *r)
1668 WERROR status = WERR_OK;
1669 char *share_name = NULL;
1671 union srvsvc_NetShareInfo *info = r->out.info;
1673 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1675 if (!r->in.share_name) {
1676 return WERR_INVALID_NAME;
1679 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1681 return WERR_NOT_ENOUGH_MEMORY;
1684 return WERR_INVALID_NAME;
1687 switch (r->in.level) {
1689 info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1690 W_ERROR_HAVE_NO_MEMORY(info->info0);
1691 init_srv_share_info_0(p, info->info0, snum);
1694 info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1695 W_ERROR_HAVE_NO_MEMORY(info->info1);
1696 init_srv_share_info_1(p, info->info1, snum);
1699 info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1700 W_ERROR_HAVE_NO_MEMORY(info->info2);
1701 init_srv_share_info_2(p, info->info2, snum);
1702 info->info2->current_users =
1703 count_current_connections(info->info2->name, false);
1706 info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1707 W_ERROR_HAVE_NO_MEMORY(info->info501);
1708 init_srv_share_info_501(p, info->info501, snum);
1711 info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1712 W_ERROR_HAVE_NO_MEMORY(info->info502);
1713 init_srv_share_info_502(p, info->info502, snum);
1716 info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1717 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1718 init_srv_share_info_1004(p, info->info1004, snum);
1721 info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1722 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1723 init_srv_share_info_1005(p, info->info1005, snum);
1726 info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1727 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1728 init_srv_share_info_1006(p, info->info1006, snum);
1731 info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1732 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1733 init_srv_share_info_1007(p, info->info1007, snum);
1736 init_srv_share_info_1501(p, &info->info1501, snum);
1739 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1741 status = WERR_INVALID_LEVEL;
1745 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1750 /*******************************************************************
1751 _srvsvc_NetShareSetInfo. Modify share details.
1752 ********************************************************************/
1754 WERROR _srvsvc_NetShareSetInfo(struct pipes_struct *p,
1755 struct srvsvc_NetShareSetInfo *r)
1757 const struct loadparm_substitution *lp_sub =
1758 loadparm_s3_global_substitution();
1759 char *command = NULL;
1760 char *share_name = NULL;
1761 char *comment = NULL;
1762 const char *pathname = NULL;
1767 struct security_descriptor *psd = NULL;
1768 bool is_disk_op = False;
1769 const char *csc_policy = NULL;
1770 bool csc_policy_changed = false;
1771 const char *csc_policies[] = {"manual", "documents", "programs",
1773 uint32_t client_csc_policy;
1774 int max_connections = 0;
1775 TALLOC_CTX *ctx = p->mem_ctx;
1776 union srvsvc_NetShareInfo *info = r->in.info;
1778 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1780 if (!r->in.share_name) {
1781 return WERR_INVALID_NAME;
1784 if (r->out.parm_error) {
1785 *r->out.parm_error = 0;
1788 if ( strequal(r->in.share_name,"IPC$")
1789 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1790 || strequal(r->in.share_name,"global") )
1792 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s cannot be "
1793 "modified by a remote user.\n",
1794 r->in.share_name ));
1795 return WERR_ACCESS_DENIED;
1798 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1800 return WERR_NOT_ENOUGH_MEMORY;
1803 /* Does this share exist ? */
1805 return WERR_NERR_NETNAMENOTFOUND;
1807 /* No change to printer shares. */
1808 if (lp_printable(snum))
1809 return WERR_ACCESS_DENIED;
1811 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1813 /* fail out now if you are not root and not a disk op */
1815 if ( p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op ) {
1816 DEBUG(2,("_srvsvc_NetShareSetInfo: uid %u doesn't have the "
1817 "SeDiskOperatorPrivilege privilege needed to modify "
1819 (unsigned int)p->session_info->unix_token->uid,
1821 return WERR_ACCESS_DENIED;
1824 max_connections = lp_max_connections(snum);
1825 csc_policy = csc_policies[lp_csc_policy(snum)];
1827 switch (r->in.level) {
1829 pathname = lp_path(ctx, lp_sub, snum);
1830 comment = talloc_strdup(ctx, info->info1->comment);
1831 type = info->info1->type;
1835 comment = talloc_strdup(ctx, info->info2->comment);
1836 pathname = info->info2->path;
1837 type = info->info2->type;
1838 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1839 0 : info->info2->max_users;
1843 /* not supported on set but here for completeness */
1845 comment = talloc_strdup(ctx, info->info501->comment);
1846 type = info->info501->type;
1851 comment = talloc_strdup(ctx, info->info502->comment);
1852 pathname = info->info502->path;
1853 type = info->info502->type;
1854 psd = info->info502->sd_buf.sd;
1855 map_generic_share_sd_bits(psd);
1858 pathname = lp_path(ctx, lp_sub, snum);
1859 comment = talloc_strdup(ctx, info->info1004->comment);
1860 type = STYPE_DISKTREE;
1863 /* XP re-sets the csc policy even if it wasn't changed by the
1864 user, so we must compare it to see if it's what is set in
1865 smb.conf, so that we can contine other ops like setting
1867 client_csc_policy = (info->info1005->dfs_flags &
1868 SHARE_1005_CSC_POLICY_MASK) >>
1869 SHARE_1005_CSC_POLICY_SHIFT;
1871 if (client_csc_policy == lp_csc_policy(snum))
1874 csc_policy = csc_policies[client_csc_policy];
1875 csc_policy_changed = true;
1878 pathname = lp_path(ctx, lp_sub, snum);
1879 comment = lp_comment(ctx, lp_sub, snum);
1880 type = STYPE_DISKTREE;
1884 return WERR_ACCESS_DENIED;
1886 pathname = lp_path(ctx, lp_sub, snum);
1887 comment = lp_comment(ctx, lp_sub, snum);
1888 psd = info->info1501->sd;
1889 map_generic_share_sd_bits(psd);
1890 type = STYPE_DISKTREE;
1893 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1895 return WERR_INVALID_LEVEL;
1898 /* We can only modify disk shares. */
1899 if (type != STYPE_DISKTREE) {
1900 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s is not a "
1903 return WERR_ACCESS_DENIED;
1906 if (comment == NULL) {
1907 return WERR_NOT_ENOUGH_MEMORY;
1910 /* Check if the pathname is valid. */
1911 if (!(path = valid_share_pathname(p->mem_ctx, pathname ))) {
1912 DEBUG(5,("_srvsvc_NetShareSetInfo: invalid pathname %s\n",
1914 return WERR_BAD_PATHNAME;
1917 /* Ensure share name, pathname and comment don't contain '"' characters. */
1918 string_replace(share_name, '"', ' ');
1919 string_replace(path, '"', ' ');
1920 string_replace(comment, '"', ' ');
1922 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1923 lp_change_share_command(talloc_tos(), lp_sub) ? lp_change_share_command(talloc_tos(), lp_sub) : "NULL" ));
1925 /* Only call modify function if something changed. */
1927 if (strcmp(path, lp_path(talloc_tos(), lp_sub, snum))
1928 || strcmp(comment, lp_comment(talloc_tos(), lp_sub, snum))
1929 || (lp_max_connections(snum) != max_connections)
1930 || csc_policy_changed) {
1932 if (!lp_change_share_command(talloc_tos(), lp_sub) || !*lp_change_share_command(talloc_tos(), lp_sub)) {
1933 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1934 return WERR_ACCESS_DENIED;
1937 command = talloc_asprintf(p->mem_ctx,
1938 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d \"%s\"",
1939 lp_change_share_command(talloc_tos(), lp_sub),
1940 get_dyn_CONFIGFILE(),
1947 return WERR_NOT_ENOUGH_MEMORY;
1950 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1952 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1957 ret = smbrun(command, NULL, NULL);
1959 /* Tell everyone we updated smb.conf. */
1960 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED,
1967 /********* END SeDiskOperatorPrivilege BLOCK *********/
1969 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1972 TALLOC_FREE(command);
1975 return WERR_ACCESS_DENIED;
1977 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1981 /* Replace SD if changed. */
1983 struct security_descriptor *old_sd;
1987 old_sd = get_share_security(p->mem_ctx, lp_servicename(talloc_tos(), lp_sub, snum), &sd_size);
1989 if (old_sd && !security_descriptor_equal(old_sd, psd)) {
1990 status = set_share_security(share_name, psd);
1991 if (!NT_STATUS_IS_OK(status)) {
1992 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1998 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
2003 /*******************************************************************
2004 _srvsvc_NetShareAdd.
2005 Call 'add_share_command "sharename" "pathname"
2006 "comment" "max connections = "
2007 ********************************************************************/
2009 WERROR _srvsvc_NetShareAdd(struct pipes_struct *p,
2010 struct srvsvc_NetShareAdd *r)
2012 char *command = NULL;
2013 char *share_name_in = NULL;
2014 char *share_name = NULL;
2015 char *comment = NULL;
2016 char *pathname = NULL;
2021 struct security_descriptor *psd = NULL;
2023 int max_connections = 0;
2025 TALLOC_CTX *ctx = p->mem_ctx;
2026 const struct loadparm_substitution *lp_sub =
2027 loadparm_s3_global_substitution();
2029 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
2031 if (r->out.parm_error) {
2032 *r->out.parm_error = 0;
2035 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2037 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op )
2038 return WERR_ACCESS_DENIED;
2040 if (!lp_add_share_command(talloc_tos(), lp_sub) || !*lp_add_share_command(talloc_tos(), lp_sub)) {
2041 DBG_WARNING("_srvsvc_NetShareAdd: No \"add share command\" parameter set in smb.conf.\n");
2042 return WERR_ACCESS_DENIED;
2045 switch (r->in.level) {
2047 /* No path. Not enough info in a level 0 to do anything. */
2048 return WERR_ACCESS_DENIED;
2050 /* Not enough info in a level 1 to do anything. */
2051 return WERR_ACCESS_DENIED;
2053 share_name_in = talloc_strdup(ctx, r->in.info->info2->name);
2054 comment = talloc_strdup(ctx, r->in.info->info2->comment);
2055 pathname = talloc_strdup(ctx, r->in.info->info2->path);
2056 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
2057 0 : r->in.info->info2->max_users;
2058 type = r->in.info->info2->type;
2061 /* No path. Not enough info in a level 501 to do anything. */
2062 return WERR_ACCESS_DENIED;
2064 share_name_in = talloc_strdup(ctx, r->in.info->info502->name);
2065 comment = talloc_strdup(ctx, r->in.info->info502->comment);
2066 pathname = talloc_strdup(ctx, r->in.info->info502->path);
2067 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
2068 0 : r->in.info->info502->max_users;
2069 type = r->in.info->info502->type;
2070 psd = r->in.info->info502->sd_buf.sd;
2071 map_generic_share_sd_bits(psd);
2074 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
2080 return WERR_ACCESS_DENIED;
2082 /* DFS only level. */
2083 return WERR_ACCESS_DENIED;
2085 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
2087 return WERR_INVALID_LEVEL;
2090 /* check for invalid share names */
2092 if (!share_name_in || !validate_net_name(share_name_in,
2093 INVALID_SHARENAME_CHARS,
2094 strlen(share_name_in))) {
2095 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
2096 share_name_in ? share_name_in : ""));
2097 return WERR_INVALID_NAME;
2100 if (strequal(share_name_in,"IPC$") || strequal(share_name_in,"global")
2101 || (lp_enable_asu_support() &&
2102 strequal(share_name_in,"ADMIN$"))) {
2103 return WERR_ACCESS_DENIED;
2106 snum = find_service(ctx, share_name_in, &share_name);
2108 return WERR_NOT_ENOUGH_MEMORY;
2111 /* Share already exists. */
2113 return WERR_FILE_EXISTS;
2116 /* We can only add disk shares. */
2117 if (type != STYPE_DISKTREE) {
2118 return WERR_ACCESS_DENIED;
2121 /* Check if the pathname is valid. */
2122 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
2123 return WERR_BAD_PATHNAME;
2126 ret = sys_lstat(path, &st, false);
2127 if (ret == -1 && (errno != EACCES)) {
2129 * If path has any other than permission
2130 * problem, return WERR_FILE_NOT_FOUND (as Windows
2133 return WERR_FILE_NOT_FOUND;
2136 /* Ensure share name, pathname and comment don't contain '"' characters. */
2137 string_replace(share_name_in, '"', ' ');
2138 string_replace(share_name, '"', ' ');
2139 string_replace(path, '"', ' ');
2141 string_replace(comment, '"', ' ');
2144 command = talloc_asprintf(ctx,
2145 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
2146 lp_add_share_command(talloc_tos(), lp_sub),
2147 get_dyn_CONFIGFILE(),
2150 comment ? comment : "",
2153 return WERR_NOT_ENOUGH_MEMORY;
2156 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
2158 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
2163 /* FIXME: use libnetconf here - gd */
2165 ret = smbrun(command, NULL, NULL);
2167 /* Tell everyone we updated smb.conf. */
2168 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
2174 /********* END SeDiskOperatorPrivilege BLOCK *********/
2176 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
2179 TALLOC_FREE(command);
2182 return WERR_ACCESS_DENIED;
2186 /* Note we use share_name here, not share_name_in as
2187 we need a canonicalized name for setting security. */
2188 status = set_share_security(share_name, psd);
2189 if (!NT_STATUS_IS_OK(status)) {
2190 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
2196 * We don't call reload_services() here, the message will
2197 * cause this to be done before the next packet is read
2198 * from the client. JRA.
2201 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
2206 /*******************************************************************
2208 Call "delete share command" with the share name as
2210 ********************************************************************/
2212 WERROR _srvsvc_NetShareDel(struct pipes_struct *p,
2213 struct srvsvc_NetShareDel *r)
2215 char *command = NULL;
2216 char *share_name = NULL;
2220 TALLOC_CTX *ctx = p->mem_ctx;
2221 const struct loadparm_substitution *lp_sub =
2222 loadparm_s3_global_substitution();
2224 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
2226 if (!r->in.share_name) {
2227 return WERR_NERR_NETNAMENOTFOUND;
2230 if ( strequal(r->in.share_name,"IPC$")
2231 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
2232 || strequal(r->in.share_name,"global") )
2234 return WERR_ACCESS_DENIED;
2237 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
2239 return WERR_NOT_ENOUGH_MEMORY;
2243 return WERR_BAD_NET_NAME;
2246 /* No change to printer shares. */
2247 if (lp_printable(snum))
2248 return WERR_ACCESS_DENIED;
2250 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2252 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op )
2253 return WERR_ACCESS_DENIED;
2255 if (!lp_delete_share_command(talloc_tos(), lp_sub) || !*lp_delete_share_command(talloc_tos(), lp_sub)) {
2256 DBG_WARNING("_srvsvc_NetShareDel: No \"delete share command\" parameter set in smb.conf.\n");
2257 return WERR_ACCESS_DENIED;
2260 command = talloc_asprintf(ctx,
2262 lp_delete_share_command(talloc_tos(), lp_sub),
2263 get_dyn_CONFIGFILE(),
2266 return WERR_NOT_ENOUGH_MEMORY;
2269 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
2271 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
2276 ret = smbrun(command, NULL, NULL);
2278 /* Tell everyone we updated smb.conf. */
2279 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
2285 /********* END SeDiskOperatorPrivilege BLOCK *********/
2287 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
2290 return WERR_ACCESS_DENIED;
2292 /* Delete the SD in the database. */
2293 delete_share_security(share_name);
2295 lp_killservice(snum);
2300 /*******************************************************************
2301 _srvsvc_NetShareDelSticky
2302 ********************************************************************/
2304 WERROR _srvsvc_NetShareDelSticky(struct pipes_struct *p,
2305 struct srvsvc_NetShareDelSticky *r)
2307 struct srvsvc_NetShareDel q;
2309 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
2311 q.in.server_unc = r->in.server_unc;
2312 q.in.share_name = r->in.share_name;
2313 q.in.reserved = r->in.reserved;
2315 return _srvsvc_NetShareDel(p, &q);
2318 /*******************************************************************
2319 _srvsvc_NetRemoteTOD
2320 ********************************************************************/
2322 WERROR _srvsvc_NetRemoteTOD(struct pipes_struct *p,
2323 struct srvsvc_NetRemoteTOD *r)
2325 struct srvsvc_NetRemoteTODInfo *tod;
2327 time_t unixdate = time(NULL);
2329 /* We do this call first as if we do it *after* the gmtime call
2330 it overwrites the pointed-to values. JRA */
2332 uint32_t zone = get_time_zone(unixdate)/60;
2334 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2336 if ( !(tod = talloc_zero(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
2337 return WERR_NOT_ENOUGH_MEMORY;
2341 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2343 t = gmtime(&unixdate);
2346 tod->elapsed = unixdate;
2348 tod->hours = t->tm_hour;
2349 tod->mins = t->tm_min;
2350 tod->secs = t->tm_sec;
2352 tod->timezone = zone;
2353 tod->tinterval = 10000;
2354 tod->day = t->tm_mday;
2355 tod->month = t->tm_mon + 1;
2356 tod->year = 1900+t->tm_year;
2357 tod->weekday = t->tm_wday;
2359 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2364 /***********************************************************************************
2365 _srvsvc_NetGetFileSecurity
2366 Win9x NT tools get security descriptor.
2367 ***********************************************************************************/
2369 WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
2370 struct srvsvc_NetGetFileSecurity *r)
2372 TALLOC_CTX *frame = talloc_stackframe();
2373 const struct loadparm_substitution *lp_sub =
2374 loadparm_s3_global_substitution();
2375 struct smb_filename *smb_fname = NULL;
2377 char *servicename = NULL;
2381 struct conn_struct_tos *c = NULL;
2382 connection_struct *conn = NULL;
2383 struct sec_desc_buf *sd_buf = NULL;
2384 files_struct *fsp = NULL;
2386 uint32_t ucf_flags = 0;
2391 werr = WERR_NERR_NETNAMENOTFOUND;
2394 snum = find_service(frame, r->in.share, &servicename);
2396 werr = WERR_NOT_ENOUGH_MEMORY;
2400 DEBUG(10, ("Could not find service %s\n", servicename));
2401 werr = WERR_NERR_NETNAMENOTFOUND;
2405 nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
2407 lp_path(frame, lp_sub, snum),
2410 if (!NT_STATUS_IS_OK(nt_status)) {
2411 DEBUG(10, ("create_conn_struct failed: %s\n",
2412 nt_errstr(nt_status)));
2413 werr = ntstatus_to_werror(nt_status);
2418 nt_status = filename_convert(frame,
2425 if (!NT_STATUS_IS_OK(nt_status)) {
2426 werr = ntstatus_to_werror(nt_status);
2430 nt_status = SMB_VFS_CREATE_FILE(
2433 &conn->cwd_fsp, /* dirfsp */
2434 smb_fname, /* fname */
2435 FILE_READ_ATTRIBUTES, /* access_mask */
2436 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2437 FILE_OPEN, /* create_disposition*/
2438 0, /* create_options */
2439 0, /* file_attributes */
2440 INTERNAL_OPEN_ONLY, /* oplock_request */
2442 0, /* allocation_size */
2443 0, /* private_flags */
2448 NULL, NULL); /* create context */
2450 if (!NT_STATUS_IS_OK(nt_status)) {
2451 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2452 smb_fname_str_dbg(smb_fname)));
2453 werr = ntstatus_to_werror(nt_status);
2457 sd_buf = talloc_zero(p->mem_ctx, struct sec_desc_buf);
2459 werr = WERR_NOT_ENOUGH_MEMORY;
2463 nt_status = SMB_VFS_FGET_NT_ACL(fsp,
2466 |SECINFO_DACL), sd_buf, &sd_buf->sd);
2468 if (!NT_STATUS_IS_OK(nt_status)) {
2469 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2470 "for file %s\n", smb_fname_str_dbg(smb_fname)));
2471 werr = ntstatus_to_werror(nt_status);
2472 TALLOC_FREE(sd_buf);
2476 if (sd_buf->sd->dacl) {
2477 sd_buf->sd->dacl->revision = NT4_ACL_REVISION;
2480 sd_size = ndr_size_security_descriptor(sd_buf->sd, 0);
2482 sd_buf->sd_size = sd_size;
2484 *r->out.sd_buf = sd_buf;
2491 close_file(NULL, fsp, NORMAL_CLOSE);
2498 /***********************************************************************************
2499 _srvsvc_NetSetFileSecurity
2500 Win9x NT tools set security descriptor.
2501 ***********************************************************************************/
2503 WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
2504 struct srvsvc_NetSetFileSecurity *r)
2506 TALLOC_CTX *frame = talloc_stackframe();
2507 const struct loadparm_substitution *lp_sub =
2508 loadparm_s3_global_substitution();
2509 struct smb_filename *smb_fname = NULL;
2510 char *servicename = NULL;
2511 files_struct *fsp = NULL;
2515 struct conn_struct_tos *c = NULL;
2516 connection_struct *conn = NULL;
2518 struct security_descriptor *psd = NULL;
2519 uint32_t security_info_sent = 0;
2520 uint32_t ucf_flags = 0;
2525 werr = WERR_NERR_NETNAMENOTFOUND;
2529 snum = find_service(frame, r->in.share, &servicename);
2531 werr = WERR_NOT_ENOUGH_MEMORY;
2536 DEBUG(10, ("Could not find service %s\n", servicename));
2537 werr = WERR_NERR_NETNAMENOTFOUND;
2541 nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
2543 lp_path(frame, lp_sub, snum),
2546 if (!NT_STATUS_IS_OK(nt_status)) {
2547 DEBUG(10, ("create_conn_struct failed: %s\n",
2548 nt_errstr(nt_status)));
2549 werr = ntstatus_to_werror(nt_status);
2554 nt_status = filename_convert(frame,
2561 if (!NT_STATUS_IS_OK(nt_status)) {
2562 werr = ntstatus_to_werror(nt_status);
2566 nt_status = SMB_VFS_CREATE_FILE(
2569 &conn->cwd_fsp, /* dirfsp */
2570 smb_fname, /* fname */
2571 FILE_WRITE_ATTRIBUTES, /* access_mask */
2572 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2573 FILE_OPEN, /* create_disposition*/
2574 0, /* create_options */
2575 0, /* file_attributes */
2576 INTERNAL_OPEN_ONLY, /* oplock_request */
2578 0, /* allocation_size */
2579 0, /* private_flags */
2584 NULL, NULL); /* create context */
2586 if (!NT_STATUS_IS_OK(nt_status)) {
2587 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2588 smb_fname_str_dbg(smb_fname)));
2589 werr = ntstatus_to_werror(nt_status);
2593 psd = r->in.sd_buf->sd;
2594 security_info_sent = r->in.securityinformation;
2596 nt_status = set_sd(fsp, psd, security_info_sent);
2598 if (!NT_STATUS_IS_OK(nt_status) ) {
2599 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2600 "on file %s\n", r->in.share));
2601 werr = WERR_ACCESS_DENIED;
2610 close_file(NULL, fsp, NORMAL_CLOSE);
2617 /***********************************************************************************
2618 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2619 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2620 These disks would the disks listed by this function.
2621 Users could then create shares relative to these disks. Watch out for moving these disks around.
2622 "Nigel Williams" <nigel@veritas.com>.
2623 ***********************************************************************************/
2625 static const char *server_disks[] = {"C:"};
2627 static uint32_t get_server_disk_count(void)
2629 return sizeof(server_disks)/sizeof(server_disks[0]);
2632 static uint32_t init_server_disk_enum(uint32_t *resume)
2634 uint32_t server_disk_count = get_server_disk_count();
2636 /*resume can be an offset into the list for now*/
2638 if(*resume & 0x80000000)
2641 if(*resume > server_disk_count)
2642 *resume = server_disk_count;
2644 return server_disk_count - *resume;
2647 static const char *next_server_disk_enum(uint32_t *resume)
2651 if(init_server_disk_enum(resume) == 0)
2654 disk = server_disks[*resume];
2658 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2663 /********************************************************************
2665 ********************************************************************/
2667 WERROR _srvsvc_NetDiskEnum(struct pipes_struct *p,
2668 struct srvsvc_NetDiskEnum *r)
2671 const char *disk_name;
2672 TALLOC_CTX *ctx = p->mem_ctx;
2674 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2678 *r->out.totalentries = init_server_disk_enum(&resume);
2680 r->out.info->disks = talloc_zero_array(ctx, struct srvsvc_NetDiskInfo0,
2681 MAX_SERVER_DISK_ENTRIES);
2682 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2684 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2686 r->out.info->count = 0;
2688 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2690 r->out.info->count++;
2692 /*copy disk name into a unicode string*/
2694 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2695 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2698 /* add a terminating null string. Is this there if there is more data to come? */
2700 r->out.info->count++;
2702 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2703 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2705 if (r->out.resume_handle) {
2706 *r->out.resume_handle = resume;
2712 /********************************************************************
2713 _srvsvc_NetNameValidate
2714 ********************************************************************/
2716 WERROR _srvsvc_NetNameValidate(struct pipes_struct *p,
2717 struct srvsvc_NetNameValidate *r)
2719 switch (r->in.name_type) {
2721 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2722 strlen_m(r->in.name)))
2724 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2726 return WERR_INVALID_NAME;
2731 return WERR_INVALID_LEVEL;
2737 /*******************************************************************
2738 ********************************************************************/
2740 struct enum_file_close_state {
2741 struct srvsvc_NetFileClose *r;
2742 struct messaging_context *msg_ctx;
2745 static int enum_file_close_fn(struct file_id id,
2746 const struct share_mode_data *d,
2747 const struct share_mode_entry *e,
2750 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2751 struct enum_file_close_state *state =
2752 (struct enum_file_close_state *)private_data;
2753 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2755 if (fid != state->r->in.fid) {
2756 return 0; /* Not this file. */
2759 if (!process_exists(e->pid) ) {
2763 /* Ok - send the close message. */
2764 DBG_DEBUG("request to close file %s, %s\n", d->servicepath,
2765 share_mode_str(talloc_tos(), 0, &id, e));
2767 share_mode_entry_to_message(msg, &id, e);
2769 state->r->out.result = ntstatus_to_werror(
2770 messaging_send_buf(state->msg_ctx,
2771 e->pid, MSG_SMB_CLOSE_FILE,
2772 (uint8_t *)msg, sizeof(msg)));
2777 /********************************************************************
2778 Close a file given a 32-bit file id.
2779 ********************************************************************/
2781 WERROR _srvsvc_NetFileClose(struct pipes_struct *p,
2782 struct srvsvc_NetFileClose *r)
2784 struct enum_file_close_state state;
2787 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2789 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2791 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op) {
2792 return WERR_ACCESS_DENIED;
2795 /* enum_file_close_fn sends the close message to
2796 * the relevant smbd process. */
2798 r->out.result = WERR_FILE_NOT_FOUND;
2800 state.msg_ctx = p->msg_ctx;
2801 share_entry_forall(enum_file_close_fn, &state);
2802 return r->out.result;
2805 /********************************************************************
2806 ********************************************************************/
2808 WERROR _srvsvc_NetCharDevEnum(struct pipes_struct *p,
2809 struct srvsvc_NetCharDevEnum *r)
2811 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2812 return WERR_NOT_SUPPORTED;
2815 WERROR _srvsvc_NetCharDevGetInfo(struct pipes_struct *p,
2816 struct srvsvc_NetCharDevGetInfo *r)
2818 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2819 return WERR_NOT_SUPPORTED;
2822 WERROR _srvsvc_NetCharDevControl(struct pipes_struct *p,
2823 struct srvsvc_NetCharDevControl *r)
2825 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2826 return WERR_NOT_SUPPORTED;
2829 WERROR _srvsvc_NetCharDevQEnum(struct pipes_struct *p,
2830 struct srvsvc_NetCharDevQEnum *r)
2832 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2833 return WERR_NOT_SUPPORTED;
2836 WERROR _srvsvc_NetCharDevQGetInfo(struct pipes_struct *p,
2837 struct srvsvc_NetCharDevQGetInfo *r)
2839 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2840 return WERR_NOT_SUPPORTED;
2843 WERROR _srvsvc_NetCharDevQSetInfo(struct pipes_struct *p,
2844 struct srvsvc_NetCharDevQSetInfo *r)
2846 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2847 return WERR_NOT_SUPPORTED;
2850 WERROR _srvsvc_NetCharDevQPurge(struct pipes_struct *p,
2851 struct srvsvc_NetCharDevQPurge *r)
2853 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2854 return WERR_NOT_SUPPORTED;
2857 WERROR _srvsvc_NetCharDevQPurgeSelf(struct pipes_struct *p,
2858 struct srvsvc_NetCharDevQPurgeSelf *r)
2860 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2861 return WERR_NOT_SUPPORTED;
2864 WERROR _srvsvc_NetFileGetInfo(struct pipes_struct *p,
2865 struct srvsvc_NetFileGetInfo *r)
2867 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2868 return WERR_NOT_SUPPORTED;
2871 WERROR _srvsvc_NetShareCheck(struct pipes_struct *p,
2872 struct srvsvc_NetShareCheck *r)
2874 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2875 return WERR_NOT_SUPPORTED;
2878 WERROR _srvsvc_NetServerStatisticsGet(struct pipes_struct *p,
2879 struct srvsvc_NetServerStatisticsGet *r)
2881 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2882 return WERR_NOT_SUPPORTED;
2885 WERROR _srvsvc_NetTransportAdd(struct pipes_struct *p,
2886 struct srvsvc_NetTransportAdd *r)
2888 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2889 return WERR_NOT_SUPPORTED;
2892 WERROR _srvsvc_NetTransportEnum(struct pipes_struct *p,
2893 struct srvsvc_NetTransportEnum *r)
2895 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2896 return WERR_NOT_SUPPORTED;
2899 WERROR _srvsvc_NetTransportDel(struct pipes_struct *p,
2900 struct srvsvc_NetTransportDel *r)
2902 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2903 return WERR_NOT_SUPPORTED;
2906 WERROR _srvsvc_NetSetServiceBits(struct pipes_struct *p,
2907 struct srvsvc_NetSetServiceBits *r)
2909 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2910 return WERR_NOT_SUPPORTED;
2913 WERROR _srvsvc_NetPathType(struct pipes_struct *p,
2914 struct srvsvc_NetPathType *r)
2916 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2917 return WERR_NOT_SUPPORTED;
2920 WERROR _srvsvc_NetPathCanonicalize(struct pipes_struct *p,
2921 struct srvsvc_NetPathCanonicalize *r)
2923 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2924 return WERR_NOT_SUPPORTED;
2927 WERROR _srvsvc_NetPathCompare(struct pipes_struct *p,
2928 struct srvsvc_NetPathCompare *r)
2930 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2931 return WERR_NOT_SUPPORTED;
2934 WERROR _srvsvc_NETRPRNAMECANONICALIZE(struct pipes_struct *p,
2935 struct srvsvc_NETRPRNAMECANONICALIZE *r)
2937 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2938 return WERR_NOT_SUPPORTED;
2941 WERROR _srvsvc_NetPRNameCompare(struct pipes_struct *p,
2942 struct srvsvc_NetPRNameCompare *r)
2944 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2945 return WERR_NOT_SUPPORTED;
2948 WERROR _srvsvc_NetShareDelStart(struct pipes_struct *p,
2949 struct srvsvc_NetShareDelStart *r)
2951 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2952 return WERR_NOT_SUPPORTED;
2955 WERROR _srvsvc_NetShareDelCommit(struct pipes_struct *p,
2956 struct srvsvc_NetShareDelCommit *r)
2958 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2959 return WERR_NOT_SUPPORTED;
2962 WERROR _srvsvc_NetServerTransportAddEx(struct pipes_struct *p,
2963 struct srvsvc_NetServerTransportAddEx *r)
2965 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2966 return WERR_NOT_SUPPORTED;
2969 WERROR _srvsvc_NetServerSetServiceBitsEx(struct pipes_struct *p,
2970 struct srvsvc_NetServerSetServiceBitsEx *r)
2972 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2973 return WERR_NOT_SUPPORTED;
2976 WERROR _srvsvc_NETRDFSGETVERSION(struct pipes_struct *p,
2977 struct srvsvc_NETRDFSGETVERSION *r)
2979 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2980 return WERR_NOT_SUPPORTED;
2983 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(struct pipes_struct *p,
2984 struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2986 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2987 return WERR_NOT_SUPPORTED;
2990 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(struct pipes_struct *p,
2991 struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2993 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2994 return WERR_NOT_SUPPORTED;
2997 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(struct pipes_struct *p,
2998 struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
3000 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3001 return WERR_NOT_SUPPORTED;
3004 WERROR _srvsvc_NETRDFSSETSERVERINFO(struct pipes_struct *p,
3005 struct srvsvc_NETRDFSSETSERVERINFO *r)
3007 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3008 return WERR_NOT_SUPPORTED;
3011 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(struct pipes_struct *p,
3012 struct srvsvc_NETRDFSCREATEEXITPOINT *r)
3014 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3015 return WERR_NOT_SUPPORTED;
3018 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(struct pipes_struct *p,
3019 struct srvsvc_NETRDFSDELETEEXITPOINT *r)
3021 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3022 return WERR_NOT_SUPPORTED;
3025 WERROR _srvsvc_NETRDFSMODIFYPREFIX(struct pipes_struct *p,
3026 struct srvsvc_NETRDFSMODIFYPREFIX *r)
3028 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3029 return WERR_NOT_SUPPORTED;
3032 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(struct pipes_struct *p,
3033 struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
3035 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3036 return WERR_NOT_SUPPORTED;
3039 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(struct pipes_struct *p,
3040 struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
3042 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3043 return WERR_NOT_SUPPORTED;
3046 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(struct pipes_struct *p,
3047 struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
3049 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3050 return WERR_NOT_SUPPORTED;
3053 /* include the generated boilerplate */
3054 #include "librpc/gen_ndr/ndr_srvsvc_scompat.c"