s3-srvsvc: fix _srvsvc_NetShareAdd segfault.
[Samba.git] / source / rpc_server / srv_srvsvc_nt.c
blobfb7478653d09f131ef8c9fe620e247d3229ca828
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 if (r->out.parm_error) {
1704 *r->out.parm_error = 0;
1707 get_current_user(&user,p);
1709 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1711 if (user.ut.uid != sec_initial_uid() && !is_disk_op )
1712 return WERR_ACCESS_DENIED;
1714 if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
1715 DEBUG(10,("_srvsvc_NetShareAdd: No add share command\n"));
1716 return WERR_ACCESS_DENIED;
1719 switch (r->in.level) {
1720 case 0:
1721 /* No path. Not enough info in a level 0 to do anything. */
1722 return WERR_ACCESS_DENIED;
1723 case 1:
1724 /* Not enough info in a level 1 to do anything. */
1725 return WERR_ACCESS_DENIED;
1726 case 2:
1727 share_name = talloc_strdup(ctx, r->in.info->info2->name);
1728 comment = talloc_strdup(ctx, r->in.info->info2->comment);
1729 pathname = talloc_strdup(ctx, r->in.info->info2->path);
1730 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
1731 0 : r->in.info->info2->max_users;
1732 type = r->in.info->info2->type;
1733 break;
1734 case 501:
1735 /* No path. Not enough info in a level 501 to do anything. */
1736 return WERR_ACCESS_DENIED;
1737 case 502:
1738 share_name = talloc_strdup(ctx, r->in.info->info502->name);
1739 comment = talloc_strdup(ctx, r->in.info->info502->comment);
1740 pathname = talloc_strdup(ctx, r->in.info->info502->path);
1741 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
1742 0 : r->in.info->info502->max_users;
1743 type = r->in.info->info502->type;
1744 psd = r->in.info->info502->sd_buf.sd;
1745 map_generic_share_sd_bits(psd);
1746 break;
1748 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
1750 case 1004:
1751 case 1005:
1752 case 1006:
1753 case 1007:
1754 return WERR_ACCESS_DENIED;
1755 case 1501:
1756 /* DFS only level. */
1757 return WERR_ACCESS_DENIED;
1758 default:
1759 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
1760 r->in.level));
1761 return WERR_UNKNOWN_LEVEL;
1764 /* check for invalid share names */
1766 if (!share_name || !validate_net_name(share_name,
1767 INVALID_SHARENAME_CHARS,
1768 strlen(share_name))) {
1769 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
1770 share_name ? share_name : ""));
1771 return WERR_INVALID_NAME;
1774 if (strequal(share_name,"IPC$") || strequal(share_name,"global")
1775 || (lp_enable_asu_support() &&
1776 strequal(share_name,"ADMIN$"))) {
1777 return WERR_ACCESS_DENIED;
1780 snum = find_service(share_name);
1782 /* Share already exists. */
1783 if (snum >= 0) {
1784 return WERR_ALREADY_EXISTS;
1787 /* We can only add disk shares. */
1788 if (type != STYPE_DISKTREE) {
1789 return WERR_ACCESS_DENIED;
1792 /* Check if the pathname is valid. */
1793 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
1794 return WERR_OBJECT_PATH_INVALID;
1797 /* Ensure share name, pathname and comment don't contain '"' characters. */
1798 string_replace(share_name, '"', ' ');
1799 string_replace(path, '"', ' ');
1800 if (comment) {
1801 string_replace(comment, '"', ' ');
1804 command = talloc_asprintf(ctx,
1805 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1806 lp_add_share_cmd(),
1807 get_dyn_CONFIGFILE(),
1808 share_name,
1809 path,
1810 comment ? comment : "",
1811 max_connections);
1812 if (!command) {
1813 return WERR_NOMEM;
1816 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
1818 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1820 if ( is_disk_op )
1821 become_root();
1823 /* FIXME: use libnetconf here - gd */
1825 if ( (ret = smbrun(command, NULL)) == 0 ) {
1826 /* Tell everyone we updated smb.conf. */
1827 message_send_all(smbd_messaging_context(),
1828 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1831 if ( is_disk_op )
1832 unbecome_root();
1834 /********* END SeDiskOperatorPrivilege BLOCK *********/
1836 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
1837 command, ret ));
1839 TALLOC_FREE(command);
1841 if ( ret != 0 )
1842 return WERR_ACCESS_DENIED;
1844 if (psd) {
1845 if (!set_share_security(share_name, psd)) {
1846 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
1847 share_name ));
1852 * We don't call reload_services() here, the message will
1853 * cause this to be done before the next packet is read
1854 * from the client. JRA.
1857 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1859 return WERR_OK;
1862 /*******************************************************************
1863 _srvsvc_NetShareDel
1864 Call "delete share command" with the share name as
1865 a parameter.
1866 ********************************************************************/
1868 WERROR _srvsvc_NetShareDel(pipes_struct *p,
1869 struct srvsvc_NetShareDel *r)
1871 struct current_user user;
1872 char *command = NULL;
1873 char *share_name = NULL;
1874 int ret;
1875 int snum;
1876 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1877 bool is_disk_op;
1878 struct share_params *params;
1879 TALLOC_CTX *ctx = p->mem_ctx;
1881 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
1883 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1884 if (!share_name) {
1885 return WERR_NET_NAME_NOT_FOUND;
1887 if ( strequal(share_name,"IPC$")
1888 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1889 || strequal(share_name,"global") )
1891 return WERR_ACCESS_DENIED;
1894 if (!(params = get_share_params(p->mem_ctx, share_name))) {
1895 return WERR_NO_SUCH_SHARE;
1898 snum = find_service(share_name);
1900 /* No change to printer shares. */
1901 if (lp_print_ok(snum))
1902 return WERR_ACCESS_DENIED;
1904 get_current_user(&user,p);
1906 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1908 if (user.ut.uid != sec_initial_uid() && !is_disk_op )
1909 return WERR_ACCESS_DENIED;
1911 if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
1912 DEBUG(10,("_srvsvc_NetShareDel: No delete share command\n"));
1913 return WERR_ACCESS_DENIED;
1916 command = talloc_asprintf(ctx,
1917 "%s \"%s\" \"%s\"",
1918 lp_delete_share_cmd(),
1919 get_dyn_CONFIGFILE(),
1920 lp_servicename(snum));
1921 if (!command) {
1922 return WERR_NOMEM;
1925 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
1927 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1929 if ( is_disk_op )
1930 become_root();
1932 if ( (ret = smbrun(command, NULL)) == 0 ) {
1933 /* Tell everyone we updated smb.conf. */
1934 message_send_all(smbd_messaging_context(),
1935 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1938 if ( is_disk_op )
1939 unbecome_root();
1941 /********* END SeDiskOperatorPrivilege BLOCK *********/
1943 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
1945 if ( ret != 0 )
1946 return WERR_ACCESS_DENIED;
1948 /* Delete the SD in the database. */
1949 delete_share_security(lp_servicename(params->service));
1951 lp_killservice(params->service);
1953 return WERR_OK;
1956 /*******************************************************************
1957 _srvsvc_NetShareDelSticky
1958 ********************************************************************/
1960 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p,
1961 struct srvsvc_NetShareDelSticky *r)
1963 struct srvsvc_NetShareDel q;
1965 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
1967 q.in.server_unc = r->in.server_unc;
1968 q.in.share_name = r->in.share_name;
1969 q.in.reserved = r->in.reserved;
1971 return _srvsvc_NetShareDel(p, &q);
1974 /*******************************************************************
1975 _srvsvc_NetRemoteTOD
1976 ********************************************************************/
1978 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p,
1979 struct srvsvc_NetRemoteTOD *r)
1981 struct srvsvc_NetRemoteTODInfo *tod;
1982 struct tm *t;
1983 time_t unixdate = time(NULL);
1985 /* We do this call first as if we do it *after* the gmtime call
1986 it overwrites the pointed-to values. JRA */
1988 uint32 zone = get_time_zone(unixdate)/60;
1990 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
1992 if ( !(tod = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
1993 return WERR_NOMEM;
1995 *r->out.info = tod;
1997 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
1999 t = gmtime(&unixdate);
2001 /* set up the */
2002 init_srvsvc_NetRemoteTODInfo(tod,
2003 unixdate,
2005 t->tm_hour,
2006 t->tm_min,
2007 t->tm_sec,
2009 zone,
2010 10000,
2011 t->tm_mday,
2012 t->tm_mon + 1,
2013 1900+t->tm_year,
2014 t->tm_wday);
2016 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2018 return WERR_OK;
2021 /***********************************************************************************
2022 _srvsvc_NetGetFileSecurity
2023 Win9x NT tools get security descriptor.
2024 ***********************************************************************************/
2026 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p,
2027 struct srvsvc_NetGetFileSecurity *r)
2029 SEC_DESC *psd = NULL;
2030 size_t sd_size;
2031 fstring servicename;
2032 SMB_STRUCT_STAT st;
2033 NTSTATUS nt_status;
2034 WERROR werr;
2035 connection_struct *conn = NULL;
2036 struct sec_desc_buf *sd_buf = NULL;
2037 files_struct *fsp = NULL;
2038 int snum;
2039 char *oldcwd = NULL;
2041 ZERO_STRUCT(st);
2043 fstrcpy(servicename, r->in.share);
2045 snum = find_service(servicename);
2046 if (snum == -1) {
2047 DEBUG(10, ("Could not find service %s\n", servicename));
2048 werr = WERR_NET_NAME_NOT_FOUND;
2049 goto error_exit;
2052 nt_status = create_conn_struct(talloc_tos(), &conn, snum,
2053 lp_pathname(snum), &oldcwd);
2054 if (!NT_STATUS_IS_OK(nt_status)) {
2055 DEBUG(10, ("create_conn_struct failed: %s\n",
2056 nt_errstr(nt_status)));
2057 werr = ntstatus_to_werror(nt_status);
2058 goto error_exit;
2061 conn->server_info = p->server_info;
2063 nt_status = create_file(
2064 conn, /* conn */
2065 NULL, /* req */
2066 0, /* root_dir_fid */
2067 r->in.file, /* fname */
2068 FILE_READ_ATTRIBUTES, /* access_mask */
2069 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2070 FILE_OPEN, /* create_disposition*/
2071 0, /* create_options */
2072 0, /* file_attributes */
2073 INTERNAL_OPEN_ONLY, /* oplock_request */
2074 0, /* allocation_size */
2075 NULL, /* sd */
2076 NULL, /* ea_list */
2077 &fsp, /* result */
2078 NULL, /* pinfo */
2079 NULL); /* psbuf */
2081 if (!NT_STATUS_IS_OK(nt_status)) {
2082 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2083 r->in.file));
2084 werr = ntstatus_to_werror(nt_status);
2085 goto error_exit;
2088 nt_status = SMB_VFS_FGET_NT_ACL(fsp,
2089 (OWNER_SECURITY_INFORMATION
2090 |GROUP_SECURITY_INFORMATION
2091 |DACL_SECURITY_INFORMATION), &psd);
2093 if (!NT_STATUS_IS_OK(nt_status)) {
2094 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2095 "for file %s\n", r->in.file));
2096 werr = ntstatus_to_werror(nt_status);
2097 goto error_exit;
2100 sd_size = ndr_size_security_descriptor(psd, 0);
2102 sd_buf = TALLOC_ZERO_P(p->mem_ctx, struct sec_desc_buf);
2103 if (!sd_buf) {
2104 werr = WERR_NOMEM;
2105 goto error_exit;
2108 sd_buf->sd_size = sd_size;
2109 sd_buf->sd = psd;
2111 *r->out.sd_buf = sd_buf;
2113 psd->dacl->revision = NT4_ACL_REVISION;
2115 close_file(fsp, NORMAL_CLOSE);
2116 vfs_ChDir(conn, oldcwd);
2117 conn_free_internal(conn);
2118 return WERR_OK;
2120 error_exit:
2122 if (fsp) {
2123 close_file(fsp, NORMAL_CLOSE);
2126 if (oldcwd) {
2127 vfs_ChDir(conn, oldcwd);
2130 if (conn) {
2131 conn_free_internal(conn);
2134 return werr;
2137 /***********************************************************************************
2138 _srvsvc_NetSetFileSecurity
2139 Win9x NT tools set security descriptor.
2140 ***********************************************************************************/
2142 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p,
2143 struct srvsvc_NetSetFileSecurity *r)
2145 fstring servicename;
2146 files_struct *fsp = NULL;
2147 SMB_STRUCT_STAT st;
2148 NTSTATUS nt_status;
2149 WERROR werr;
2150 connection_struct *conn = NULL;
2151 int snum;
2152 char *oldcwd = NULL;
2154 ZERO_STRUCT(st);
2156 fstrcpy(servicename, r->in.share);
2158 snum = find_service(servicename);
2159 if (snum == -1) {
2160 DEBUG(10, ("Could not find service %s\n", servicename));
2161 werr = WERR_NET_NAME_NOT_FOUND;
2162 goto error_exit;
2165 nt_status = create_conn_struct(talloc_tos(), &conn, snum,
2166 lp_pathname(snum), &oldcwd);
2167 if (!NT_STATUS_IS_OK(nt_status)) {
2168 DEBUG(10, ("create_conn_struct failed: %s\n",
2169 nt_errstr(nt_status)));
2170 werr = ntstatus_to_werror(nt_status);
2171 goto error_exit;
2174 conn->server_info = p->server_info;
2176 nt_status = create_file(
2177 conn, /* conn */
2178 NULL, /* req */
2179 0, /* root_dir_fid */
2180 r->in.file, /* fname */
2181 FILE_WRITE_ATTRIBUTES, /* access_mask */
2182 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2183 FILE_OPEN, /* create_disposition*/
2184 0, /* create_options */
2185 0, /* file_attributes */
2186 INTERNAL_OPEN_ONLY, /* oplock_request */
2187 0, /* allocation_size */
2188 NULL, /* sd */
2189 NULL, /* ea_list */
2190 &fsp, /* result */
2191 NULL, /* pinfo */
2192 NULL); /* psbuf */
2194 if (!NT_STATUS_IS_OK(nt_status)) {
2195 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2196 r->in.file));
2197 werr = ntstatus_to_werror(nt_status);
2198 goto error_exit;
2201 nt_status = SMB_VFS_FSET_NT_ACL(fsp,
2202 r->in.securityinformation,
2203 r->in.sd_buf->sd);
2205 if (!NT_STATUS_IS_OK(nt_status) ) {
2206 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2207 "on file %s\n", r->in.share));
2208 werr = WERR_ACCESS_DENIED;
2209 goto error_exit;
2212 close_file(fsp, NORMAL_CLOSE);
2213 vfs_ChDir(conn, oldcwd);
2214 conn_free_internal(conn);
2215 return WERR_OK;
2217 error_exit:
2219 if (fsp) {
2220 close_file(fsp, NORMAL_CLOSE);
2223 if (oldcwd) {
2224 vfs_ChDir(conn, oldcwd);
2227 if (conn) {
2228 conn_free_internal(conn);
2231 return werr;
2234 /***********************************************************************************
2235 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2236 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2237 These disks would the disks listed by this function.
2238 Users could then create shares relative to these disks. Watch out for moving these disks around.
2239 "Nigel Williams" <nigel@veritas.com>.
2240 ***********************************************************************************/
2242 static const char *server_disks[] = {"C:"};
2244 static uint32 get_server_disk_count(void)
2246 return sizeof(server_disks)/sizeof(server_disks[0]);
2249 static uint32 init_server_disk_enum(uint32 *resume)
2251 uint32 server_disk_count = get_server_disk_count();
2253 /*resume can be an offset into the list for now*/
2255 if(*resume & 0x80000000)
2256 *resume = 0;
2258 if(*resume > server_disk_count)
2259 *resume = server_disk_count;
2261 return server_disk_count - *resume;
2264 static const char *next_server_disk_enum(uint32 *resume)
2266 const char *disk;
2268 if(init_server_disk_enum(resume) == 0)
2269 return NULL;
2271 disk = server_disks[*resume];
2273 (*resume)++;
2275 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2277 return disk;
2280 /********************************************************************
2281 _srvsvc_NetDiskEnum
2282 ********************************************************************/
2284 WERROR _srvsvc_NetDiskEnum(pipes_struct *p,
2285 struct srvsvc_NetDiskEnum *r)
2287 uint32 i;
2288 const char *disk_name;
2289 TALLOC_CTX *ctx = p->mem_ctx;
2290 WERROR werr;
2291 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2293 werr = WERR_OK;
2295 *r->out.totalentries = init_server_disk_enum(&resume);
2297 r->out.info->disks = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetDiskInfo0,
2298 MAX_SERVER_DISK_ENTRIES);
2299 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2301 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2303 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2305 r->out.info->count++;
2307 /*copy disk name into a unicode string*/
2309 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2310 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2313 /* add a terminating null string. Is this there if there is more data to come? */
2315 r->out.info->count++;
2317 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2318 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2320 if (r->out.resume_handle) {
2321 *r->out.resume_handle = resume;
2324 return werr;
2327 /********************************************************************
2328 _srvsvc_NetNameValidate
2329 ********************************************************************/
2331 WERROR _srvsvc_NetNameValidate(pipes_struct *p,
2332 struct srvsvc_NetNameValidate *r)
2334 switch (r->in.name_type) {
2335 case 0x9:
2336 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2337 strlen_m(r->in.name)))
2339 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2340 r->in.name));
2341 return WERR_INVALID_NAME;
2343 break;
2345 default:
2346 return WERR_UNKNOWN_LEVEL;
2349 return WERR_OK;
2352 /*******************************************************************
2353 ********************************************************************/
2355 static void enum_file_close_fn( const struct share_mode_entry *e,
2356 const char *sharepath, const char *fname,
2357 void *private_data )
2359 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2360 struct srvsvc_NetFileClose *r =
2361 (struct srvsvc_NetFileClose *)private_data;
2362 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2364 if (fid != r->in.fid) {
2365 return; /* Not this file. */
2368 if (!process_exists(e->pid) ) {
2369 return;
2372 /* Ok - send the close message. */
2373 DEBUG(10,("enum_file_close_fn: request to close file %s, %s\n",
2374 sharepath,
2375 share_mode_str(talloc_tos(), 0, e) ));
2377 share_mode_entry_to_message(msg, e);
2379 r->out.result = ntstatus_to_werror(
2380 messaging_send_buf(smbd_messaging_context(),
2381 e->pid, MSG_SMB_CLOSE_FILE,
2382 (uint8 *)msg,
2383 MSG_SMB_SHARE_MODE_ENTRY_SIZE));
2386 /********************************************************************
2387 Close a file given a 32-bit file id.
2388 ********************************************************************/
2390 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2392 struct current_user user;
2393 SE_PRIV se_diskop = SE_DISK_OPERATOR;
2394 bool is_disk_op;
2396 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2398 get_current_user(&user,p);
2400 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
2402 if (user.ut.uid != sec_initial_uid() && !is_disk_op) {
2403 return WERR_ACCESS_DENIED;
2406 /* enum_file_close_fn sends the close message to
2407 * the relevent smbd process. */
2409 r->out.result = WERR_BADFILE;
2410 share_mode_forall( enum_file_close_fn, (void *)r);
2411 return r->out.result;
2414 /********************************************************************
2415 ********************************************************************/
2417 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2419 p->rng_fault_state = True;
2420 return WERR_NOT_SUPPORTED;
2423 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2425 p->rng_fault_state = True;
2426 return WERR_NOT_SUPPORTED;
2429 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2431 p->rng_fault_state = True;
2432 return WERR_NOT_SUPPORTED;
2435 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2437 p->rng_fault_state = True;
2438 return WERR_NOT_SUPPORTED;
2441 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2443 p->rng_fault_state = True;
2444 return WERR_NOT_SUPPORTED;
2447 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2449 p->rng_fault_state = True;
2450 return WERR_NOT_SUPPORTED;
2453 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2455 p->rng_fault_state = True;
2456 return WERR_NOT_SUPPORTED;
2459 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2461 p->rng_fault_state = True;
2462 return WERR_NOT_SUPPORTED;
2465 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2467 p->rng_fault_state = True;
2468 return WERR_NOT_SUPPORTED;
2471 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2473 p->rng_fault_state = True;
2474 return WERR_NOT_SUPPORTED;
2477 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2479 p->rng_fault_state = True;
2480 return WERR_NOT_SUPPORTED;
2483 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2485 p->rng_fault_state = True;
2486 return WERR_NOT_SUPPORTED;
2489 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2491 p->rng_fault_state = True;
2492 return WERR_NOT_SUPPORTED;
2495 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2497 p->rng_fault_state = True;
2498 return WERR_NOT_SUPPORTED;
2501 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2503 p->rng_fault_state = True;
2504 return WERR_NOT_SUPPORTED;
2507 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2509 p->rng_fault_state = True;
2510 return WERR_NOT_SUPPORTED;
2513 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2515 p->rng_fault_state = True;
2516 return WERR_NOT_SUPPORTED;
2519 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2521 p->rng_fault_state = True;
2522 return WERR_NOT_SUPPORTED;
2525 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2527 p->rng_fault_state = True;
2528 return WERR_NOT_SUPPORTED;
2531 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2533 p->rng_fault_state = True;
2534 return WERR_NOT_SUPPORTED;
2537 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2539 p->rng_fault_state = True;
2540 return WERR_NOT_SUPPORTED;
2543 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2545 p->rng_fault_state = True;
2546 return WERR_NOT_SUPPORTED;
2549 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2551 p->rng_fault_state = True;
2552 return WERR_NOT_SUPPORTED;
2555 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2557 p->rng_fault_state = True;
2558 return WERR_NOT_SUPPORTED;
2561 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2563 p->rng_fault_state = True;
2564 return WERR_NOT_SUPPORTED;
2567 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2569 p->rng_fault_state = True;
2570 return WERR_NOT_SUPPORTED;
2573 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2575 p->rng_fault_state = True;
2576 return WERR_NOT_SUPPORTED;
2579 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
2581 p->rng_fault_state = True;
2582 return WERR_NOT_SUPPORTED;
2585 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2587 p->rng_fault_state = True;
2588 return WERR_NOT_SUPPORTED;
2591 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2593 p->rng_fault_state = True;
2594 return WERR_NOT_SUPPORTED;
2597 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2599 p->rng_fault_state = True;
2600 return WERR_NOT_SUPPORTED;
2603 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2605 p->rng_fault_state = True;
2606 return WERR_NOT_SUPPORTED;
2609 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2611 p->rng_fault_state = True;
2612 return WERR_NOT_SUPPORTED;
2615 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2617 p->rng_fault_state = True;
2618 return WERR_NOT_SUPPORTED;
2621 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2623 p->rng_fault_state = True;
2624 return WERR_NOT_SUPPORTED;