Fix srvsvc_Net[Get|Set]FileSecurity
[Samba.git] / source / rpc_server / srv_srvsvc_nt.c
blobbb9c3687fbc6d86483e1542306c479950973a408
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->pipe_user.ut.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->pipe_user.ut.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->pipe_user.ut.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->pipe_user.ut.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->pipe_user.ut.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 Fill in a share info structure.
497 ********************************************************************/
499 static WERROR init_srv_share_info_ctr(pipes_struct *p,
500 struct srvsvc_NetShareInfoCtr *info_ctr,
501 uint32_t *resume_handle_p,
502 uint32_t *total_entries,
503 bool all_shares)
505 int num_entries = 0;
506 int alloc_entries = 0;
507 int num_services = 0;
508 int snum;
509 TALLOC_CTX *ctx = p->mem_ctx;
510 int i = 0;
511 int valid_share_count = 0;
512 union srvsvc_NetShareCtr ctr;
513 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
515 DEBUG(5,("init_srv_share_info_ctr\n"));
517 /* Ensure all the usershares are loaded. */
518 become_root();
519 load_usershare_shares();
520 load_registry_shares();
521 num_services = lp_numservices();
522 unbecome_root();
524 /* Count the number of entries. */
525 for (snum = 0; snum < num_services; snum++) {
526 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
527 DEBUG(10, ("counting service %s\n", lp_servicename(snum)));
528 num_entries++;
529 } else {
530 DEBUG(10, ("NOT counting service %s\n", lp_servicename(snum)));
534 if (!num_entries || (resume_handle >= num_entries)) {
535 return WERR_OK;
538 /* Calculate alloc entries. */
539 alloc_entries = num_entries - resume_handle;
540 switch (info_ctr->level) {
541 case 0:
542 ctr.ctr0 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr0);
543 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
545 ctr.ctr0->count = alloc_entries;
546 ctr.ctr0->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
547 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
549 for (snum = 0; snum < num_services; snum++) {
550 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
551 (resume_handle <= (i + valid_share_count++)) ) {
552 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
556 break;
558 case 1:
559 ctr.ctr1 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1);
560 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
562 ctr.ctr1->count = alloc_entries;
563 ctr.ctr1->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
564 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
566 for (snum = 0; snum < num_services; snum++) {
567 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
568 (resume_handle <= (i + valid_share_count++)) ) {
569 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
573 break;
575 case 2:
576 ctr.ctr2 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr2);
577 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
579 ctr.ctr2->count = alloc_entries;
580 ctr.ctr2->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
581 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
583 for (snum = 0; snum < num_services; snum++) {
584 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
585 (resume_handle <= (i + valid_share_count++)) ) {
586 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
590 break;
592 case 501:
593 ctr.ctr501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr501);
594 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
596 ctr.ctr501->count = alloc_entries;
597 ctr.ctr501->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
598 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
600 for (snum = 0; snum < num_services; snum++) {
601 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
602 (resume_handle <= (i + valid_share_count++)) ) {
603 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
607 break;
609 case 502:
610 ctr.ctr502 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr502);
611 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
613 ctr.ctr502->count = alloc_entries;
614 ctr.ctr502->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
615 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
617 for (snum = 0; snum < num_services; snum++) {
618 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
619 (resume_handle <= (i + valid_share_count++)) ) {
620 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
624 break;
626 case 1004:
627 ctr.ctr1004 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1004);
628 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
630 ctr.ctr1004->count = alloc_entries;
631 ctr.ctr1004->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
632 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
634 for (snum = 0; snum < num_services; snum++) {
635 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
636 (resume_handle <= (i + valid_share_count++)) ) {
637 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
641 break;
643 case 1005:
644 ctr.ctr1005 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1005);
645 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
647 ctr.ctr1005->count = alloc_entries;
648 ctr.ctr1005->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
649 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
651 for (snum = 0; snum < num_services; snum++) {
652 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
653 (resume_handle <= (i + valid_share_count++)) ) {
654 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
658 break;
660 case 1006:
661 ctr.ctr1006 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1006);
662 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
664 ctr.ctr1006->count = alloc_entries;
665 ctr.ctr1006->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
666 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
668 for (snum = 0; snum < num_services; snum++) {
669 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
670 (resume_handle <= (i + valid_share_count++)) ) {
671 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
675 break;
677 case 1007:
678 ctr.ctr1007 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1007);
679 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
681 ctr.ctr1007->count = alloc_entries;
682 ctr.ctr1007->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
683 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
685 for (snum = 0; snum < num_services; snum++) {
686 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
687 (resume_handle <= (i + valid_share_count++)) ) {
688 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
692 break;
694 case 1501:
695 ctr.ctr1501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1501);
696 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
698 ctr.ctr1501->count = alloc_entries;
699 ctr.ctr1501->array = TALLOC_ZERO_ARRAY(ctx, struct sec_desc_buf, alloc_entries);
700 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
702 for (snum = 0; snum < num_services; snum++) {
703 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
704 (resume_handle <= (i + valid_share_count++)) ) {
705 init_srv_share_info_1501(p, &ctr.ctr1501->array[i++], snum);
709 break;
711 default:
712 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
713 info_ctr->level));
714 return WERR_UNKNOWN_LEVEL;
717 *total_entries = alloc_entries;
718 if (resume_handle_p) {
719 if (all_shares) {
720 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
721 } else {
722 *resume_handle_p = num_entries;
726 info_ctr->ctr = ctr;
728 return WERR_OK;
731 /*******************************************************************
732 fill in a sess info level 0 structure.
733 ********************************************************************/
735 static WERROR init_srv_sess_info_0(pipes_struct *p,
736 struct srvsvc_NetSessCtr0 *ctr0,
737 uint32_t *resume_handle_p,
738 uint32_t *total_entries)
740 struct sessionid *session_list;
741 uint32_t num_entries = 0;
742 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
743 *total_entries = list_sessions(p->mem_ctx, &session_list);
745 DEBUG(5,("init_srv_sess_info_0\n"));
747 if (ctr0 == NULL) {
748 if (resume_handle_p) {
749 *resume_handle_p = 0;
751 return WERR_OK;
754 for (; resume_handle < *total_entries; resume_handle++) {
756 ctr0->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
757 ctr0->array,
758 struct srvsvc_NetSessInfo0,
759 num_entries+1);
760 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
762 init_srvsvc_NetSessInfo0(&ctr0->array[num_entries],
763 session_list[resume_handle].remote_machine);
764 num_entries++;
767 ctr0->count = num_entries;
769 if (resume_handle_p) {
770 if (*resume_handle_p >= *total_entries) {
771 *resume_handle_p = 0;
772 } else {
773 *resume_handle_p = resume_handle;
777 return WERR_OK;
780 /*******************************************************************
781 ********************************************************************/
783 static void sess_file_fn( const struct share_mode_entry *e,
784 const char *sharepath, const char *fname,
785 void *data )
787 struct sess_file_count *sess = (struct sess_file_count *)data;
789 if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
790 sess->count++;
793 return;
796 /*******************************************************************
797 ********************************************************************/
799 static int net_count_files( uid_t uid, struct server_id pid )
801 struct sess_file_count s_file_cnt;
803 s_file_cnt.count = 0;
804 s_file_cnt.uid = uid;
805 s_file_cnt.pid = pid;
807 share_mode_forall( sess_file_fn, &s_file_cnt );
809 return s_file_cnt.count;
812 /*******************************************************************
813 fill in a sess info level 1 structure.
814 ********************************************************************/
816 static WERROR init_srv_sess_info_1(pipes_struct *p,
817 struct srvsvc_NetSessCtr1 *ctr1,
818 uint32_t *resume_handle_p,
819 uint32_t *total_entries)
821 struct sessionid *session_list;
822 uint32_t num_entries = 0;
823 time_t now = time(NULL);
824 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
826 ZERO_STRUCTP(ctr1);
828 if (ctr1 == NULL) {
829 if (resume_handle_p) {
830 *resume_handle_p = 0;
832 return WERR_OK;
835 *total_entries = list_sessions(p->mem_ctx, &session_list);
837 for (; resume_handle < *total_entries; resume_handle++) {
838 uint32 num_files;
839 uint32 connect_time;
840 struct passwd *pw = sys_getpwnam(session_list[resume_handle].username);
841 bool guest;
843 if ( !pw ) {
844 DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
845 session_list[resume_handle].username));
846 continue;
849 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
850 num_files = net_count_files(pw->pw_uid, session_list[resume_handle].pid);
851 guest = strequal( session_list[resume_handle].username, lp_guestaccount() );
853 ctr1->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
854 ctr1->array,
855 struct srvsvc_NetSessInfo1,
856 num_entries+1);
857 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
859 init_srvsvc_NetSessInfo1(&ctr1->array[num_entries],
860 session_list[resume_handle].remote_machine,
861 session_list[resume_handle].username,
862 num_files,
863 connect_time,
865 guest);
866 num_entries++;
869 ctr1->count = num_entries;
871 if (resume_handle_p) {
872 if (*resume_handle_p >= *total_entries) {
873 *resume_handle_p = 0;
874 } else {
875 *resume_handle_p = resume_handle;
879 return WERR_OK;
882 /*******************************************************************
883 fill in a conn info level 0 structure.
884 ********************************************************************/
886 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
887 uint32_t *resume_handle_p,
888 uint32_t *total_entries)
890 uint32_t num_entries = 0;
891 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
893 DEBUG(5,("init_srv_conn_info_0\n"));
895 if (ctr0 == NULL) {
896 if (resume_handle_p) {
897 *resume_handle_p = 0;
899 return WERR_OK;
902 *total_entries = 1;
904 ZERO_STRUCTP(ctr0);
906 for (; resume_handle < *total_entries; resume_handle++) {
908 ctr0->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
909 ctr0->array,
910 struct srvsvc_NetConnInfo0,
911 num_entries+1);
912 if (!ctr0->array) {
913 return WERR_NOMEM;
916 init_srvsvc_NetConnInfo0(&ctr0->array[num_entries],
917 (*total_entries));
919 /* move on to creating next connection */
920 num_entries++;
923 ctr0->count = num_entries;
924 *total_entries = num_entries;
926 if (resume_handle_p) {
927 if (*resume_handle_p >= *total_entries) {
928 *resume_handle_p = 0;
929 } else {
930 *resume_handle_p = resume_handle;
934 return WERR_OK;
937 /*******************************************************************
938 fill in a conn info level 1 structure.
939 ********************************************************************/
941 static WERROR init_srv_conn_info_1(struct srvsvc_NetConnCtr1 *ctr1,
942 uint32_t *resume_handle_p,
943 uint32_t *total_entries)
945 uint32_t num_entries = 0;
946 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
948 DEBUG(5,("init_srv_conn_info_1\n"));
950 if (ctr1 == NULL) {
951 if (resume_handle_p) {
952 *resume_handle_p = 0;
954 return WERR_OK;
957 *total_entries = 1;
959 ZERO_STRUCTP(ctr1);
961 for (; resume_handle < *total_entries; resume_handle++) {
963 ctr1->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
964 ctr1->array,
965 struct srvsvc_NetConnInfo1,
966 num_entries+1);
967 if (!ctr1->array) {
968 return WERR_NOMEM;
971 init_srvsvc_NetConnInfo1(&ctr1->array[num_entries],
972 (*total_entries),
973 0x3,
977 "dummy_user",
978 "IPC$");
980 /* move on to creating next connection */
981 num_entries++;
984 ctr1->count = num_entries;
985 *total_entries = num_entries;
987 if (resume_handle_p) {
988 if (*resume_handle_p >= *total_entries) {
989 *resume_handle_p = 0;
990 } else {
991 *resume_handle_p = resume_handle;
995 return WERR_OK;
998 /*******************************************************************
999 _srvsvc_NetFileEnum
1000 *******************************************************************/
1002 WERROR _srvsvc_NetFileEnum(pipes_struct *p,
1003 struct srvsvc_NetFileEnum *r)
1005 TALLOC_CTX *ctx = NULL;
1006 struct srvsvc_NetFileCtr3 *ctr3;
1007 uint32_t resume_hnd = 0;
1008 WERROR werr;
1010 switch (r->in.info_ctr->level) {
1011 case 3:
1012 break;
1013 default:
1014 return WERR_UNKNOWN_LEVEL;
1017 ctx = talloc_tos();
1018 ctr3 = r->in.info_ctr->ctr.ctr3;
1019 if (!ctr3) {
1020 werr = WERR_INVALID_PARAM;
1021 goto done;
1024 /* TODO -- Windows enumerates
1025 (b) active pipes
1026 (c) open directories and files */
1028 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1029 if (!W_ERROR_IS_OK(werr)) {
1030 goto done;
1033 werr = net_enum_pipes(ctx, r->in.user, &ctr3, resume_hnd);
1034 if (!W_ERROR_IS_OK(werr)) {
1035 goto done;
1038 *r->out.totalentries = ctr3->count;
1039 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1040 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1042 werr = WERR_OK;
1044 done:
1045 return werr;
1048 /*******************************************************************
1049 _srvsvc_NetSrvGetInfo
1050 ********************************************************************/
1052 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p,
1053 struct srvsvc_NetSrvGetInfo *r)
1055 WERROR status = WERR_OK;
1057 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1059 if (!pipe_access_check(p)) {
1060 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1061 return WERR_ACCESS_DENIED;
1064 switch (r->in.level) {
1066 /* Technically level 102 should only be available to
1067 Administrators but there isn't anything super-secret
1068 here, as most of it is made up. */
1070 case 102: {
1071 struct srvsvc_NetSrvInfo102 *info102;
1073 info102 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1074 if (!info102) {
1075 return WERR_NOMEM;
1078 init_srvsvc_NetSrvInfo102(info102,
1079 PLATFORM_ID_NT,
1080 global_myname(),
1081 lp_major_announce_version(),
1082 lp_minor_announce_version(),
1083 lp_default_server_announce(),
1084 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
1085 0xffffffff, /* users */
1086 0xf, /* disc */
1087 0, /* hidden */
1088 240, /* announce */
1089 3000, /* announce delta */
1090 100000, /* licenses */
1091 "c:\\"); /* user path */
1092 r->out.info->info102 = info102;
1093 break;
1095 case 101: {
1096 struct srvsvc_NetSrvInfo101 *info101;
1098 info101 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1099 if (!info101) {
1100 return WERR_NOMEM;
1103 init_srvsvc_NetSrvInfo101(info101,
1104 PLATFORM_ID_NT,
1105 global_myname(),
1106 lp_major_announce_version(),
1107 lp_minor_announce_version(),
1108 lp_default_server_announce(),
1109 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1110 r->out.info->info101 = info101;
1111 break;
1113 case 100: {
1114 struct srvsvc_NetSrvInfo100 *info100;
1116 info100 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1117 if (!info100) {
1118 return WERR_NOMEM;
1121 init_srvsvc_NetSrvInfo100(info100,
1122 PLATFORM_ID_NT,
1123 global_myname());
1124 r->out.info->info100 = info100;
1126 break;
1128 default:
1129 status = WERR_UNKNOWN_LEVEL;
1130 break;
1133 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1135 return status;
1138 /*******************************************************************
1139 _srvsvc_NetSrvSetInfo
1140 ********************************************************************/
1142 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p,
1143 struct srvsvc_NetSrvSetInfo *r)
1145 WERROR status = WERR_OK;
1147 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1149 /* Set up the net server set info structure. */
1151 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1153 return status;
1156 /*******************************************************************
1157 _srvsvc_NetConnEnum
1158 ********************************************************************/
1160 WERROR _srvsvc_NetConnEnum(pipes_struct *p,
1161 struct srvsvc_NetConnEnum *r)
1163 WERROR werr;
1165 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1167 switch (r->in.info_ctr->level) {
1168 case 0:
1169 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1170 r->in.resume_handle,
1171 r->out.totalentries);
1172 break;
1173 case 1:
1174 werr = init_srv_conn_info_1(r->in.info_ctr->ctr.ctr1,
1175 r->in.resume_handle,
1176 r->out.totalentries);
1177 break;
1178 default:
1179 return WERR_UNKNOWN_LEVEL;
1182 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1184 return werr;
1187 /*******************************************************************
1188 _srvsvc_NetSessEnum
1189 ********************************************************************/
1191 WERROR _srvsvc_NetSessEnum(pipes_struct *p,
1192 struct srvsvc_NetSessEnum *r)
1194 WERROR werr;
1196 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1198 switch (r->in.info_ctr->level) {
1199 case 0:
1200 werr = init_srv_sess_info_0(p,
1201 r->in.info_ctr->ctr.ctr0,
1202 r->in.resume_handle,
1203 r->out.totalentries);
1204 break;
1205 case 1:
1206 werr = init_srv_sess_info_1(p,
1207 r->in.info_ctr->ctr.ctr1,
1208 r->in.resume_handle,
1209 r->out.totalentries);
1210 break;
1211 default:
1212 return WERR_UNKNOWN_LEVEL;
1215 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1217 return werr;
1220 /*******************************************************************
1221 _srvsvc_NetSessDel
1222 ********************************************************************/
1224 WERROR _srvsvc_NetSessDel(pipes_struct *p,
1225 struct srvsvc_NetSessDel *r)
1227 struct sessionid *session_list;
1228 struct current_user user;
1229 int num_sessions, snum;
1230 const char *username;
1231 const char *machine;
1232 bool not_root = False;
1233 WERROR werr;
1235 username = r->in.user;
1236 machine = r->in.client;
1238 /* strip leading backslashes if any */
1239 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1240 machine += 2;
1243 num_sessions = list_sessions(p->mem_ctx, &session_list);
1245 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1247 werr = WERR_ACCESS_DENIED;
1249 get_current_user(&user, p);
1251 /* fail out now if you are not root or not a domain admin */
1253 if ((user.ut.uid != sec_initial_uid()) &&
1254 ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
1256 goto done;
1259 for (snum = 0; snum < num_sessions; snum++) {
1261 if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
1262 strequal(session_list[snum].remote_machine, machine)) {
1264 NTSTATUS ntstat;
1266 if (user.ut.uid != sec_initial_uid()) {
1267 not_root = True;
1268 become_root();
1271 ntstat = messaging_send(smbd_messaging_context(),
1272 session_list[snum].pid,
1273 MSG_SHUTDOWN, &data_blob_null);
1275 if (NT_STATUS_IS_OK(ntstat))
1276 werr = WERR_OK;
1278 if (not_root)
1279 unbecome_root();
1283 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1285 done:
1287 return werr;
1290 /*******************************************************************
1291 _srvsvc_NetShareEnumAll
1292 ********************************************************************/
1294 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p,
1295 struct srvsvc_NetShareEnumAll *r)
1297 WERROR werr;
1299 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1301 if (!pipe_access_check(p)) {
1302 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1303 return WERR_ACCESS_DENIED;
1306 /* Create the list of shares for the response. */
1307 werr = init_srv_share_info_ctr(p,
1308 r->in.info_ctr,
1309 r->in.resume_handle,
1310 r->out.totalentries,
1311 true);
1313 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1315 return werr;
1318 /*******************************************************************
1319 _srvsvc_NetShareEnum
1320 ********************************************************************/
1322 WERROR _srvsvc_NetShareEnum(pipes_struct *p,
1323 struct srvsvc_NetShareEnum *r)
1325 WERROR werr;
1327 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1329 if (!pipe_access_check(p)) {
1330 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1331 return WERR_ACCESS_DENIED;
1334 /* Create the list of shares for the response. */
1335 werr = init_srv_share_info_ctr(p,
1336 r->in.info_ctr,
1337 r->in.resume_handle,
1338 r->out.totalentries,
1339 false);
1341 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1343 return werr;
1346 /*******************************************************************
1347 _srvsvc_NetShareGetInfo
1348 ********************************************************************/
1350 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p,
1351 struct srvsvc_NetShareGetInfo *r)
1353 WERROR status = WERR_OK;
1354 fstring share_name;
1355 int snum;
1356 union srvsvc_NetShareInfo *info = r->out.info;
1358 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1360 fstrcpy(share_name, r->in.share_name);
1362 snum = find_service(share_name);
1363 if (snum < 0) {
1364 return WERR_INVALID_NAME;
1367 switch (r->in.level) {
1368 case 0:
1369 info->info0 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo0);
1370 W_ERROR_HAVE_NO_MEMORY(info->info0);
1371 init_srv_share_info_0(p, info->info0, snum);
1372 break;
1373 case 1:
1374 info->info1 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1);
1375 W_ERROR_HAVE_NO_MEMORY(info->info1);
1376 init_srv_share_info_1(p, info->info1, snum);
1377 break;
1378 case 2:
1379 info->info2 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo2);
1380 W_ERROR_HAVE_NO_MEMORY(info->info2);
1381 init_srv_share_info_2(p, info->info2, snum);
1382 break;
1383 case 501:
1384 info->info501 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo501);
1385 W_ERROR_HAVE_NO_MEMORY(info->info501);
1386 init_srv_share_info_501(p, info->info501, snum);
1387 break;
1388 case 502:
1389 info->info502 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo502);
1390 W_ERROR_HAVE_NO_MEMORY(info->info502);
1391 init_srv_share_info_502(p, info->info502, snum);
1392 break;
1393 case 1004:
1394 info->info1004 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1395 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1396 init_srv_share_info_1004(p, info->info1004, snum);
1397 break;
1398 case 1005:
1399 info->info1005 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1400 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1401 init_srv_share_info_1005(p, info->info1005, snum);
1402 break;
1403 case 1006:
1404 info->info1006 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1405 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1406 init_srv_share_info_1006(p, info->info1006, snum);
1407 break;
1408 case 1007:
1409 info->info1007 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1410 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1411 init_srv_share_info_1007(p, info->info1007, snum);
1412 break;
1413 case 1501:
1414 init_srv_share_info_1501(p, info->info1501, snum);
1415 break;
1416 default:
1417 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1418 r->in.level));
1419 status = WERR_UNKNOWN_LEVEL;
1420 break;
1423 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1425 return status;
1428 /*******************************************************************
1429 Check a given DOS pathname is valid for a share.
1430 ********************************************************************/
1432 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
1434 char *ptr = NULL;
1436 if (!dos_pathname) {
1437 return NULL;
1440 ptr = talloc_strdup(ctx, dos_pathname);
1441 if (!ptr) {
1442 return NULL;
1444 /* Convert any '\' paths to '/' */
1445 unix_format(ptr);
1446 ptr = unix_clean_name(ctx, ptr);
1447 if (!ptr) {
1448 return NULL;
1451 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1452 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
1453 ptr += 2;
1455 /* Only absolute paths allowed. */
1456 if (*ptr != '/')
1457 return NULL;
1459 return ptr;
1462 /*******************************************************************
1463 _srvsvc_NetShareSetInfo. Modify share details.
1464 ********************************************************************/
1466 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p,
1467 struct srvsvc_NetShareSetInfo *r)
1469 struct current_user user;
1470 char *command = NULL;
1471 char *share_name = NULL;
1472 char *comment = NULL;
1473 const char *pathname = NULL;
1474 int type;
1475 int snum;
1476 int ret;
1477 char *path = NULL;
1478 SEC_DESC *psd = NULL;
1479 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1480 bool is_disk_op = False;
1481 int max_connections = 0;
1482 TALLOC_CTX *ctx = p->mem_ctx;
1483 union srvsvc_NetShareInfo *info = r->in.info;
1485 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1487 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1488 if (!share_name) {
1489 return WERR_NOMEM;
1492 if (r->out.parm_error) {
1493 *r->out.parm_error = 0;
1496 if ( strequal(share_name,"IPC$")
1497 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1498 || strequal(share_name,"global") )
1500 return WERR_ACCESS_DENIED;
1503 snum = find_service(share_name);
1505 /* Does this share exist ? */
1506 if (snum < 0)
1507 return WERR_NET_NAME_NOT_FOUND;
1509 /* No change to printer shares. */
1510 if (lp_print_ok(snum))
1511 return WERR_ACCESS_DENIED;
1513 get_current_user(&user,p);
1515 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1517 /* fail out now if you are not root and not a disk op */
1519 if ( user.ut.uid != sec_initial_uid() && !is_disk_op )
1520 return WERR_ACCESS_DENIED;
1522 switch (r->in.level) {
1523 case 1:
1524 pathname = talloc_strdup(ctx, lp_pathname(snum));
1525 comment = talloc_strdup(ctx, info->info1->comment);
1526 type = info->info1->type;
1527 psd = NULL;
1528 break;
1529 case 2:
1530 comment = talloc_strdup(ctx, info->info2->comment);
1531 pathname = info->info2->path;
1532 type = info->info2->type;
1533 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1534 0 : info->info2->max_users;
1535 psd = NULL;
1536 break;
1537 #if 0
1538 /* not supported on set but here for completeness */
1539 case 501:
1540 comment = talloc_strdup(ctx, info->info501->comment);
1541 type = info->info501->type;
1542 psd = NULL;
1543 break;
1544 #endif
1545 case 502:
1546 comment = talloc_strdup(ctx, info->info502->comment);
1547 pathname = info->info502->path;
1548 type = info->info502->type;
1549 psd = info->info502->sd_buf.sd;
1550 map_generic_share_sd_bits(psd);
1551 break;
1552 case 1004:
1553 pathname = talloc_strdup(ctx, lp_pathname(snum));
1554 comment = talloc_strdup(ctx, info->info1004->comment);
1555 type = STYPE_DISKTREE;
1556 break;
1557 case 1005:
1558 /* XP re-sets the csc policy even if it wasn't changed by the
1559 user, so we must compare it to see if it's what is set in
1560 smb.conf, so that we can contine other ops like setting
1561 ACLs on a share */
1562 if (((info->info1005->dfs_flags &
1563 SHARE_1005_CSC_POLICY_MASK) >>
1564 SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1565 return WERR_OK;
1566 else {
1567 DEBUG(3, ("_srvsvc_NetShareSetInfo: client is trying to change csc policy from the network; must be done with smb.conf\n"));
1568 return WERR_ACCESS_DENIED;
1570 case 1006:
1571 case 1007:
1572 return WERR_ACCESS_DENIED;
1573 case 1501:
1574 pathname = talloc_strdup(ctx, lp_pathname(snum));
1575 comment = talloc_strdup(ctx, lp_comment(snum));
1576 psd = info->info1501->sd;
1577 map_generic_share_sd_bits(psd);
1578 type = STYPE_DISKTREE;
1579 break;
1580 default:
1581 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1582 r->in.level));
1583 return WERR_UNKNOWN_LEVEL;
1586 /* We can only modify disk shares. */
1587 if (type != STYPE_DISKTREE)
1588 return WERR_ACCESS_DENIED;
1590 if (comment == NULL) {
1591 return WERR_NOMEM;
1594 /* Check if the pathname is valid. */
1595 if (!(path = valid_share_pathname(p->mem_ctx, pathname )))
1596 return WERR_OBJECT_PATH_INVALID;
1598 /* Ensure share name, pathname and comment don't contain '"' characters. */
1599 string_replace(share_name, '"', ' ');
1600 string_replace(path, '"', ' ');
1601 string_replace(comment, '"', ' ');
1603 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1604 lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1606 /* Only call modify function if something changed. */
1608 if (strcmp(path, lp_pathname(snum)) || strcmp(comment, lp_comment(snum))
1609 || (lp_max_connections(snum) != max_connections)) {
1610 if (!lp_change_share_cmd() || !*lp_change_share_cmd()) {
1611 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1612 return WERR_ACCESS_DENIED;
1615 command = talloc_asprintf(p->mem_ctx,
1616 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1617 lp_change_share_cmd(),
1618 get_dyn_CONFIGFILE(),
1619 share_name,
1620 path,
1621 comment ? comment : "",
1622 max_connections);
1623 if (!command) {
1624 return WERR_NOMEM;
1627 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1629 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1631 if (is_disk_op)
1632 become_root();
1634 if ( (ret = smbrun(command, NULL)) == 0 ) {
1635 /* Tell everyone we updated smb.conf. */
1636 message_send_all(smbd_messaging_context(),
1637 MSG_SMB_CONF_UPDATED, NULL, 0,
1638 NULL);
1641 if ( is_disk_op )
1642 unbecome_root();
1644 /********* END SeDiskOperatorPrivilege BLOCK *********/
1646 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1647 command, ret ));
1649 TALLOC_FREE(command);
1651 if ( ret != 0 )
1652 return WERR_ACCESS_DENIED;
1653 } else {
1654 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1655 share_name ));
1658 /* Replace SD if changed. */
1659 if (psd) {
1660 SEC_DESC *old_sd;
1661 size_t sd_size;
1663 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum), &sd_size);
1665 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1666 if (!set_share_security(share_name, psd))
1667 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1668 share_name ));
1672 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1674 return WERR_OK;
1677 /*******************************************************************
1678 _srvsvc_NetShareAdd.
1679 Call 'add_share_command "sharename" "pathname"
1680 "comment" "max connections = "
1681 ********************************************************************/
1683 WERROR _srvsvc_NetShareAdd(pipes_struct *p,
1684 struct srvsvc_NetShareAdd *r)
1686 struct current_user user;
1687 char *command = NULL;
1688 char *share_name = NULL;
1689 char *comment = NULL;
1690 char *pathname = NULL;
1691 int type;
1692 int snum;
1693 int ret;
1694 char *path;
1695 SEC_DESC *psd = NULL;
1696 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1697 bool is_disk_op;
1698 int max_connections = 0;
1699 TALLOC_CTX *ctx = p->mem_ctx;
1701 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1703 *r->out.parm_error = 0;
1705 get_current_user(&user,p);
1707 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1709 if (user.ut.uid != sec_initial_uid() && !is_disk_op )
1710 return WERR_ACCESS_DENIED;
1712 if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
1713 DEBUG(10,("_srvsvc_NetShareAdd: No add share command\n"));
1714 return WERR_ACCESS_DENIED;
1717 switch (r->in.level) {
1718 case 0:
1719 /* No path. Not enough info in a level 0 to do anything. */
1720 return WERR_ACCESS_DENIED;
1721 case 1:
1722 /* Not enough info in a level 1 to do anything. */
1723 return WERR_ACCESS_DENIED;
1724 case 2:
1725 share_name = talloc_strdup(ctx, r->in.info->info2->name);
1726 comment = talloc_strdup(ctx, r->in.info->info2->comment);
1727 pathname = talloc_strdup(ctx, r->in.info->info2->path);
1728 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
1729 0 : r->in.info->info2->max_users;
1730 type = r->in.info->info2->type;
1731 break;
1732 case 501:
1733 /* No path. Not enough info in a level 501 to do anything. */
1734 return WERR_ACCESS_DENIED;
1735 case 502:
1736 share_name = talloc_strdup(ctx, r->in.info->info502->name);
1737 comment = talloc_strdup(ctx, r->in.info->info502->comment);
1738 pathname = talloc_strdup(ctx, r->in.info->info502->path);
1739 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
1740 0 : r->in.info->info502->max_users;
1741 type = r->in.info->info502->type;
1742 psd = r->in.info->info502->sd_buf.sd;
1743 map_generic_share_sd_bits(psd);
1744 break;
1746 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
1748 case 1004:
1749 case 1005:
1750 case 1006:
1751 case 1007:
1752 return WERR_ACCESS_DENIED;
1753 case 1501:
1754 /* DFS only level. */
1755 return WERR_ACCESS_DENIED;
1756 default:
1757 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
1758 r->in.level));
1759 return WERR_UNKNOWN_LEVEL;
1762 /* check for invalid share names */
1764 if (!share_name || !validate_net_name(share_name,
1765 INVALID_SHARENAME_CHARS,
1766 strlen(share_name))) {
1767 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
1768 share_name ? share_name : ""));
1769 return WERR_INVALID_NAME;
1772 if (strequal(share_name,"IPC$") || strequal(share_name,"global")
1773 || (lp_enable_asu_support() &&
1774 strequal(share_name,"ADMIN$"))) {
1775 return WERR_ACCESS_DENIED;
1778 snum = find_service(share_name);
1780 /* Share already exists. */
1781 if (snum >= 0) {
1782 return WERR_ALREADY_EXISTS;
1785 /* We can only add disk shares. */
1786 if (type != STYPE_DISKTREE) {
1787 return WERR_ACCESS_DENIED;
1790 /* Check if the pathname is valid. */
1791 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
1792 return WERR_OBJECT_PATH_INVALID;
1795 /* Ensure share name, pathname and comment don't contain '"' characters. */
1796 string_replace(share_name, '"', ' ');
1797 string_replace(path, '"', ' ');
1798 if (comment) {
1799 string_replace(comment, '"', ' ');
1802 command = talloc_asprintf(ctx,
1803 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1804 lp_add_share_cmd(),
1805 get_dyn_CONFIGFILE(),
1806 share_name,
1807 path,
1808 comment ? comment : "",
1809 max_connections);
1810 if (!command) {
1811 return WERR_NOMEM;
1814 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
1816 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1818 if ( is_disk_op )
1819 become_root();
1821 /* FIXME: use libnetconf here - gd */
1823 if ( (ret = smbrun(command, NULL)) == 0 ) {
1824 /* Tell everyone we updated smb.conf. */
1825 message_send_all(smbd_messaging_context(),
1826 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1829 if ( is_disk_op )
1830 unbecome_root();
1832 /********* END SeDiskOperatorPrivilege BLOCK *********/
1834 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
1835 command, ret ));
1837 TALLOC_FREE(command);
1839 if ( ret != 0 )
1840 return WERR_ACCESS_DENIED;
1842 if (psd) {
1843 if (!set_share_security(share_name, psd)) {
1844 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
1845 share_name ));
1850 * We don't call reload_services() here, the message will
1851 * cause this to be done before the next packet is read
1852 * from the client. JRA.
1855 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1857 return WERR_OK;
1860 /*******************************************************************
1861 _srvsvc_NetShareDel
1862 Call "delete share command" with the share name as
1863 a parameter.
1864 ********************************************************************/
1866 WERROR _srvsvc_NetShareDel(pipes_struct *p,
1867 struct srvsvc_NetShareDel *r)
1869 struct current_user user;
1870 char *command = NULL;
1871 char *share_name = NULL;
1872 int ret;
1873 int snum;
1874 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1875 bool is_disk_op;
1876 struct share_params *params;
1877 TALLOC_CTX *ctx = p->mem_ctx;
1879 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
1881 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1882 if (!share_name) {
1883 return WERR_NET_NAME_NOT_FOUND;
1885 if ( strequal(share_name,"IPC$")
1886 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1887 || strequal(share_name,"global") )
1889 return WERR_ACCESS_DENIED;
1892 if (!(params = get_share_params(p->mem_ctx, share_name))) {
1893 return WERR_NO_SUCH_SHARE;
1896 snum = find_service(share_name);
1898 /* No change to printer shares. */
1899 if (lp_print_ok(snum))
1900 return WERR_ACCESS_DENIED;
1902 get_current_user(&user,p);
1904 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1906 if (user.ut.uid != sec_initial_uid() && !is_disk_op )
1907 return WERR_ACCESS_DENIED;
1909 if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
1910 DEBUG(10,("_srvsvc_NetShareDel: No delete share command\n"));
1911 return WERR_ACCESS_DENIED;
1914 command = talloc_asprintf(ctx,
1915 "%s \"%s\" \"%s\"",
1916 lp_delete_share_cmd(),
1917 get_dyn_CONFIGFILE(),
1918 lp_servicename(snum));
1919 if (!command) {
1920 return WERR_NOMEM;
1923 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
1925 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1927 if ( is_disk_op )
1928 become_root();
1930 if ( (ret = smbrun(command, NULL)) == 0 ) {
1931 /* Tell everyone we updated smb.conf. */
1932 message_send_all(smbd_messaging_context(),
1933 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1936 if ( is_disk_op )
1937 unbecome_root();
1939 /********* END SeDiskOperatorPrivilege BLOCK *********/
1941 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
1943 if ( ret != 0 )
1944 return WERR_ACCESS_DENIED;
1946 /* Delete the SD in the database. */
1947 delete_share_security(lp_servicename(params->service));
1949 lp_killservice(params->service);
1951 return WERR_OK;
1954 /*******************************************************************
1955 _srvsvc_NetShareDelSticky
1956 ********************************************************************/
1958 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p,
1959 struct srvsvc_NetShareDelSticky *r)
1961 struct srvsvc_NetShareDel q;
1963 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
1965 q.in.server_unc = r->in.server_unc;
1966 q.in.share_name = r->in.share_name;
1967 q.in.reserved = r->in.reserved;
1969 return _srvsvc_NetShareDel(p, &q);
1972 /*******************************************************************
1973 _srvsvc_NetRemoteTOD
1974 ********************************************************************/
1976 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p,
1977 struct srvsvc_NetRemoteTOD *r)
1979 struct srvsvc_NetRemoteTODInfo *tod;
1980 struct tm *t;
1981 time_t unixdate = time(NULL);
1983 /* We do this call first as if we do it *after* the gmtime call
1984 it overwrites the pointed-to values. JRA */
1986 uint32 zone = get_time_zone(unixdate)/60;
1988 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
1990 if ( !(tod = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
1991 return WERR_NOMEM;
1993 *r->out.info = tod;
1995 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
1997 t = gmtime(&unixdate);
1999 /* set up the */
2000 init_srvsvc_NetRemoteTODInfo(tod,
2001 unixdate,
2003 t->tm_hour,
2004 t->tm_min,
2005 t->tm_sec,
2007 zone,
2008 10000,
2009 t->tm_mday,
2010 t->tm_mon + 1,
2011 1900+t->tm_year,
2012 t->tm_wday);
2014 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2016 return WERR_OK;
2019 /***********************************************************************************
2020 _srvsvc_NetGetFileSecurity
2021 Win9x NT tools get security descriptor.
2022 ***********************************************************************************/
2024 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p,
2025 struct srvsvc_NetGetFileSecurity *r)
2027 SEC_DESC *psd = NULL;
2028 size_t sd_size;
2029 fstring servicename;
2030 SMB_STRUCT_STAT st;
2031 NTSTATUS nt_status;
2032 WERROR werr;
2033 connection_struct *conn = NULL;
2034 struct sec_desc_buf *sd_buf = NULL;
2035 files_struct *fsp = NULL;
2036 int snum;
2037 char *oldcwd = NULL;
2039 ZERO_STRUCT(st);
2041 fstrcpy(servicename, r->in.share);
2043 snum = find_service(servicename);
2044 if (snum == -1) {
2045 DEBUG(10, ("Could not find service %s\n", servicename));
2046 werr = WERR_NET_NAME_NOT_FOUND;
2047 goto error_exit;
2050 nt_status = create_conn_struct(talloc_tos(), &conn, snum,
2051 lp_pathname(snum), &oldcwd);
2052 if (!NT_STATUS_IS_OK(nt_status)) {
2053 DEBUG(10, ("create_conn_struct failed: %s\n",
2054 nt_errstr(nt_status)));
2055 werr = ntstatus_to_werror(nt_status);
2056 goto error_exit;
2059 conn->server_info = p->server_info;
2061 nt_status = create_file(
2062 conn, /* conn */
2063 NULL, /* req */
2064 0, /* root_dir_fid */
2065 r->in.file, /* fname */
2066 FILE_READ_ATTRIBUTES, /* access_mask */
2067 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2068 FILE_OPEN, /* create_disposition*/
2069 0, /* create_options */
2070 0, /* file_attributes */
2071 INTERNAL_OPEN_ONLY, /* oplock_request */
2072 0, /* allocation_size */
2073 NULL, /* sd */
2074 NULL, /* ea_list */
2075 &fsp, /* result */
2076 NULL, /* pinfo */
2077 NULL); /* psbuf */
2079 if (!NT_STATUS_IS_OK(nt_status)) {
2080 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2081 r->in.file));
2082 werr = ntstatus_to_werror(nt_status);
2083 goto error_exit;
2086 nt_status = SMB_VFS_FGET_NT_ACL(fsp,
2087 (OWNER_SECURITY_INFORMATION
2088 |GROUP_SECURITY_INFORMATION
2089 |DACL_SECURITY_INFORMATION), &psd);
2091 if (!NT_STATUS_IS_OK(nt_status)) {
2092 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2093 "for file %s\n", r->in.file));
2094 werr = ntstatus_to_werror(nt_status);
2095 goto error_exit;
2098 sd_size = ndr_size_security_descriptor(psd, 0);
2100 sd_buf = TALLOC_ZERO_P(p->mem_ctx, struct sec_desc_buf);
2101 if (!sd_buf) {
2102 werr = WERR_NOMEM;
2103 goto error_exit;
2106 sd_buf->sd_size = sd_size;
2107 sd_buf->sd = psd;
2109 *r->out.sd_buf = sd_buf;
2111 psd->dacl->revision = NT4_ACL_REVISION;
2113 close_file(fsp, NORMAL_CLOSE);
2114 vfs_ChDir(conn, oldcwd);
2115 conn_free_internal(conn);
2116 return WERR_OK;
2118 error_exit:
2120 if (fsp) {
2121 close_file(fsp, NORMAL_CLOSE);
2124 if (oldcwd) {
2125 vfs_ChDir(conn, oldcwd);
2128 if (conn) {
2129 conn_free_internal(conn);
2132 return werr;
2135 /***********************************************************************************
2136 _srvsvc_NetSetFileSecurity
2137 Win9x NT tools set security descriptor.
2138 ***********************************************************************************/
2140 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p,
2141 struct srvsvc_NetSetFileSecurity *r)
2143 fstring servicename;
2144 files_struct *fsp = NULL;
2145 SMB_STRUCT_STAT st;
2146 NTSTATUS nt_status;
2147 WERROR werr;
2148 connection_struct *conn = NULL;
2149 int snum;
2150 char *oldcwd = NULL;
2152 ZERO_STRUCT(st);
2154 fstrcpy(servicename, r->in.share);
2156 snum = find_service(servicename);
2157 if (snum == -1) {
2158 DEBUG(10, ("Could not find service %s\n", servicename));
2159 werr = WERR_NET_NAME_NOT_FOUND;
2160 goto error_exit;
2163 nt_status = create_conn_struct(talloc_tos(), &conn, snum,
2164 lp_pathname(snum), &oldcwd);
2165 if (!NT_STATUS_IS_OK(nt_status)) {
2166 DEBUG(10, ("create_conn_struct failed: %s\n",
2167 nt_errstr(nt_status)));
2168 werr = ntstatus_to_werror(nt_status);
2169 goto error_exit;
2172 conn->server_info = p->server_info;
2174 nt_status = create_file(
2175 conn, /* conn */
2176 NULL, /* req */
2177 0, /* root_dir_fid */
2178 r->in.file, /* fname */
2179 FILE_WRITE_ATTRIBUTES, /* access_mask */
2180 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2181 FILE_OPEN, /* create_disposition*/
2182 0, /* create_options */
2183 0, /* file_attributes */
2184 INTERNAL_OPEN_ONLY, /* oplock_request */
2185 0, /* allocation_size */
2186 NULL, /* sd */
2187 NULL, /* ea_list */
2188 &fsp, /* result */
2189 NULL, /* pinfo */
2190 NULL); /* psbuf */
2192 if (!NT_STATUS_IS_OK(nt_status)) {
2193 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2194 r->in.file));
2195 werr = ntstatus_to_werror(nt_status);
2196 goto error_exit;
2199 nt_status = SMB_VFS_FSET_NT_ACL(fsp,
2200 r->in.securityinformation,
2201 r->in.sd_buf->sd);
2203 if (!NT_STATUS_IS_OK(nt_status) ) {
2204 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2205 "on file %s\n", r->in.share));
2206 werr = WERR_ACCESS_DENIED;
2207 goto error_exit;
2210 close_file(fsp, NORMAL_CLOSE);
2211 vfs_ChDir(conn, oldcwd);
2212 conn_free_internal(conn);
2213 return WERR_OK;
2215 error_exit:
2217 if (fsp) {
2218 close_file(fsp, NORMAL_CLOSE);
2221 if (oldcwd) {
2222 vfs_ChDir(conn, oldcwd);
2225 if (conn) {
2226 conn_free_internal(conn);
2229 return werr;
2232 /***********************************************************************************
2233 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2234 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2235 These disks would the disks listed by this function.
2236 Users could then create shares relative to these disks. Watch out for moving these disks around.
2237 "Nigel Williams" <nigel@veritas.com>.
2238 ***********************************************************************************/
2240 static const char *server_disks[] = {"C:"};
2242 static uint32 get_server_disk_count(void)
2244 return sizeof(server_disks)/sizeof(server_disks[0]);
2247 static uint32 init_server_disk_enum(uint32 *resume)
2249 uint32 server_disk_count = get_server_disk_count();
2251 /*resume can be an offset into the list for now*/
2253 if(*resume & 0x80000000)
2254 *resume = 0;
2256 if(*resume > server_disk_count)
2257 *resume = server_disk_count;
2259 return server_disk_count - *resume;
2262 static const char *next_server_disk_enum(uint32 *resume)
2264 const char *disk;
2266 if(init_server_disk_enum(resume) == 0)
2267 return NULL;
2269 disk = server_disks[*resume];
2271 (*resume)++;
2273 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2275 return disk;
2278 /********************************************************************
2279 _srvsvc_NetDiskEnum
2280 ********************************************************************/
2282 WERROR _srvsvc_NetDiskEnum(pipes_struct *p,
2283 struct srvsvc_NetDiskEnum *r)
2285 uint32 i;
2286 const char *disk_name;
2287 TALLOC_CTX *ctx = p->mem_ctx;
2288 WERROR werr;
2289 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2291 werr = WERR_OK;
2293 *r->out.totalentries = init_server_disk_enum(&resume);
2295 r->out.info->disks = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetDiskInfo0,
2296 MAX_SERVER_DISK_ENTRIES);
2297 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2299 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2301 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2303 r->out.info->count++;
2305 /*copy disk name into a unicode string*/
2307 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2308 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2311 /* add a terminating null string. Is this there if there is more data to come? */
2313 r->out.info->count++;
2315 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2316 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2318 if (r->out.resume_handle) {
2319 *r->out.resume_handle = resume;
2322 return werr;
2325 /********************************************************************
2326 _srvsvc_NetNameValidate
2327 ********************************************************************/
2329 WERROR _srvsvc_NetNameValidate(pipes_struct *p,
2330 struct srvsvc_NetNameValidate *r)
2332 switch (r->in.name_type) {
2333 case 0x9:
2334 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2335 strlen_m(r->in.name)))
2337 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2338 r->in.name));
2339 return WERR_INVALID_NAME;
2341 break;
2343 default:
2344 return WERR_UNKNOWN_LEVEL;
2347 return WERR_OK;
2350 /*******************************************************************
2351 ********************************************************************/
2353 static void enum_file_close_fn( const struct share_mode_entry *e,
2354 const char *sharepath, const char *fname,
2355 void *private_data )
2357 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2358 struct srvsvc_NetFileClose *r =
2359 (struct srvsvc_NetFileClose *)private_data;
2360 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2362 if (fid != r->in.fid) {
2363 return; /* Not this file. */
2366 if (!process_exists(e->pid) ) {
2367 return;
2370 /* Ok - send the close message. */
2371 DEBUG(10,("enum_file_close_fn: request to close file %s, %s\n",
2372 sharepath,
2373 share_mode_str(talloc_tos(), 0, e) ));
2375 share_mode_entry_to_message(msg, e);
2377 r->out.result = ntstatus_to_werror(
2378 messaging_send_buf(smbd_messaging_context(),
2379 e->pid, MSG_SMB_CLOSE_FILE,
2380 (uint8 *)msg,
2381 MSG_SMB_SHARE_MODE_ENTRY_SIZE));
2384 /********************************************************************
2385 Close a file given a 32-bit file id.
2386 ********************************************************************/
2388 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2390 struct current_user user;
2391 SE_PRIV se_diskop = SE_DISK_OPERATOR;
2392 bool is_disk_op;
2394 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2396 get_current_user(&user,p);
2398 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
2400 if (user.ut.uid != sec_initial_uid() && !is_disk_op) {
2401 return WERR_ACCESS_DENIED;
2404 /* enum_file_close_fn sends the close message to
2405 * the relevent smbd process. */
2407 r->out.result = WERR_BADFILE;
2408 share_mode_forall( enum_file_close_fn, (void *)r);
2409 return r->out.result;
2412 /********************************************************************
2413 ********************************************************************/
2415 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2417 p->rng_fault_state = True;
2418 return WERR_NOT_SUPPORTED;
2421 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2423 p->rng_fault_state = True;
2424 return WERR_NOT_SUPPORTED;
2427 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2429 p->rng_fault_state = True;
2430 return WERR_NOT_SUPPORTED;
2433 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2435 p->rng_fault_state = True;
2436 return WERR_NOT_SUPPORTED;
2439 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2441 p->rng_fault_state = True;
2442 return WERR_NOT_SUPPORTED;
2445 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2447 p->rng_fault_state = True;
2448 return WERR_NOT_SUPPORTED;
2451 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2453 p->rng_fault_state = True;
2454 return WERR_NOT_SUPPORTED;
2457 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2459 p->rng_fault_state = True;
2460 return WERR_NOT_SUPPORTED;
2463 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2465 p->rng_fault_state = True;
2466 return WERR_NOT_SUPPORTED;
2469 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2471 p->rng_fault_state = True;
2472 return WERR_NOT_SUPPORTED;
2475 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2477 p->rng_fault_state = True;
2478 return WERR_NOT_SUPPORTED;
2481 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2483 p->rng_fault_state = True;
2484 return WERR_NOT_SUPPORTED;
2487 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2489 p->rng_fault_state = True;
2490 return WERR_NOT_SUPPORTED;
2493 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2495 p->rng_fault_state = True;
2496 return WERR_NOT_SUPPORTED;
2499 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2501 p->rng_fault_state = True;
2502 return WERR_NOT_SUPPORTED;
2505 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2507 p->rng_fault_state = True;
2508 return WERR_NOT_SUPPORTED;
2511 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2513 p->rng_fault_state = True;
2514 return WERR_NOT_SUPPORTED;
2517 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2519 p->rng_fault_state = True;
2520 return WERR_NOT_SUPPORTED;
2523 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2525 p->rng_fault_state = True;
2526 return WERR_NOT_SUPPORTED;
2529 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2531 p->rng_fault_state = True;
2532 return WERR_NOT_SUPPORTED;
2535 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2537 p->rng_fault_state = True;
2538 return WERR_NOT_SUPPORTED;
2541 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2543 p->rng_fault_state = True;
2544 return WERR_NOT_SUPPORTED;
2547 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2549 p->rng_fault_state = True;
2550 return WERR_NOT_SUPPORTED;
2553 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2555 p->rng_fault_state = True;
2556 return WERR_NOT_SUPPORTED;
2559 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2561 p->rng_fault_state = True;
2562 return WERR_NOT_SUPPORTED;
2565 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2567 p->rng_fault_state = True;
2568 return WERR_NOT_SUPPORTED;
2571 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2573 p->rng_fault_state = True;
2574 return WERR_NOT_SUPPORTED;
2577 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
2579 p->rng_fault_state = True;
2580 return WERR_NOT_SUPPORTED;
2583 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2585 p->rng_fault_state = True;
2586 return WERR_NOT_SUPPORTED;
2589 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2591 p->rng_fault_state = True;
2592 return WERR_NOT_SUPPORTED;
2595 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2597 p->rng_fault_state = True;
2598 return WERR_NOT_SUPPORTED;
2601 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2603 p->rng_fault_state = True;
2604 return WERR_NOT_SUPPORTED;
2607 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2609 p->rng_fault_state = True;
2610 return WERR_NOT_SUPPORTED;
2613 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2615 p->rng_fault_state = True;
2616 return WERR_NOT_SUPPORTED;
2619 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2621 p->rng_fault_state = True;
2622 return WERR_NOT_SUPPORTED;