Add an entry for the "check" command to the tdbtool manpage.
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_srvsvc_nt.c
blob15af963c4c68191e5f572516c36c3ea46cd30c45
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997,
5 * Copyright (C) Jeremy Allison 2001.
6 * Copyright (C) Nigel Williams 2001.
7 * Copyright (C) Gerald (Jerry) Carter 2006.
8 * Copyright (C) Guenther Deschner 2008.
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. */
26 #include "includes.h"
28 extern const struct generic_mapping file_generic_mapping;
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
33 #define MAX_SERVER_DISK_ENTRIES 15
35 /* Use for enumerating connections, pipes, & files */
37 struct file_enum_count {
38 TALLOC_CTX *ctx;
39 const char *username;
40 struct srvsvc_NetFileCtr3 *ctr3;
43 struct sess_file_count {
44 struct server_id pid;
45 uid_t uid;
46 int count;
49 /****************************************************************************
50 Count the entries belonging to a service in the connection db.
51 ****************************************************************************/
53 static int pipe_enum_fn( struct db_record *rec, void *p)
55 struct pipe_open_rec prec;
56 struct file_enum_count *fenum = (struct file_enum_count *)p;
57 struct srvsvc_NetFileInfo3 *f;
58 int i = fenum->ctr3->count;
59 char *fullpath = NULL;
60 const char *username;
62 if (rec->value.dsize != sizeof(struct pipe_open_rec))
63 return 0;
65 memcpy(&prec, rec->value.dptr, sizeof(struct pipe_open_rec));
67 if ( !process_exists(prec.pid) ) {
68 return 0;
71 username = uidtoname(prec.uid);
73 if ((fenum->username != NULL)
74 && !strequal(username, fenum->username)) {
75 return 0;
78 fullpath = talloc_asprintf(fenum->ctx, "\\PIPE\\%s", prec.name );
79 if (!fullpath) {
80 return 1;
83 f = TALLOC_REALLOC_ARRAY(fenum->ctx, fenum->ctr3->array,
84 struct srvsvc_NetFileInfo3, i+1);
85 if ( !f ) {
86 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
87 return 1;
89 fenum->ctr3->array = f;
91 init_srvsvc_NetFileInfo3(&fenum->ctr3->array[i],
92 (((uint32_t)(procid_to_pid(&prec.pid))<<16) | prec.pnum),
93 (FILE_READ_DATA|FILE_WRITE_DATA),
95 fullpath,
96 username);
98 fenum->ctr3->count++;
100 return 0;
103 /*******************************************************************
104 ********************************************************************/
106 static WERROR net_enum_pipes(TALLOC_CTX *ctx,
107 const char *username,
108 struct srvsvc_NetFileCtr3 **ctr3,
109 uint32_t resume )
111 struct file_enum_count fenum;
113 fenum.ctx = ctx;
114 fenum.username = username;
115 fenum.ctr3 = *ctr3;
117 if (connections_traverse(pipe_enum_fn, &fenum) == -1) {
118 DEBUG(0,("net_enum_pipes: traverse of connections.tdb "
119 "failed\n"));
120 return WERR_NOMEM;
123 *ctr3 = fenum.ctr3;
125 return WERR_OK;
128 /*******************************************************************
129 ********************************************************************/
131 static void enum_file_fn( const struct share_mode_entry *e,
132 const char *sharepath, const char *fname,
133 void *private_data )
135 struct file_enum_count *fenum =
136 (struct file_enum_count *)private_data;
138 struct srvsvc_NetFileInfo3 *f;
139 int i = fenum->ctr3->count;
140 files_struct fsp;
141 struct byte_range_lock *brl;
142 int num_locks = 0;
143 char *fullpath = NULL;
144 uint32 permissions;
145 const char *username;
147 /* If the pid was not found delete the entry from connections.tdb */
149 if ( !process_exists(e->pid) ) {
150 return;
153 username = uidtoname(e->uid);
155 if ((fenum->username != NULL)
156 && !strequal(username, fenum->username)) {
157 return;
160 f = TALLOC_REALLOC_ARRAY(fenum->ctx, fenum->ctr3->array,
161 struct srvsvc_NetFileInfo3, i+1);
162 if ( !f ) {
163 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
164 return;
166 fenum->ctr3->array = f;
168 /* need to count the number of locks on a file */
170 ZERO_STRUCT( fsp );
171 fsp.file_id = e->id;
173 if ( (brl = brl_get_locks(talloc_tos(), &fsp)) != NULL ) {
174 num_locks = brl->num_locks;
175 TALLOC_FREE(brl);
178 if ( strcmp( fname, "." ) == 0 ) {
179 fullpath = talloc_asprintf(fenum->ctx, "C:%s", sharepath );
180 } else {
181 fullpath = talloc_asprintf(fenum->ctx, "C:%s/%s",
182 sharepath, fname );
184 if (!fullpath) {
185 return;
187 string_replace( fullpath, '/', '\\' );
189 /* mask out create (what ever that is) */
190 permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
192 /* now fill in the srvsvc_NetFileInfo3 struct */
193 init_srvsvc_NetFileInfo3(&fenum->ctr3->array[i],
194 (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id),
195 permissions,
196 num_locks,
197 fullpath,
198 username);
199 fenum->ctr3->count++;
202 /*******************************************************************
203 ********************************************************************/
205 static WERROR net_enum_files(TALLOC_CTX *ctx,
206 const char *username,
207 struct srvsvc_NetFileCtr3 **ctr3,
208 uint32_t resume)
210 struct file_enum_count f_enum_cnt;
212 f_enum_cnt.ctx = ctx;
213 f_enum_cnt.username = username;
214 f_enum_cnt.ctr3 = *ctr3;
216 share_mode_forall( enum_file_fn, (void *)&f_enum_cnt );
218 *ctr3 = f_enum_cnt.ctr3;
220 return WERR_OK;
223 /*******************************************************************
224 Utility function to get the 'type' of a share from an snum.
225 ********************************************************************/
226 static uint32 get_share_type(int snum)
228 /* work out the share type */
229 uint32 type = STYPE_DISKTREE;
231 if (lp_print_ok(snum))
232 type = STYPE_PRINTQ;
233 if (strequal(lp_fstype(snum), "IPC"))
234 type = STYPE_IPC;
235 if (lp_administrative_share(snum))
236 type |= STYPE_HIDDEN;
238 return type;
241 /*******************************************************************
242 Fill in a share info level 0 structure.
243 ********************************************************************/
245 static void init_srv_share_info_0(pipes_struct *p, struct srvsvc_NetShareInfo0 *r, int snum)
247 const char *net_name = lp_servicename(snum);
249 init_srvsvc_NetShareInfo0(r, net_name);
252 /*******************************************************************
253 Fill in a share info level 1 structure.
254 ********************************************************************/
256 static void init_srv_share_info_1(pipes_struct *p, struct srvsvc_NetShareInfo1 *r, int snum)
258 char *net_name = lp_servicename(snum);
259 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
261 if (remark) {
262 remark = talloc_sub_advanced(
263 p->mem_ctx, lp_servicename(snum),
264 get_current_username(), lp_pathname(snum),
265 p->server_info->utok.uid, get_current_username(),
266 "", remark);
269 init_srvsvc_NetShareInfo1(r, net_name,
270 get_share_type(snum),
271 remark ? remark : "");
274 /*******************************************************************
275 Fill in a share info level 2 structure.
276 ********************************************************************/
278 static void init_srv_share_info_2(pipes_struct *p, struct srvsvc_NetShareInfo2 *r, int snum)
280 char *remark = NULL;
281 char *path = NULL;
282 int max_connections = lp_max_connections(snum);
283 uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
284 int count = 0;
285 char *net_name = lp_servicename(snum);
287 remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
288 if (remark) {
289 remark = talloc_sub_advanced(
290 p->mem_ctx, lp_servicename(snum),
291 get_current_username(), lp_pathname(snum),
292 p->server_info->utok.uid, get_current_username(),
293 "", remark);
295 path = talloc_asprintf(p->mem_ctx,
296 "C:%s", lp_pathname(snum));
298 if (path) {
300 * Change / to \\ so that win2k will see it as a valid path.
301 * This was added to enable use of browsing in win2k add
302 * share dialog.
305 string_replace(path, '/', '\\');
308 count = count_current_connections(net_name, false);
310 init_srvsvc_NetShareInfo2(r, net_name,
311 get_share_type(snum),
312 remark ? remark : "",
314 max_uses,
315 count,
316 path ? path : "",
317 "");
320 /*******************************************************************
321 Map any generic bits to file specific bits.
322 ********************************************************************/
324 static void map_generic_share_sd_bits(SEC_DESC *psd)
326 int i;
327 SEC_ACL *ps_dacl = NULL;
329 if (!psd)
330 return;
332 ps_dacl = psd->dacl;
333 if (!ps_dacl)
334 return;
336 for (i = 0; i < ps_dacl->num_aces; i++) {
337 SEC_ACE *psa = &ps_dacl->aces[i];
338 uint32 orig_mask = psa->access_mask;
340 se_map_generic(&psa->access_mask, &file_generic_mapping);
341 psa->access_mask |= orig_mask;
345 /*******************************************************************
346 Fill in a share info level 501 structure.
347 ********************************************************************/
349 static void init_srv_share_info_501(pipes_struct *p, struct srvsvc_NetShareInfo501 *r, int snum)
351 const char *net_name = lp_servicename(snum);
352 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
354 if (remark) {
355 remark = talloc_sub_advanced(
356 p->mem_ctx, lp_servicename(snum),
357 get_current_username(), lp_pathname(snum),
358 p->server_info->utok.uid, get_current_username(),
359 "", remark);
362 init_srvsvc_NetShareInfo501(r, net_name,
363 get_share_type(snum),
364 remark ? remark : "",
365 (lp_csc_policy(snum) << 4));
368 /*******************************************************************
369 Fill in a share info level 502 structure.
370 ********************************************************************/
372 static void init_srv_share_info_502(pipes_struct *p, struct srvsvc_NetShareInfo502 *r, int snum)
374 const char *net_name = lp_servicename(snum);
375 char *path = NULL;
376 SEC_DESC *sd = NULL;
377 struct sec_desc_buf *sd_buf = NULL;
378 size_t sd_size = 0;
379 TALLOC_CTX *ctx = p->mem_ctx;
380 char *remark = talloc_strdup(ctx, lp_comment(snum));;
382 if (remark) {
383 remark = talloc_sub_advanced(
384 p->mem_ctx, lp_servicename(snum),
385 get_current_username(), lp_pathname(snum),
386 p->server_info->utok.uid, get_current_username(),
387 "", remark);
389 path = talloc_asprintf(ctx, "C:%s", lp_pathname(snum));
390 if (path) {
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(snum), &sd_size);
400 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
402 init_srvsvc_NetShareInfo502(r, net_name,
403 get_share_type(snum),
404 remark ? remark : "",
406 (uint32_t)-1,
408 path ? path : "",
410 sd_buf);
413 /***************************************************************************
414 Fill in a share info level 1004 structure.
415 ***************************************************************************/
417 static void init_srv_share_info_1004(pipes_struct *p, struct srvsvc_NetShareInfo1004 *r, int snum)
419 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
421 if (remark) {
422 remark = talloc_sub_advanced(
423 p->mem_ctx, lp_servicename(snum),
424 get_current_username(), lp_pathname(snum),
425 p->server_info->utok.uid, get_current_username(),
426 "", remark);
429 init_srvsvc_NetShareInfo1004(r, remark ? remark : "");
432 /***************************************************************************
433 Fill in a share info level 1005 structure.
434 ***************************************************************************/
436 static void init_srv_share_info_1005(pipes_struct *p, struct srvsvc_NetShareInfo1005 *r, int snum)
438 uint32_t dfs_flags = 0;
440 if (lp_host_msdfs() && lp_msdfs_root(snum)) {
441 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
444 dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
446 init_srvsvc_NetShareInfo1005(r, dfs_flags);
449 /***************************************************************************
450 Fill in a share info level 1006 structure.
451 ***************************************************************************/
453 static void init_srv_share_info_1006(pipes_struct *p, struct srvsvc_NetShareInfo1006 *r, int snum)
455 init_srvsvc_NetShareInfo1006(r, (uint32_t)-1);
458 /***************************************************************************
459 Fill in a share info level 1007 structure.
460 ***************************************************************************/
462 static void init_srv_share_info_1007(pipes_struct *p, struct srvsvc_NetShareInfo1007 *r, int snum)
464 uint32 flags = 0;
466 init_srvsvc_NetShareInfo1007(r, flags, "");
469 /*******************************************************************
470 Fill in a share info level 1501 structure.
471 ********************************************************************/
473 static void init_srv_share_info_1501(pipes_struct *p, struct sec_desc_buf *r, int snum)
475 SEC_DESC *sd;
476 size_t sd_size;
477 TALLOC_CTX *ctx = p->mem_ctx;
479 sd = get_share_security(ctx, lp_servicename(snum), &sd_size);
481 r = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
484 /*******************************************************************
485 True if it ends in '$'.
486 ********************************************************************/
488 static bool is_hidden_share(int snum)
490 const char *net_name = lp_servicename(snum);
492 return (net_name[strlen(net_name) - 1] == '$') ? True : False;
495 /*******************************************************************
496 Verify user is allowed to view share, access based enumeration
497 ********************************************************************/
498 static bool is_enumeration_allowed(pipes_struct *p,
499 int snum)
501 if (!lp_access_based_share_enum(snum))
502 return true;
504 return share_access_check(p->server_info->ptok, lp_servicename(snum),
505 FILE_READ_DATA);
508 /*******************************************************************
509 Fill in a share info structure.
510 ********************************************************************/
512 static WERROR init_srv_share_info_ctr(pipes_struct *p,
513 struct srvsvc_NetShareInfoCtr *info_ctr,
514 uint32_t *resume_handle_p,
515 uint32_t *total_entries,
516 bool all_shares)
518 int num_entries = 0;
519 int alloc_entries = 0;
520 int num_services = 0;
521 int snum;
522 TALLOC_CTX *ctx = p->mem_ctx;
523 int i = 0;
524 int valid_share_count = 0;
525 bool *allowed = 0;
526 union srvsvc_NetShareCtr ctr;
527 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
529 DEBUG(5,("init_srv_share_info_ctr\n"));
531 /* Ensure all the usershares are loaded. */
532 become_root();
533 load_usershare_shares();
534 load_registry_shares();
535 num_services = lp_numservices();
536 unbecome_root();
538 allowed = TALLOC_ZERO_ARRAY(ctx, bool, num_services);
539 W_ERROR_HAVE_NO_MEMORY(allowed);
541 /* Count the number of entries. */
542 for (snum = 0; snum < num_services; snum++) {
543 if (lp_browseable(snum) && lp_snum_ok(snum) &&
544 is_enumeration_allowed(p, snum) &&
545 (all_shares || !is_hidden_share(snum)) ) {
546 DEBUG(10, ("counting service %s\n", lp_servicename(snum)));
547 allowed[snum] = true;
548 num_entries++;
549 } else {
550 DEBUG(10, ("NOT counting service %s\n", lp_servicename(snum)));
554 if (!num_entries || (resume_handle >= num_entries)) {
555 return WERR_OK;
558 /* Calculate alloc entries. */
559 alloc_entries = num_entries - resume_handle;
560 switch (info_ctr->level) {
561 case 0:
562 ctr.ctr0 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr0);
563 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
565 ctr.ctr0->count = alloc_entries;
566 ctr.ctr0->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
567 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
569 for (snum = 0; snum < num_services; snum++) {
570 if (allowed[snum] &&
571 (resume_handle <= (i + valid_share_count++)) ) {
572 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
576 break;
578 case 1:
579 ctr.ctr1 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1);
580 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
582 ctr.ctr1->count = alloc_entries;
583 ctr.ctr1->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
584 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
586 for (snum = 0; snum < num_services; snum++) {
587 if (allowed[snum] &&
588 (resume_handle <= (i + valid_share_count++)) ) {
589 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
593 break;
595 case 2:
596 ctr.ctr2 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr2);
597 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
599 ctr.ctr2->count = alloc_entries;
600 ctr.ctr2->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
601 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
603 for (snum = 0; snum < num_services; snum++) {
604 if (allowed[snum] &&
605 (resume_handle <= (i + valid_share_count++)) ) {
606 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
610 break;
612 case 501:
613 ctr.ctr501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr501);
614 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
616 ctr.ctr501->count = alloc_entries;
617 ctr.ctr501->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
618 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
620 for (snum = 0; snum < num_services; snum++) {
621 if (allowed[snum] &&
622 (resume_handle <= (i + valid_share_count++)) ) {
623 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
627 break;
629 case 502:
630 ctr.ctr502 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr502);
631 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
633 ctr.ctr502->count = alloc_entries;
634 ctr.ctr502->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
635 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
637 for (snum = 0; snum < num_services; snum++) {
638 if (allowed[snum] &&
639 (resume_handle <= (i + valid_share_count++)) ) {
640 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
644 break;
646 case 1004:
647 ctr.ctr1004 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1004);
648 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
650 ctr.ctr1004->count = alloc_entries;
651 ctr.ctr1004->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
652 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
654 for (snum = 0; snum < num_services; snum++) {
655 if (allowed[snum] &&
656 (resume_handle <= (i + valid_share_count++)) ) {
657 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
661 break;
663 case 1005:
664 ctr.ctr1005 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1005);
665 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
667 ctr.ctr1005->count = alloc_entries;
668 ctr.ctr1005->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
669 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
671 for (snum = 0; snum < num_services; snum++) {
672 if (allowed[snum] &&
673 (resume_handle <= (i + valid_share_count++)) ) {
674 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
678 break;
680 case 1006:
681 ctr.ctr1006 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1006);
682 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
684 ctr.ctr1006->count = alloc_entries;
685 ctr.ctr1006->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
686 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
688 for (snum = 0; snum < num_services; snum++) {
689 if (allowed[snum] &&
690 (resume_handle <= (i + valid_share_count++)) ) {
691 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
695 break;
697 case 1007:
698 ctr.ctr1007 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1007);
699 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
701 ctr.ctr1007->count = alloc_entries;
702 ctr.ctr1007->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
703 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
705 for (snum = 0; snum < num_services; snum++) {
706 if (allowed[snum] &&
707 (resume_handle <= (i + valid_share_count++)) ) {
708 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
712 break;
714 case 1501:
715 ctr.ctr1501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1501);
716 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
718 ctr.ctr1501->count = alloc_entries;
719 ctr.ctr1501->array = TALLOC_ZERO_ARRAY(ctx, struct sec_desc_buf, alloc_entries);
720 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
722 for (snum = 0; snum < num_services; snum++) {
723 if (allowed[snum] &&
724 (resume_handle <= (i + valid_share_count++)) ) {
725 init_srv_share_info_1501(p, &ctr.ctr1501->array[i++], snum);
729 break;
731 default:
732 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
733 info_ctr->level));
734 return WERR_UNKNOWN_LEVEL;
737 *total_entries = alloc_entries;
738 if (resume_handle_p) {
739 if (all_shares) {
740 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
741 } else {
742 *resume_handle_p = num_entries;
746 info_ctr->ctr = ctr;
748 return WERR_OK;
751 /*******************************************************************
752 fill in a sess info level 0 structure.
753 ********************************************************************/
755 static WERROR init_srv_sess_info_0(pipes_struct *p,
756 struct srvsvc_NetSessCtr0 *ctr0,
757 uint32_t *resume_handle_p,
758 uint32_t *total_entries)
760 struct sessionid *session_list;
761 uint32_t num_entries = 0;
762 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
763 *total_entries = list_sessions(p->mem_ctx, &session_list);
765 DEBUG(5,("init_srv_sess_info_0\n"));
767 if (ctr0 == NULL) {
768 if (resume_handle_p) {
769 *resume_handle_p = 0;
771 return WERR_OK;
774 for (; resume_handle < *total_entries; resume_handle++) {
776 ctr0->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
777 ctr0->array,
778 struct srvsvc_NetSessInfo0,
779 num_entries+1);
780 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
782 init_srvsvc_NetSessInfo0(&ctr0->array[num_entries],
783 session_list[resume_handle].remote_machine);
784 num_entries++;
787 ctr0->count = num_entries;
789 if (resume_handle_p) {
790 if (*resume_handle_p >= *total_entries) {
791 *resume_handle_p = 0;
792 } else {
793 *resume_handle_p = resume_handle;
797 return WERR_OK;
800 /*******************************************************************
801 ********************************************************************/
803 static void sess_file_fn( const struct share_mode_entry *e,
804 const char *sharepath, const char *fname,
805 void *data )
807 struct sess_file_count *sess = (struct sess_file_count *)data;
809 if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
810 sess->count++;
813 return;
816 /*******************************************************************
817 ********************************************************************/
819 static int net_count_files( uid_t uid, struct server_id pid )
821 struct sess_file_count s_file_cnt;
823 s_file_cnt.count = 0;
824 s_file_cnt.uid = uid;
825 s_file_cnt.pid = pid;
827 share_mode_forall( sess_file_fn, &s_file_cnt );
829 return s_file_cnt.count;
832 /*******************************************************************
833 fill in a sess info level 1 structure.
834 ********************************************************************/
836 static WERROR init_srv_sess_info_1(pipes_struct *p,
837 struct srvsvc_NetSessCtr1 *ctr1,
838 uint32_t *resume_handle_p,
839 uint32_t *total_entries)
841 struct sessionid *session_list;
842 uint32_t num_entries = 0;
843 time_t now = time(NULL);
844 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
846 ZERO_STRUCTP(ctr1);
848 if (ctr1 == NULL) {
849 if (resume_handle_p) {
850 *resume_handle_p = 0;
852 return WERR_OK;
855 *total_entries = list_sessions(p->mem_ctx, &session_list);
857 for (; resume_handle < *total_entries; resume_handle++) {
858 uint32 num_files;
859 uint32 connect_time;
860 struct passwd *pw = sys_getpwnam(session_list[resume_handle].username);
861 bool guest;
863 if ( !pw ) {
864 DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
865 session_list[resume_handle].username));
866 continue;
869 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
870 num_files = net_count_files(pw->pw_uid, session_list[resume_handle].pid);
871 guest = strequal( session_list[resume_handle].username, lp_guestaccount() );
873 ctr1->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
874 ctr1->array,
875 struct srvsvc_NetSessInfo1,
876 num_entries+1);
877 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
879 init_srvsvc_NetSessInfo1(&ctr1->array[num_entries],
880 session_list[resume_handle].remote_machine,
881 session_list[resume_handle].username,
882 num_files,
883 connect_time,
885 guest);
886 num_entries++;
889 ctr1->count = num_entries;
891 if (resume_handle_p) {
892 if (*resume_handle_p >= *total_entries) {
893 *resume_handle_p = 0;
894 } else {
895 *resume_handle_p = resume_handle;
899 return WERR_OK;
902 /*******************************************************************
903 fill in a conn info level 0 structure.
904 ********************************************************************/
906 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
907 uint32_t *resume_handle_p,
908 uint32_t *total_entries)
910 uint32_t num_entries = 0;
911 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
913 DEBUG(5,("init_srv_conn_info_0\n"));
915 if (ctr0 == NULL) {
916 if (resume_handle_p) {
917 *resume_handle_p = 0;
919 return WERR_OK;
922 *total_entries = 1;
924 ZERO_STRUCTP(ctr0);
926 for (; resume_handle < *total_entries; resume_handle++) {
928 ctr0->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
929 ctr0->array,
930 struct srvsvc_NetConnInfo0,
931 num_entries+1);
932 if (!ctr0->array) {
933 return WERR_NOMEM;
936 init_srvsvc_NetConnInfo0(&ctr0->array[num_entries],
937 (*total_entries));
939 /* move on to creating next connection */
940 num_entries++;
943 ctr0->count = num_entries;
944 *total_entries = num_entries;
946 if (resume_handle_p) {
947 if (*resume_handle_p >= *total_entries) {
948 *resume_handle_p = 0;
949 } else {
950 *resume_handle_p = resume_handle;
954 return WERR_OK;
957 /*******************************************************************
958 fill in a conn info level 1 structure.
959 ********************************************************************/
961 static WERROR init_srv_conn_info_1(struct srvsvc_NetConnCtr1 *ctr1,
962 uint32_t *resume_handle_p,
963 uint32_t *total_entries)
965 uint32_t num_entries = 0;
966 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
968 DEBUG(5,("init_srv_conn_info_1\n"));
970 if (ctr1 == NULL) {
971 if (resume_handle_p) {
972 *resume_handle_p = 0;
974 return WERR_OK;
977 *total_entries = 1;
979 ZERO_STRUCTP(ctr1);
981 for (; resume_handle < *total_entries; resume_handle++) {
983 ctr1->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
984 ctr1->array,
985 struct srvsvc_NetConnInfo1,
986 num_entries+1);
987 if (!ctr1->array) {
988 return WERR_NOMEM;
991 init_srvsvc_NetConnInfo1(&ctr1->array[num_entries],
992 (*total_entries),
993 0x3,
997 "dummy_user",
998 "IPC$");
1000 /* move on to creating next connection */
1001 num_entries++;
1004 ctr1->count = num_entries;
1005 *total_entries = num_entries;
1007 if (resume_handle_p) {
1008 if (*resume_handle_p >= *total_entries) {
1009 *resume_handle_p = 0;
1010 } else {
1011 *resume_handle_p = resume_handle;
1015 return WERR_OK;
1018 /*******************************************************************
1019 _srvsvc_NetFileEnum
1020 *******************************************************************/
1022 WERROR _srvsvc_NetFileEnum(pipes_struct *p,
1023 struct srvsvc_NetFileEnum *r)
1025 TALLOC_CTX *ctx = NULL;
1026 struct srvsvc_NetFileCtr3 *ctr3;
1027 uint32_t resume_hnd = 0;
1028 WERROR werr;
1030 switch (r->in.info_ctr->level) {
1031 case 3:
1032 break;
1033 default:
1034 return WERR_UNKNOWN_LEVEL;
1037 ctx = talloc_tos();
1038 ctr3 = r->in.info_ctr->ctr.ctr3;
1039 if (!ctr3) {
1040 werr = WERR_INVALID_PARAM;
1041 goto done;
1044 /* TODO -- Windows enumerates
1045 (b) active pipes
1046 (c) open directories and files */
1048 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1049 if (!W_ERROR_IS_OK(werr)) {
1050 goto done;
1053 werr = net_enum_pipes(ctx, r->in.user, &ctr3, resume_hnd);
1054 if (!W_ERROR_IS_OK(werr)) {
1055 goto done;
1058 *r->out.totalentries = ctr3->count;
1059 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1060 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1062 werr = WERR_OK;
1064 done:
1065 return werr;
1068 /*******************************************************************
1069 _srvsvc_NetSrvGetInfo
1070 ********************************************************************/
1072 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p,
1073 struct srvsvc_NetSrvGetInfo *r)
1075 WERROR status = WERR_OK;
1077 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1079 if (!pipe_access_check(p)) {
1080 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1081 return WERR_ACCESS_DENIED;
1084 switch (r->in.level) {
1086 /* Technically level 102 should only be available to
1087 Administrators but there isn't anything super-secret
1088 here, as most of it is made up. */
1090 case 102: {
1091 struct srvsvc_NetSrvInfo102 *info102;
1093 info102 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1094 if (!info102) {
1095 return WERR_NOMEM;
1098 init_srvsvc_NetSrvInfo102(info102,
1099 PLATFORM_ID_NT,
1100 global_myname(),
1101 lp_major_announce_version(),
1102 lp_minor_announce_version(),
1103 lp_default_server_announce(),
1104 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
1105 0xffffffff, /* users */
1106 0xf, /* disc */
1107 0, /* hidden */
1108 240, /* announce */
1109 3000, /* announce delta */
1110 100000, /* licenses */
1111 "c:\\"); /* user path */
1112 r->out.info->info102 = info102;
1113 break;
1115 case 101: {
1116 struct srvsvc_NetSrvInfo101 *info101;
1118 info101 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1119 if (!info101) {
1120 return WERR_NOMEM;
1123 init_srvsvc_NetSrvInfo101(info101,
1124 PLATFORM_ID_NT,
1125 global_myname(),
1126 lp_major_announce_version(),
1127 lp_minor_announce_version(),
1128 lp_default_server_announce(),
1129 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1130 r->out.info->info101 = info101;
1131 break;
1133 case 100: {
1134 struct srvsvc_NetSrvInfo100 *info100;
1136 info100 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1137 if (!info100) {
1138 return WERR_NOMEM;
1141 init_srvsvc_NetSrvInfo100(info100,
1142 PLATFORM_ID_NT,
1143 global_myname());
1144 r->out.info->info100 = info100;
1146 break;
1148 default:
1149 status = WERR_UNKNOWN_LEVEL;
1150 break;
1153 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1155 return status;
1158 /*******************************************************************
1159 _srvsvc_NetSrvSetInfo
1160 ********************************************************************/
1162 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p,
1163 struct srvsvc_NetSrvSetInfo *r)
1165 WERROR status = WERR_OK;
1167 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1169 /* Set up the net server set info structure. */
1171 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1173 return status;
1176 /*******************************************************************
1177 _srvsvc_NetConnEnum
1178 ********************************************************************/
1180 WERROR _srvsvc_NetConnEnum(pipes_struct *p,
1181 struct srvsvc_NetConnEnum *r)
1183 WERROR werr;
1185 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1187 switch (r->in.info_ctr->level) {
1188 case 0:
1189 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1190 r->in.resume_handle,
1191 r->out.totalentries);
1192 break;
1193 case 1:
1194 werr = init_srv_conn_info_1(r->in.info_ctr->ctr.ctr1,
1195 r->in.resume_handle,
1196 r->out.totalentries);
1197 break;
1198 default:
1199 return WERR_UNKNOWN_LEVEL;
1202 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1204 return werr;
1207 /*******************************************************************
1208 _srvsvc_NetSessEnum
1209 ********************************************************************/
1211 WERROR _srvsvc_NetSessEnum(pipes_struct *p,
1212 struct srvsvc_NetSessEnum *r)
1214 WERROR werr;
1216 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1218 switch (r->in.info_ctr->level) {
1219 case 0:
1220 werr = init_srv_sess_info_0(p,
1221 r->in.info_ctr->ctr.ctr0,
1222 r->in.resume_handle,
1223 r->out.totalentries);
1224 break;
1225 case 1:
1226 werr = init_srv_sess_info_1(p,
1227 r->in.info_ctr->ctr.ctr1,
1228 r->in.resume_handle,
1229 r->out.totalentries);
1230 break;
1231 default:
1232 return WERR_UNKNOWN_LEVEL;
1235 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1237 return werr;
1240 /*******************************************************************
1241 _srvsvc_NetSessDel
1242 ********************************************************************/
1244 WERROR _srvsvc_NetSessDel(pipes_struct *p,
1245 struct srvsvc_NetSessDel *r)
1247 struct sessionid *session_list;
1248 int num_sessions, snum;
1249 const char *username;
1250 const char *machine;
1251 bool not_root = False;
1252 WERROR werr;
1254 username = r->in.user;
1255 machine = r->in.client;
1257 /* strip leading backslashes if any */
1258 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1259 machine += 2;
1262 num_sessions = list_sessions(p->mem_ctx, &session_list);
1264 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1266 werr = WERR_ACCESS_DENIED;
1268 /* fail out now if you are not root or not a domain admin */
1270 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1271 ( ! nt_token_check_domain_rid(p->server_info->ptok,
1272 DOMAIN_GROUP_RID_ADMINS))) {
1274 goto done;
1277 for (snum = 0; snum < num_sessions; snum++) {
1279 if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
1280 strequal(session_list[snum].remote_machine, machine)) {
1282 NTSTATUS ntstat;
1284 if (p->server_info->utok.uid != sec_initial_uid()) {
1285 not_root = True;
1286 become_root();
1289 ntstat = messaging_send(smbd_messaging_context(),
1290 session_list[snum].pid,
1291 MSG_SHUTDOWN, &data_blob_null);
1293 if (NT_STATUS_IS_OK(ntstat))
1294 werr = WERR_OK;
1296 if (not_root)
1297 unbecome_root();
1301 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1303 done:
1305 return werr;
1308 /*******************************************************************
1309 _srvsvc_NetShareEnumAll
1310 ********************************************************************/
1312 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p,
1313 struct srvsvc_NetShareEnumAll *r)
1315 WERROR werr;
1317 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1319 if (!pipe_access_check(p)) {
1320 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1321 return WERR_ACCESS_DENIED;
1324 /* Create the list of shares for the response. */
1325 werr = init_srv_share_info_ctr(p,
1326 r->in.info_ctr,
1327 r->in.resume_handle,
1328 r->out.totalentries,
1329 true);
1331 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1333 return werr;
1336 /*******************************************************************
1337 _srvsvc_NetShareEnum
1338 ********************************************************************/
1340 WERROR _srvsvc_NetShareEnum(pipes_struct *p,
1341 struct srvsvc_NetShareEnum *r)
1343 WERROR werr;
1345 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1347 if (!pipe_access_check(p)) {
1348 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1349 return WERR_ACCESS_DENIED;
1352 /* Create the list of shares for the response. */
1353 werr = init_srv_share_info_ctr(p,
1354 r->in.info_ctr,
1355 r->in.resume_handle,
1356 r->out.totalentries,
1357 false);
1359 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1361 return werr;
1364 /*******************************************************************
1365 _srvsvc_NetShareGetInfo
1366 ********************************************************************/
1368 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p,
1369 struct srvsvc_NetShareGetInfo *r)
1371 WERROR status = WERR_OK;
1372 fstring share_name;
1373 int snum;
1374 union srvsvc_NetShareInfo *info = r->out.info;
1376 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1378 fstrcpy(share_name, r->in.share_name);
1380 snum = find_service(share_name);
1381 if (snum < 0) {
1382 return WERR_INVALID_NAME;
1385 switch (r->in.level) {
1386 case 0:
1387 info->info0 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo0);
1388 W_ERROR_HAVE_NO_MEMORY(info->info0);
1389 init_srv_share_info_0(p, info->info0, snum);
1390 break;
1391 case 1:
1392 info->info1 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1);
1393 W_ERROR_HAVE_NO_MEMORY(info->info1);
1394 init_srv_share_info_1(p, info->info1, snum);
1395 break;
1396 case 2:
1397 info->info2 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo2);
1398 W_ERROR_HAVE_NO_MEMORY(info->info2);
1399 init_srv_share_info_2(p, info->info2, snum);
1400 break;
1401 case 501:
1402 info->info501 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo501);
1403 W_ERROR_HAVE_NO_MEMORY(info->info501);
1404 init_srv_share_info_501(p, info->info501, snum);
1405 break;
1406 case 502:
1407 info->info502 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo502);
1408 W_ERROR_HAVE_NO_MEMORY(info->info502);
1409 init_srv_share_info_502(p, info->info502, snum);
1410 break;
1411 case 1004:
1412 info->info1004 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1413 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1414 init_srv_share_info_1004(p, info->info1004, snum);
1415 break;
1416 case 1005:
1417 info->info1005 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1418 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1419 init_srv_share_info_1005(p, info->info1005, snum);
1420 break;
1421 case 1006:
1422 info->info1006 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1423 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1424 init_srv_share_info_1006(p, info->info1006, snum);
1425 break;
1426 case 1007:
1427 info->info1007 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1428 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1429 init_srv_share_info_1007(p, info->info1007, snum);
1430 break;
1431 case 1501:
1432 init_srv_share_info_1501(p, info->info1501, snum);
1433 break;
1434 default:
1435 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1436 r->in.level));
1437 status = WERR_UNKNOWN_LEVEL;
1438 break;
1441 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1443 return status;
1446 /*******************************************************************
1447 Check a given DOS pathname is valid for a share.
1448 ********************************************************************/
1450 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
1452 char *ptr = NULL;
1454 if (!dos_pathname) {
1455 return NULL;
1458 ptr = talloc_strdup(ctx, dos_pathname);
1459 if (!ptr) {
1460 return NULL;
1462 /* Convert any '\' paths to '/' */
1463 unix_format(ptr);
1464 ptr = unix_clean_name(ctx, ptr);
1465 if (!ptr) {
1466 return NULL;
1469 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1470 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
1471 ptr += 2;
1473 /* Only absolute paths allowed. */
1474 if (*ptr != '/')
1475 return NULL;
1477 return ptr;
1480 /*******************************************************************
1481 _srvsvc_NetShareSetInfo. Modify share details.
1482 ********************************************************************/
1484 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p,
1485 struct srvsvc_NetShareSetInfo *r)
1487 char *command = NULL;
1488 char *share_name = NULL;
1489 char *comment = NULL;
1490 const char *pathname = NULL;
1491 int type;
1492 int snum;
1493 int ret;
1494 char *path = NULL;
1495 SEC_DESC *psd = NULL;
1496 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1497 bool is_disk_op = False;
1498 int max_connections = 0;
1499 TALLOC_CTX *ctx = p->mem_ctx;
1500 union srvsvc_NetShareInfo *info = r->in.info;
1502 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1504 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1505 if (!share_name) {
1506 return WERR_NOMEM;
1509 if (r->out.parm_error) {
1510 *r->out.parm_error = 0;
1513 if ( strequal(share_name,"IPC$")
1514 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1515 || strequal(share_name,"global") )
1517 return WERR_ACCESS_DENIED;
1520 snum = find_service(share_name);
1522 /* Does this share exist ? */
1523 if (snum < 0)
1524 return WERR_NET_NAME_NOT_FOUND;
1526 /* No change to printer shares. */
1527 if (lp_print_ok(snum))
1528 return WERR_ACCESS_DENIED;
1530 is_disk_op = user_has_privileges( p->server_info->ptok, &se_diskop );
1532 /* fail out now if you are not root and not a disk op */
1534 if ( p->server_info->utok.uid != sec_initial_uid() && !is_disk_op )
1535 return WERR_ACCESS_DENIED;
1537 switch (r->in.level) {
1538 case 1:
1539 pathname = talloc_strdup(ctx, lp_pathname(snum));
1540 comment = talloc_strdup(ctx, info->info1->comment);
1541 type = info->info1->type;
1542 psd = NULL;
1543 break;
1544 case 2:
1545 comment = talloc_strdup(ctx, info->info2->comment);
1546 pathname = info->info2->path;
1547 type = info->info2->type;
1548 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1549 0 : info->info2->max_users;
1550 psd = NULL;
1551 break;
1552 #if 0
1553 /* not supported on set but here for completeness */
1554 case 501:
1555 comment = talloc_strdup(ctx, info->info501->comment);
1556 type = info->info501->type;
1557 psd = NULL;
1558 break;
1559 #endif
1560 case 502:
1561 comment = talloc_strdup(ctx, info->info502->comment);
1562 pathname = info->info502->path;
1563 type = info->info502->type;
1564 psd = info->info502->sd_buf.sd;
1565 map_generic_share_sd_bits(psd);
1566 break;
1567 case 1004:
1568 pathname = talloc_strdup(ctx, lp_pathname(snum));
1569 comment = talloc_strdup(ctx, info->info1004->comment);
1570 type = STYPE_DISKTREE;
1571 break;
1572 case 1005:
1573 /* XP re-sets the csc policy even if it wasn't changed by the
1574 user, so we must compare it to see if it's what is set in
1575 smb.conf, so that we can contine other ops like setting
1576 ACLs on a share */
1577 if (((info->info1005->dfs_flags &
1578 SHARE_1005_CSC_POLICY_MASK) >>
1579 SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1580 return WERR_OK;
1581 else {
1582 DEBUG(3, ("_srvsvc_NetShareSetInfo: client is trying to change csc policy from the network; must be done with smb.conf\n"));
1583 return WERR_ACCESS_DENIED;
1585 case 1006:
1586 case 1007:
1587 return WERR_ACCESS_DENIED;
1588 case 1501:
1589 pathname = talloc_strdup(ctx, lp_pathname(snum));
1590 comment = talloc_strdup(ctx, lp_comment(snum));
1591 psd = info->info1501->sd;
1592 map_generic_share_sd_bits(psd);
1593 type = STYPE_DISKTREE;
1594 break;
1595 default:
1596 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1597 r->in.level));
1598 return WERR_UNKNOWN_LEVEL;
1601 /* We can only modify disk shares. */
1602 if (type != STYPE_DISKTREE)
1603 return WERR_ACCESS_DENIED;
1605 if (comment == NULL) {
1606 return WERR_NOMEM;
1609 /* Check if the pathname is valid. */
1610 if (!(path = valid_share_pathname(p->mem_ctx, pathname )))
1611 return WERR_OBJECT_PATH_INVALID;
1613 /* Ensure share name, pathname and comment don't contain '"' characters. */
1614 string_replace(share_name, '"', ' ');
1615 string_replace(path, '"', ' ');
1616 string_replace(comment, '"', ' ');
1618 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1619 lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1621 /* Only call modify function if something changed. */
1623 if (strcmp(path, lp_pathname(snum)) || strcmp(comment, lp_comment(snum))
1624 || (lp_max_connections(snum) != max_connections)) {
1625 if (!lp_change_share_cmd() || !*lp_change_share_cmd()) {
1626 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1627 return WERR_ACCESS_DENIED;
1630 command = talloc_asprintf(p->mem_ctx,
1631 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1632 lp_change_share_cmd(),
1633 get_dyn_CONFIGFILE(),
1634 share_name,
1635 path,
1636 comment ? comment : "",
1637 max_connections);
1638 if (!command) {
1639 return WERR_NOMEM;
1642 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1644 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1646 if (is_disk_op)
1647 become_root();
1649 if ( (ret = smbrun(command, NULL)) == 0 ) {
1650 /* Tell everyone we updated smb.conf. */
1651 message_send_all(smbd_messaging_context(),
1652 MSG_SMB_CONF_UPDATED, NULL, 0,
1653 NULL);
1656 if ( is_disk_op )
1657 unbecome_root();
1659 /********* END SeDiskOperatorPrivilege BLOCK *********/
1661 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1662 command, ret ));
1664 TALLOC_FREE(command);
1666 if ( ret != 0 )
1667 return WERR_ACCESS_DENIED;
1668 } else {
1669 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1670 share_name ));
1673 /* Replace SD if changed. */
1674 if (psd) {
1675 SEC_DESC *old_sd;
1676 size_t sd_size;
1678 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum), &sd_size);
1680 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1681 if (!set_share_security(share_name, psd))
1682 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1683 share_name ));
1687 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1689 return WERR_OK;
1692 /*******************************************************************
1693 _srvsvc_NetShareAdd.
1694 Call 'add_share_command "sharename" "pathname"
1695 "comment" "max connections = "
1696 ********************************************************************/
1698 WERROR _srvsvc_NetShareAdd(pipes_struct *p,
1699 struct srvsvc_NetShareAdd *r)
1701 char *command = NULL;
1702 char *share_name = NULL;
1703 char *comment = NULL;
1704 char *pathname = NULL;
1705 int type;
1706 int snum;
1707 int ret;
1708 char *path;
1709 SEC_DESC *psd = NULL;
1710 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1711 bool is_disk_op;
1712 int max_connections = 0;
1713 TALLOC_CTX *ctx = p->mem_ctx;
1715 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1717 if (r->out.parm_error) {
1718 *r->out.parm_error = 0;
1721 is_disk_op = user_has_privileges( p->server_info->ptok, &se_diskop );
1723 if (p->server_info->utok.uid != sec_initial_uid() && !is_disk_op )
1724 return WERR_ACCESS_DENIED;
1726 if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
1727 DEBUG(10,("_srvsvc_NetShareAdd: No add share command\n"));
1728 return WERR_ACCESS_DENIED;
1731 switch (r->in.level) {
1732 case 0:
1733 /* No path. Not enough info in a level 0 to do anything. */
1734 return WERR_ACCESS_DENIED;
1735 case 1:
1736 /* Not enough info in a level 1 to do anything. */
1737 return WERR_ACCESS_DENIED;
1738 case 2:
1739 share_name = talloc_strdup(ctx, r->in.info->info2->name);
1740 comment = talloc_strdup(ctx, r->in.info->info2->comment);
1741 pathname = talloc_strdup(ctx, r->in.info->info2->path);
1742 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
1743 0 : r->in.info->info2->max_users;
1744 type = r->in.info->info2->type;
1745 break;
1746 case 501:
1747 /* No path. Not enough info in a level 501 to do anything. */
1748 return WERR_ACCESS_DENIED;
1749 case 502:
1750 share_name = talloc_strdup(ctx, r->in.info->info502->name);
1751 comment = talloc_strdup(ctx, r->in.info->info502->comment);
1752 pathname = talloc_strdup(ctx, r->in.info->info502->path);
1753 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
1754 0 : r->in.info->info502->max_users;
1755 type = r->in.info->info502->type;
1756 psd = r->in.info->info502->sd_buf.sd;
1757 map_generic_share_sd_bits(psd);
1758 break;
1760 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
1762 case 1004:
1763 case 1005:
1764 case 1006:
1765 case 1007:
1766 return WERR_ACCESS_DENIED;
1767 case 1501:
1768 /* DFS only level. */
1769 return WERR_ACCESS_DENIED;
1770 default:
1771 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
1772 r->in.level));
1773 return WERR_UNKNOWN_LEVEL;
1776 /* check for invalid share names */
1778 if (!share_name || !validate_net_name(share_name,
1779 INVALID_SHARENAME_CHARS,
1780 strlen(share_name))) {
1781 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
1782 share_name ? share_name : ""));
1783 return WERR_INVALID_NAME;
1786 if (strequal(share_name,"IPC$") || strequal(share_name,"global")
1787 || (lp_enable_asu_support() &&
1788 strequal(share_name,"ADMIN$"))) {
1789 return WERR_ACCESS_DENIED;
1792 snum = find_service(share_name);
1794 /* Share already exists. */
1795 if (snum >= 0) {
1796 return WERR_FILE_EXISTS;
1799 /* We can only add disk shares. */
1800 if (type != STYPE_DISKTREE) {
1801 return WERR_ACCESS_DENIED;
1804 /* Check if the pathname is valid. */
1805 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
1806 return WERR_OBJECT_PATH_INVALID;
1809 /* Ensure share name, pathname and comment don't contain '"' characters. */
1810 string_replace(share_name, '"', ' ');
1811 string_replace(path, '"', ' ');
1812 if (comment) {
1813 string_replace(comment, '"', ' ');
1816 command = talloc_asprintf(ctx,
1817 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1818 lp_add_share_cmd(),
1819 get_dyn_CONFIGFILE(),
1820 share_name,
1821 path,
1822 comment ? comment : "",
1823 max_connections);
1824 if (!command) {
1825 return WERR_NOMEM;
1828 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
1830 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1832 if ( is_disk_op )
1833 become_root();
1835 /* FIXME: use libnetconf here - gd */
1837 if ( (ret = smbrun(command, NULL)) == 0 ) {
1838 /* Tell everyone we updated smb.conf. */
1839 message_send_all(smbd_messaging_context(),
1840 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1843 if ( is_disk_op )
1844 unbecome_root();
1846 /********* END SeDiskOperatorPrivilege BLOCK *********/
1848 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
1849 command, ret ));
1851 TALLOC_FREE(command);
1853 if ( ret != 0 )
1854 return WERR_ACCESS_DENIED;
1856 if (psd) {
1857 if (!set_share_security(share_name, psd)) {
1858 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
1859 share_name ));
1864 * We don't call reload_services() here, the message will
1865 * cause this to be done before the next packet is read
1866 * from the client. JRA.
1869 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1871 return WERR_OK;
1874 /*******************************************************************
1875 _srvsvc_NetShareDel
1876 Call "delete share command" with the share name as
1877 a parameter.
1878 ********************************************************************/
1880 WERROR _srvsvc_NetShareDel(pipes_struct *p,
1881 struct srvsvc_NetShareDel *r)
1883 char *command = NULL;
1884 char *share_name = NULL;
1885 int ret;
1886 int snum;
1887 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1888 bool is_disk_op;
1889 struct share_params *params;
1890 TALLOC_CTX *ctx = p->mem_ctx;
1892 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
1894 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1895 if (!share_name) {
1896 return WERR_NET_NAME_NOT_FOUND;
1898 if ( strequal(share_name,"IPC$")
1899 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1900 || strequal(share_name,"global") )
1902 return WERR_ACCESS_DENIED;
1905 if (!(params = get_share_params(p->mem_ctx, share_name))) {
1906 return WERR_NO_SUCH_SHARE;
1909 snum = find_service(share_name);
1911 /* No change to printer shares. */
1912 if (lp_print_ok(snum))
1913 return WERR_ACCESS_DENIED;
1915 is_disk_op = user_has_privileges( p->server_info->ptok, &se_diskop );
1917 if (p->server_info->utok.uid != sec_initial_uid() && !is_disk_op )
1918 return WERR_ACCESS_DENIED;
1920 if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
1921 DEBUG(10,("_srvsvc_NetShareDel: No delete share command\n"));
1922 return WERR_ACCESS_DENIED;
1925 command = talloc_asprintf(ctx,
1926 "%s \"%s\" \"%s\"",
1927 lp_delete_share_cmd(),
1928 get_dyn_CONFIGFILE(),
1929 lp_servicename(snum));
1930 if (!command) {
1931 return WERR_NOMEM;
1934 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
1936 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1938 if ( is_disk_op )
1939 become_root();
1941 if ( (ret = smbrun(command, NULL)) == 0 ) {
1942 /* Tell everyone we updated smb.conf. */
1943 message_send_all(smbd_messaging_context(),
1944 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1947 if ( is_disk_op )
1948 unbecome_root();
1950 /********* END SeDiskOperatorPrivilege BLOCK *********/
1952 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
1954 if ( ret != 0 )
1955 return WERR_ACCESS_DENIED;
1957 /* Delete the SD in the database. */
1958 delete_share_security(lp_servicename(params->service));
1960 lp_killservice(params->service);
1962 return WERR_OK;
1965 /*******************************************************************
1966 _srvsvc_NetShareDelSticky
1967 ********************************************************************/
1969 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p,
1970 struct srvsvc_NetShareDelSticky *r)
1972 struct srvsvc_NetShareDel q;
1974 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
1976 q.in.server_unc = r->in.server_unc;
1977 q.in.share_name = r->in.share_name;
1978 q.in.reserved = r->in.reserved;
1980 return _srvsvc_NetShareDel(p, &q);
1983 /*******************************************************************
1984 _srvsvc_NetRemoteTOD
1985 ********************************************************************/
1987 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p,
1988 struct srvsvc_NetRemoteTOD *r)
1990 struct srvsvc_NetRemoteTODInfo *tod;
1991 struct tm *t;
1992 time_t unixdate = time(NULL);
1994 /* We do this call first as if we do it *after* the gmtime call
1995 it overwrites the pointed-to values. JRA */
1997 uint32 zone = get_time_zone(unixdate)/60;
1999 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2001 if ( !(tod = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
2002 return WERR_NOMEM;
2004 *r->out.info = tod;
2006 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2008 t = gmtime(&unixdate);
2010 /* set up the */
2011 init_srvsvc_NetRemoteTODInfo(tod,
2012 unixdate,
2014 t->tm_hour,
2015 t->tm_min,
2016 t->tm_sec,
2018 zone,
2019 10000,
2020 t->tm_mday,
2021 t->tm_mon + 1,
2022 1900+t->tm_year,
2023 t->tm_wday);
2025 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2027 return WERR_OK;
2030 /***********************************************************************************
2031 _srvsvc_NetGetFileSecurity
2032 Win9x NT tools get security descriptor.
2033 ***********************************************************************************/
2035 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p,
2036 struct srvsvc_NetGetFileSecurity *r)
2038 SEC_DESC *psd = NULL;
2039 size_t sd_size;
2040 fstring servicename;
2041 SMB_STRUCT_STAT st;
2042 NTSTATUS nt_status;
2043 WERROR werr;
2044 connection_struct *conn = NULL;
2045 struct sec_desc_buf *sd_buf = NULL;
2046 files_struct *fsp = NULL;
2047 int snum;
2048 char *oldcwd = NULL;
2050 ZERO_STRUCT(st);
2052 fstrcpy(servicename, r->in.share);
2054 snum = find_service(servicename);
2055 if (snum == -1) {
2056 DEBUG(10, ("Could not find service %s\n", servicename));
2057 werr = WERR_NET_NAME_NOT_FOUND;
2058 goto error_exit;
2061 nt_status = create_conn_struct(talloc_tos(), &conn, snum,
2062 lp_pathname(snum), p->server_info,
2063 &oldcwd);
2064 if (!NT_STATUS_IS_OK(nt_status)) {
2065 DEBUG(10, ("create_conn_struct failed: %s\n",
2066 nt_errstr(nt_status)));
2067 werr = ntstatus_to_werror(nt_status);
2068 goto error_exit;
2071 nt_status = SMB_VFS_CREATE_FILE(
2072 conn, /* conn */
2073 NULL, /* req */
2074 0, /* root_dir_fid */
2075 r->in.file, /* fname */
2076 CFF_DOS_PATH, /* create_file_flags */
2077 FILE_READ_ATTRIBUTES, /* access_mask */
2078 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2079 FILE_OPEN, /* create_disposition*/
2080 0, /* create_options */
2081 0, /* file_attributes */
2082 INTERNAL_OPEN_ONLY, /* oplock_request */
2083 0, /* allocation_size */
2084 NULL, /* sd */
2085 NULL, /* ea_list */
2086 &fsp, /* result */
2087 NULL, /* pinfo */
2088 NULL); /* psbuf */
2090 if (!NT_STATUS_IS_OK(nt_status)) {
2091 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2092 r->in.file));
2093 werr = ntstatus_to_werror(nt_status);
2094 goto error_exit;
2097 nt_status = SMB_VFS_FGET_NT_ACL(fsp,
2098 (OWNER_SECURITY_INFORMATION
2099 |GROUP_SECURITY_INFORMATION
2100 |DACL_SECURITY_INFORMATION), &psd);
2102 if (!NT_STATUS_IS_OK(nt_status)) {
2103 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2104 "for file %s\n", r->in.file));
2105 werr = ntstatus_to_werror(nt_status);
2106 goto error_exit;
2109 sd_size = ndr_size_security_descriptor(psd, 0);
2111 sd_buf = TALLOC_ZERO_P(p->mem_ctx, struct sec_desc_buf);
2112 if (!sd_buf) {
2113 werr = WERR_NOMEM;
2114 goto error_exit;
2117 sd_buf->sd_size = sd_size;
2118 sd_buf->sd = psd;
2120 *r->out.sd_buf = sd_buf;
2122 psd->dacl->revision = NT4_ACL_REVISION;
2124 close_file(NULL, fsp, NORMAL_CLOSE);
2125 vfs_ChDir(conn, oldcwd);
2126 conn_free_internal(conn);
2127 return WERR_OK;
2129 error_exit:
2131 if (fsp) {
2132 close_file(NULL, fsp, NORMAL_CLOSE);
2135 if (oldcwd) {
2136 vfs_ChDir(conn, oldcwd);
2139 if (conn) {
2140 conn_free_internal(conn);
2143 return werr;
2146 /***********************************************************************************
2147 _srvsvc_NetSetFileSecurity
2148 Win9x NT tools set security descriptor.
2149 ***********************************************************************************/
2151 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p,
2152 struct srvsvc_NetSetFileSecurity *r)
2154 fstring servicename;
2155 files_struct *fsp = NULL;
2156 SMB_STRUCT_STAT st;
2157 NTSTATUS nt_status;
2158 WERROR werr;
2159 connection_struct *conn = NULL;
2160 int snum;
2161 char *oldcwd = NULL;
2162 struct security_descriptor *psd = NULL;
2163 uint32_t security_info_sent = 0;
2165 ZERO_STRUCT(st);
2167 fstrcpy(servicename, r->in.share);
2169 snum = find_service(servicename);
2170 if (snum == -1) {
2171 DEBUG(10, ("Could not find service %s\n", servicename));
2172 werr = WERR_NET_NAME_NOT_FOUND;
2173 goto error_exit;
2176 nt_status = create_conn_struct(talloc_tos(), &conn, snum,
2177 lp_pathname(snum), p->server_info,
2178 &oldcwd);
2179 if (!NT_STATUS_IS_OK(nt_status)) {
2180 DEBUG(10, ("create_conn_struct failed: %s\n",
2181 nt_errstr(nt_status)));
2182 werr = ntstatus_to_werror(nt_status);
2183 goto error_exit;
2186 nt_status = SMB_VFS_CREATE_FILE(
2187 conn, /* conn */
2188 NULL, /* req */
2189 0, /* root_dir_fid */
2190 r->in.file, /* fname */
2191 CFF_DOS_PATH, /* create_file_flags */
2192 FILE_WRITE_ATTRIBUTES, /* access_mask */
2193 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2194 FILE_OPEN, /* create_disposition*/
2195 0, /* create_options */
2196 0, /* file_attributes */
2197 INTERNAL_OPEN_ONLY, /* oplock_request */
2198 0, /* allocation_size */
2199 NULL, /* sd */
2200 NULL, /* ea_list */
2201 &fsp, /* result */
2202 NULL, /* pinfo */
2203 NULL); /* psbuf */
2205 if (!NT_STATUS_IS_OK(nt_status)) {
2206 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2207 r->in.file));
2208 werr = ntstatus_to_werror(nt_status);
2209 goto error_exit;
2212 psd = r->in.sd_buf->sd;
2213 security_info_sent = r->in.securityinformation;
2215 if (psd->owner_sid==0) {
2216 security_info_sent &= ~OWNER_SECURITY_INFORMATION;
2218 if (psd->group_sid==0) {
2219 security_info_sent &= ~GROUP_SECURITY_INFORMATION;
2221 if (psd->sacl==0) {
2222 security_info_sent &= ~SACL_SECURITY_INFORMATION;
2224 if (psd->dacl==0) {
2225 security_info_sent &= ~DACL_SECURITY_INFORMATION;
2228 /* Convert all the generic bits. */
2229 security_acl_map_generic(psd->dacl, &file_generic_mapping);
2230 security_acl_map_generic(psd->sacl, &file_generic_mapping);
2232 nt_status = SMB_VFS_FSET_NT_ACL(fsp,
2233 security_info_sent,
2234 psd);
2236 if (!NT_STATUS_IS_OK(nt_status) ) {
2237 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2238 "on file %s\n", r->in.share));
2239 werr = WERR_ACCESS_DENIED;
2240 goto error_exit;
2243 close_file(NULL, fsp, NORMAL_CLOSE);
2244 vfs_ChDir(conn, oldcwd);
2245 conn_free_internal(conn);
2246 return WERR_OK;
2248 error_exit:
2250 if (fsp) {
2251 close_file(NULL, fsp, NORMAL_CLOSE);
2254 if (oldcwd) {
2255 vfs_ChDir(conn, oldcwd);
2258 if (conn) {
2259 conn_free_internal(conn);
2262 return werr;
2265 /***********************************************************************************
2266 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2267 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2268 These disks would the disks listed by this function.
2269 Users could then create shares relative to these disks. Watch out for moving these disks around.
2270 "Nigel Williams" <nigel@veritas.com>.
2271 ***********************************************************************************/
2273 static const char *server_disks[] = {"C:"};
2275 static uint32 get_server_disk_count(void)
2277 return sizeof(server_disks)/sizeof(server_disks[0]);
2280 static uint32 init_server_disk_enum(uint32 *resume)
2282 uint32 server_disk_count = get_server_disk_count();
2284 /*resume can be an offset into the list for now*/
2286 if(*resume & 0x80000000)
2287 *resume = 0;
2289 if(*resume > server_disk_count)
2290 *resume = server_disk_count;
2292 return server_disk_count - *resume;
2295 static const char *next_server_disk_enum(uint32 *resume)
2297 const char *disk;
2299 if(init_server_disk_enum(resume) == 0)
2300 return NULL;
2302 disk = server_disks[*resume];
2304 (*resume)++;
2306 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2308 return disk;
2311 /********************************************************************
2312 _srvsvc_NetDiskEnum
2313 ********************************************************************/
2315 WERROR _srvsvc_NetDiskEnum(pipes_struct *p,
2316 struct srvsvc_NetDiskEnum *r)
2318 uint32 i;
2319 const char *disk_name;
2320 TALLOC_CTX *ctx = p->mem_ctx;
2321 WERROR werr;
2322 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2324 werr = WERR_OK;
2326 *r->out.totalentries = init_server_disk_enum(&resume);
2328 r->out.info->disks = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetDiskInfo0,
2329 MAX_SERVER_DISK_ENTRIES);
2330 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2332 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2334 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2336 r->out.info->count++;
2338 /*copy disk name into a unicode string*/
2340 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2341 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2344 /* add a terminating null string. Is this there if there is more data to come? */
2346 r->out.info->count++;
2348 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2349 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2351 if (r->out.resume_handle) {
2352 *r->out.resume_handle = resume;
2355 return werr;
2358 /********************************************************************
2359 _srvsvc_NetNameValidate
2360 ********************************************************************/
2362 WERROR _srvsvc_NetNameValidate(pipes_struct *p,
2363 struct srvsvc_NetNameValidate *r)
2365 switch (r->in.name_type) {
2366 case 0x9:
2367 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2368 strlen_m(r->in.name)))
2370 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2371 r->in.name));
2372 return WERR_INVALID_NAME;
2374 break;
2376 default:
2377 return WERR_UNKNOWN_LEVEL;
2380 return WERR_OK;
2383 /*******************************************************************
2384 ********************************************************************/
2386 static void enum_file_close_fn( const struct share_mode_entry *e,
2387 const char *sharepath, const char *fname,
2388 void *private_data )
2390 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2391 struct srvsvc_NetFileClose *r =
2392 (struct srvsvc_NetFileClose *)private_data;
2393 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2395 if (fid != r->in.fid) {
2396 return; /* Not this file. */
2399 if (!process_exists(e->pid) ) {
2400 return;
2403 /* Ok - send the close message. */
2404 DEBUG(10,("enum_file_close_fn: request to close file %s, %s\n",
2405 sharepath,
2406 share_mode_str(talloc_tos(), 0, e) ));
2408 share_mode_entry_to_message(msg, e);
2410 r->out.result = ntstatus_to_werror(
2411 messaging_send_buf(smbd_messaging_context(),
2412 e->pid, MSG_SMB_CLOSE_FILE,
2413 (uint8 *)msg,
2414 MSG_SMB_SHARE_MODE_ENTRY_SIZE));
2417 /********************************************************************
2418 Close a file given a 32-bit file id.
2419 ********************************************************************/
2421 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2423 SE_PRIV se_diskop = SE_DISK_OPERATOR;
2424 bool is_disk_op;
2426 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2428 is_disk_op = user_has_privileges( p->server_info->ptok, &se_diskop );
2430 if (p->server_info->utok.uid != sec_initial_uid() && !is_disk_op) {
2431 return WERR_ACCESS_DENIED;
2434 /* enum_file_close_fn sends the close message to
2435 * the relevent smbd process. */
2437 r->out.result = WERR_BADFILE;
2438 share_mode_forall( enum_file_close_fn, (void *)r);
2439 return r->out.result;
2442 /********************************************************************
2443 ********************************************************************/
2445 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2447 p->rng_fault_state = True;
2448 return WERR_NOT_SUPPORTED;
2451 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2453 p->rng_fault_state = True;
2454 return WERR_NOT_SUPPORTED;
2457 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2459 p->rng_fault_state = True;
2460 return WERR_NOT_SUPPORTED;
2463 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2465 p->rng_fault_state = True;
2466 return WERR_NOT_SUPPORTED;
2469 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2471 p->rng_fault_state = True;
2472 return WERR_NOT_SUPPORTED;
2475 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2477 p->rng_fault_state = True;
2478 return WERR_NOT_SUPPORTED;
2481 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2483 p->rng_fault_state = True;
2484 return WERR_NOT_SUPPORTED;
2487 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2489 p->rng_fault_state = True;
2490 return WERR_NOT_SUPPORTED;
2493 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2495 p->rng_fault_state = True;
2496 return WERR_NOT_SUPPORTED;
2499 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2501 p->rng_fault_state = True;
2502 return WERR_NOT_SUPPORTED;
2505 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2507 p->rng_fault_state = True;
2508 return WERR_NOT_SUPPORTED;
2511 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2513 p->rng_fault_state = True;
2514 return WERR_NOT_SUPPORTED;
2517 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2519 p->rng_fault_state = True;
2520 return WERR_NOT_SUPPORTED;
2523 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2525 p->rng_fault_state = True;
2526 return WERR_NOT_SUPPORTED;
2529 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2531 p->rng_fault_state = True;
2532 return WERR_NOT_SUPPORTED;
2535 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2537 p->rng_fault_state = True;
2538 return WERR_NOT_SUPPORTED;
2541 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2543 p->rng_fault_state = True;
2544 return WERR_NOT_SUPPORTED;
2547 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2549 p->rng_fault_state = True;
2550 return WERR_NOT_SUPPORTED;
2553 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2555 p->rng_fault_state = True;
2556 return WERR_NOT_SUPPORTED;
2559 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2561 p->rng_fault_state = True;
2562 return WERR_NOT_SUPPORTED;
2565 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2567 p->rng_fault_state = True;
2568 return WERR_NOT_SUPPORTED;
2571 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2573 p->rng_fault_state = True;
2574 return WERR_NOT_SUPPORTED;
2577 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2579 p->rng_fault_state = True;
2580 return WERR_NOT_SUPPORTED;
2583 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2585 p->rng_fault_state = True;
2586 return WERR_NOT_SUPPORTED;
2589 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2591 p->rng_fault_state = True;
2592 return WERR_NOT_SUPPORTED;
2595 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2597 p->rng_fault_state = True;
2598 return WERR_NOT_SUPPORTED;
2601 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2603 p->rng_fault_state = True;
2604 return WERR_NOT_SUPPORTED;
2607 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
2609 p->rng_fault_state = True;
2610 return WERR_NOT_SUPPORTED;
2613 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2615 p->rng_fault_state = True;
2616 return WERR_NOT_SUPPORTED;
2619 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2621 p->rng_fault_state = True;
2622 return WERR_NOT_SUPPORTED;
2625 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2627 p->rng_fault_state = True;
2628 return WERR_NOT_SUPPORTED;
2631 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2633 p->rng_fault_state = True;
2634 return WERR_NOT_SUPPORTED;
2637 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2639 p->rng_fault_state = True;
2640 return WERR_NOT_SUPPORTED;
2643 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2645 p->rng_fault_state = True;
2646 return WERR_NOT_SUPPORTED;
2649 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2651 p->rng_fault_state = True;
2652 return WERR_NOT_SUPPORTED;