s3: Add an async smbsock_connect
[Samba.git] / source3 / rpc_server / srv_srvsvc_nt.c
blobd8c0ce6d429c80cf85c58b539053193f2fdcef7f
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 fenum->ctr3->array[i].fid =
92 (((uint32_t)(procid_to_pid(&prec.pid))<<16) | prec.pnum);
93 fenum->ctr3->array[i].permissions =
94 (FILE_READ_DATA|FILE_WRITE_DATA);
95 fenum->ctr3->array[i].num_locks = 0;
96 fenum->ctr3->array[i].path = fullpath;
97 fenum->ctr3->array[i].user = username;
99 fenum->ctr3->count++;
101 return 0;
104 /*******************************************************************
105 ********************************************************************/
107 static WERROR net_enum_pipes(TALLOC_CTX *ctx,
108 const char *username,
109 struct srvsvc_NetFileCtr3 **ctr3,
110 uint32_t resume )
112 struct file_enum_count fenum;
114 fenum.ctx = ctx;
115 fenum.username = username;
116 fenum.ctr3 = *ctr3;
118 if (connections_traverse(pipe_enum_fn, &fenum) == -1) {
119 DEBUG(0,("net_enum_pipes: traverse of connections.tdb "
120 "failed\n"));
121 return WERR_NOMEM;
124 *ctr3 = fenum.ctr3;
126 return WERR_OK;
129 /*******************************************************************
130 ********************************************************************/
132 static void enum_file_fn( const struct share_mode_entry *e,
133 const char *sharepath, const char *fname,
134 void *private_data )
136 struct file_enum_count *fenum =
137 (struct file_enum_count *)private_data;
139 struct srvsvc_NetFileInfo3 *f;
140 int i = fenum->ctr3->count;
141 files_struct fsp;
142 struct byte_range_lock *brl;
143 int num_locks = 0;
144 char *fullpath = NULL;
145 uint32 permissions;
146 const char *username;
148 /* If the pid was not found delete the entry from connections.tdb */
150 if ( !process_exists(e->pid) ) {
151 return;
154 username = uidtoname(e->uid);
156 if ((fenum->username != NULL)
157 && !strequal(username, fenum->username)) {
158 return;
161 f = TALLOC_REALLOC_ARRAY(fenum->ctx, fenum->ctr3->array,
162 struct srvsvc_NetFileInfo3, i+1);
163 if ( !f ) {
164 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
165 return;
167 fenum->ctr3->array = f;
169 /* need to count the number of locks on a file */
171 ZERO_STRUCT( fsp );
172 fsp.file_id = e->id;
174 if ( (brl = brl_get_locks(talloc_tos(), &fsp)) != NULL ) {
175 num_locks = brl->num_locks;
176 TALLOC_FREE(brl);
179 if ( strcmp( fname, "." ) == 0 ) {
180 fullpath = talloc_asprintf(fenum->ctx, "C:%s", sharepath );
181 } else {
182 fullpath = talloc_asprintf(fenum->ctx, "C:%s/%s",
183 sharepath, fname );
185 if (!fullpath) {
186 return;
188 string_replace( fullpath, '/', '\\' );
190 /* mask out create (what ever that is) */
191 permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
193 /* now fill in the srvsvc_NetFileInfo3 struct */
195 fenum->ctr3->array[i].fid =
196 (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
197 fenum->ctr3->array[i].permissions = permissions;
198 fenum->ctr3->array[i].num_locks = num_locks;
199 fenum->ctr3->array[i].path = fullpath;
200 fenum->ctr3->array[i].user = username;
202 fenum->ctr3->count++;
205 /*******************************************************************
206 ********************************************************************/
208 static WERROR net_enum_files(TALLOC_CTX *ctx,
209 const char *username,
210 struct srvsvc_NetFileCtr3 **ctr3,
211 uint32_t resume)
213 struct file_enum_count f_enum_cnt;
215 f_enum_cnt.ctx = ctx;
216 f_enum_cnt.username = username;
217 f_enum_cnt.ctr3 = *ctr3;
219 share_mode_forall( enum_file_fn, (void *)&f_enum_cnt );
221 *ctr3 = f_enum_cnt.ctr3;
223 return WERR_OK;
226 /*******************************************************************
227 Utility function to get the 'type' of a share from an snum.
228 ********************************************************************/
229 static uint32 get_share_type(int snum)
231 /* work out the share type */
232 uint32 type = STYPE_DISKTREE;
234 if (lp_print_ok(snum))
235 type = STYPE_PRINTQ;
236 if (strequal(lp_fstype(snum), "IPC"))
237 type = STYPE_IPC;
238 if (lp_administrative_share(snum))
239 type |= STYPE_HIDDEN;
241 return type;
244 /*******************************************************************
245 Fill in a share info level 0 structure.
246 ********************************************************************/
248 static void init_srv_share_info_0(pipes_struct *p, struct srvsvc_NetShareInfo0 *r, int snum)
250 r->name = lp_servicename(snum);
253 /*******************************************************************
254 Fill in a share info level 1 structure.
255 ********************************************************************/
257 static void init_srv_share_info_1(pipes_struct *p, struct srvsvc_NetShareInfo1 *r, int snum)
259 char *net_name = lp_servicename(snum);
260 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
262 if (remark) {
263 remark = talloc_sub_advanced(
264 p->mem_ctx, lp_servicename(snum),
265 get_current_username(), lp_pathname(snum),
266 p->server_info->utok.uid, get_current_username(),
267 "", remark);
270 r->name = net_name;
271 r->type = get_share_type(snum);
272 r->comment = remark ? remark : "";
275 /*******************************************************************
276 Fill in a share info level 2 structure.
277 ********************************************************************/
279 static void init_srv_share_info_2(pipes_struct *p, struct srvsvc_NetShareInfo2 *r, int snum)
281 char *remark = NULL;
282 char *path = NULL;
283 int max_connections = lp_max_connections(snum);
284 uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
285 char *net_name = lp_servicename(snum);
287 remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
288 if (remark) {
289 remark = talloc_sub_advanced(
290 p->mem_ctx, lp_servicename(snum),
291 get_current_username(), lp_pathname(snum),
292 p->server_info->utok.uid, get_current_username(),
293 "", remark);
295 path = talloc_asprintf(p->mem_ctx,
296 "C:%s", lp_pathname(snum));
298 if (path) {
300 * Change / to \\ so that win2k will see it as a valid path.
301 * This was added to enable use of browsing in win2k add
302 * share dialog.
305 string_replace(path, '/', '\\');
308 r->name = net_name;
309 r->type = get_share_type(snum);
310 r->comment = remark ? remark : "";
311 r->permissions = 0;
312 r->max_users = max_uses;
313 r->current_users = count_current_connections(net_name, false);
314 r->path = path ? path : "";
315 r->password = "";
318 /*******************************************************************
319 Map any generic bits to file specific bits.
320 ********************************************************************/
322 static void map_generic_share_sd_bits(SEC_DESC *psd)
324 int i;
325 SEC_ACL *ps_dacl = NULL;
327 if (!psd)
328 return;
330 ps_dacl = psd->dacl;
331 if (!ps_dacl)
332 return;
334 for (i = 0; i < ps_dacl->num_aces; i++) {
335 SEC_ACE *psa = &ps_dacl->aces[i];
336 uint32 orig_mask = psa->access_mask;
338 se_map_generic(&psa->access_mask, &file_generic_mapping);
339 psa->access_mask |= orig_mask;
343 /*******************************************************************
344 Fill in a share info level 501 structure.
345 ********************************************************************/
347 static void init_srv_share_info_501(pipes_struct *p, struct srvsvc_NetShareInfo501 *r, int snum)
349 const char *net_name = lp_servicename(snum);
350 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
352 if (remark) {
353 remark = talloc_sub_advanced(
354 p->mem_ctx, lp_servicename(snum),
355 get_current_username(), lp_pathname(snum),
356 p->server_info->utok.uid, get_current_username(),
357 "", remark);
360 r->name = net_name;
361 r->type = get_share_type(snum);
362 r->comment = remark ? remark : "";
363 r->csc_policy = (lp_csc_policy(snum) << 4);
366 /*******************************************************************
367 Fill in a share info level 502 structure.
368 ********************************************************************/
370 static void init_srv_share_info_502(pipes_struct *p, struct srvsvc_NetShareInfo502 *r, int snum)
372 const char *net_name = lp_servicename(snum);
373 char *path = NULL;
374 SEC_DESC *sd = NULL;
375 struct sec_desc_buf *sd_buf = NULL;
376 size_t sd_size = 0;
377 TALLOC_CTX *ctx = p->mem_ctx;
378 char *remark = talloc_strdup(ctx, lp_comment(snum));;
380 if (remark) {
381 remark = talloc_sub_advanced(
382 p->mem_ctx, lp_servicename(snum),
383 get_current_username(), lp_pathname(snum),
384 p->server_info->utok.uid, get_current_username(),
385 "", remark);
387 path = talloc_asprintf(ctx, "C:%s", lp_pathname(snum));
388 if (path) {
390 * Change / to \\ so that win2k will see it as a valid path. This was added to
391 * enable use of browsing in win2k add share dialog.
393 string_replace(path, '/', '\\');
396 sd = get_share_security(ctx, lp_servicename(snum), &sd_size);
398 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
400 r->name = net_name;
401 r->type = get_share_type(snum);
402 r->comment = remark ? remark : "";
403 r->permissions = 0;
404 r->max_users = (uint32_t)-1;
405 r->current_users = 1; /* ??? */
406 r->path = path ? path : "";
407 r->password = "";
408 r->sd_buf = *sd_buf;
411 /***************************************************************************
412 Fill in a share info level 1004 structure.
413 ***************************************************************************/
415 static void init_srv_share_info_1004(pipes_struct *p, struct srvsvc_NetShareInfo1004 *r, int snum)
417 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
419 if (remark) {
420 remark = talloc_sub_advanced(
421 p->mem_ctx, lp_servicename(snum),
422 get_current_username(), lp_pathname(snum),
423 p->server_info->utok.uid, get_current_username(),
424 "", remark);
427 r->comment = remark ? remark : "";
430 /***************************************************************************
431 Fill in a share info level 1005 structure.
432 ***************************************************************************/
434 static void init_srv_share_info_1005(pipes_struct *p, struct srvsvc_NetShareInfo1005 *r, int snum)
436 uint32_t dfs_flags = 0;
438 if (lp_host_msdfs() && lp_msdfs_root(snum)) {
439 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
442 dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
444 r->dfs_flags = dfs_flags;
447 /***************************************************************************
448 Fill in a share info level 1006 structure.
449 ***************************************************************************/
451 static void init_srv_share_info_1006(pipes_struct *p, struct srvsvc_NetShareInfo1006 *r, int snum)
453 r->max_users = (uint32_t)-1;
456 /***************************************************************************
457 Fill in a share info level 1007 structure.
458 ***************************************************************************/
460 static void init_srv_share_info_1007(pipes_struct *p, struct srvsvc_NetShareInfo1007 *r, int snum)
462 r->flags = 0;
463 r->alternate_directory_name = "";
466 /*******************************************************************
467 Fill in a share info level 1501 structure.
468 ********************************************************************/
470 static void init_srv_share_info_1501(pipes_struct *p, struct sec_desc_buf *r, int snum)
472 SEC_DESC *sd;
473 size_t sd_size;
474 TALLOC_CTX *ctx = p->mem_ctx;
476 sd = get_share_security(ctx, lp_servicename(snum), &sd_size);
478 r = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
481 /*******************************************************************
482 True if it ends in '$'.
483 ********************************************************************/
485 static bool is_hidden_share(int snum)
487 const char *net_name = lp_servicename(snum);
489 return (net_name[strlen(net_name) - 1] == '$') ? True : False;
492 /*******************************************************************
493 Verify user is allowed to view share, access based enumeration
494 ********************************************************************/
495 static bool is_enumeration_allowed(pipes_struct *p,
496 int snum)
498 if (!lp_access_based_share_enum(snum))
499 return true;
501 return share_access_check(p->server_info->ptok, lp_servicename(snum),
502 FILE_READ_DATA);
505 /*******************************************************************
506 Fill in a share info structure.
507 ********************************************************************/
509 static WERROR init_srv_share_info_ctr(pipes_struct *p,
510 struct srvsvc_NetShareInfoCtr *info_ctr,
511 uint32_t *resume_handle_p,
512 uint32_t *total_entries,
513 bool all_shares)
515 int num_entries = 0;
516 int alloc_entries = 0;
517 int num_services = 0;
518 int snum;
519 TALLOC_CTX *ctx = p->mem_ctx;
520 int i = 0;
521 int valid_share_count = 0;
522 bool *allowed = 0;
523 union srvsvc_NetShareCtr ctr;
524 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
526 DEBUG(5,("init_srv_share_info_ctr\n"));
528 /* Ensure all the usershares are loaded. */
529 become_root();
530 load_usershare_shares();
531 load_registry_shares();
532 num_services = lp_numservices();
533 unbecome_root();
535 allowed = TALLOC_ZERO_ARRAY(ctx, bool, num_services);
536 W_ERROR_HAVE_NO_MEMORY(allowed);
538 /* Count the number of entries. */
539 for (snum = 0; snum < num_services; snum++) {
540 if (lp_browseable(snum) && lp_snum_ok(snum) &&
541 is_enumeration_allowed(p, snum) &&
542 (all_shares || !is_hidden_share(snum)) ) {
543 DEBUG(10, ("counting service %s\n", lp_servicename(snum)));
544 allowed[snum] = true;
545 num_entries++;
546 } else {
547 DEBUG(10, ("NOT counting service %s\n", lp_servicename(snum)));
551 if (!num_entries || (resume_handle >= num_entries)) {
552 return WERR_OK;
555 /* Calculate alloc entries. */
556 alloc_entries = num_entries - resume_handle;
557 switch (info_ctr->level) {
558 case 0:
559 ctr.ctr0 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr0);
560 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
562 ctr.ctr0->count = alloc_entries;
563 ctr.ctr0->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
564 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
566 for (snum = 0; snum < num_services; snum++) {
567 if (allowed[snum] &&
568 (resume_handle <= (i + valid_share_count++)) ) {
569 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
573 break;
575 case 1:
576 ctr.ctr1 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1);
577 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
579 ctr.ctr1->count = alloc_entries;
580 ctr.ctr1->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
581 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
583 for (snum = 0; snum < num_services; snum++) {
584 if (allowed[snum] &&
585 (resume_handle <= (i + valid_share_count++)) ) {
586 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
590 break;
592 case 2:
593 ctr.ctr2 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr2);
594 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
596 ctr.ctr2->count = alloc_entries;
597 ctr.ctr2->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
598 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
600 for (snum = 0; snum < num_services; snum++) {
601 if (allowed[snum] &&
602 (resume_handle <= (i + valid_share_count++)) ) {
603 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
607 break;
609 case 501:
610 ctr.ctr501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr501);
611 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
613 ctr.ctr501->count = alloc_entries;
614 ctr.ctr501->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
615 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
617 for (snum = 0; snum < num_services; snum++) {
618 if (allowed[snum] &&
619 (resume_handle <= (i + valid_share_count++)) ) {
620 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
624 break;
626 case 502:
627 ctr.ctr502 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr502);
628 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
630 ctr.ctr502->count = alloc_entries;
631 ctr.ctr502->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
632 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
634 for (snum = 0; snum < num_services; snum++) {
635 if (allowed[snum] &&
636 (resume_handle <= (i + valid_share_count++)) ) {
637 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
641 break;
643 case 1004:
644 ctr.ctr1004 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1004);
645 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
647 ctr.ctr1004->count = alloc_entries;
648 ctr.ctr1004->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
649 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
651 for (snum = 0; snum < num_services; snum++) {
652 if (allowed[snum] &&
653 (resume_handle <= (i + valid_share_count++)) ) {
654 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
658 break;
660 case 1005:
661 ctr.ctr1005 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1005);
662 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
664 ctr.ctr1005->count = alloc_entries;
665 ctr.ctr1005->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
666 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
668 for (snum = 0; snum < num_services; snum++) {
669 if (allowed[snum] &&
670 (resume_handle <= (i + valid_share_count++)) ) {
671 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
675 break;
677 case 1006:
678 ctr.ctr1006 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1006);
679 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
681 ctr.ctr1006->count = alloc_entries;
682 ctr.ctr1006->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
683 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
685 for (snum = 0; snum < num_services; snum++) {
686 if (allowed[snum] &&
687 (resume_handle <= (i + valid_share_count++)) ) {
688 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
692 break;
694 case 1007:
695 ctr.ctr1007 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1007);
696 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
698 ctr.ctr1007->count = alloc_entries;
699 ctr.ctr1007->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
700 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
702 for (snum = 0; snum < num_services; snum++) {
703 if (allowed[snum] &&
704 (resume_handle <= (i + valid_share_count++)) ) {
705 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
709 break;
711 case 1501:
712 ctr.ctr1501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1501);
713 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
715 ctr.ctr1501->count = alloc_entries;
716 ctr.ctr1501->array = TALLOC_ZERO_ARRAY(ctx, struct sec_desc_buf, alloc_entries);
717 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
719 for (snum = 0; snum < num_services; snum++) {
720 if (allowed[snum] &&
721 (resume_handle <= (i + valid_share_count++)) ) {
722 init_srv_share_info_1501(p, &ctr.ctr1501->array[i++], snum);
726 break;
728 default:
729 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
730 info_ctr->level));
731 return WERR_UNKNOWN_LEVEL;
734 *total_entries = alloc_entries;
735 if (resume_handle_p) {
736 if (all_shares) {
737 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
738 } else {
739 *resume_handle_p = num_entries;
743 info_ctr->ctr = ctr;
745 return WERR_OK;
748 /*******************************************************************
749 fill in a sess info level 0 structure.
750 ********************************************************************/
752 static WERROR init_srv_sess_info_0(pipes_struct *p,
753 struct srvsvc_NetSessCtr0 *ctr0,
754 uint32_t *resume_handle_p,
755 uint32_t *total_entries)
757 struct sessionid *session_list;
758 uint32_t num_entries = 0;
759 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
760 *total_entries = list_sessions(p->mem_ctx, &session_list);
762 DEBUG(5,("init_srv_sess_info_0\n"));
764 if (ctr0 == NULL) {
765 if (resume_handle_p) {
766 *resume_handle_p = 0;
768 return WERR_OK;
771 for (; resume_handle < *total_entries; resume_handle++) {
773 ctr0->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
774 ctr0->array,
775 struct srvsvc_NetSessInfo0,
776 num_entries+1);
777 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
779 ctr0->array[num_entries].client =
780 session_list[resume_handle].remote_machine;
782 num_entries++;
785 ctr0->count = num_entries;
787 if (resume_handle_p) {
788 if (*resume_handle_p >= *total_entries) {
789 *resume_handle_p = 0;
790 } else {
791 *resume_handle_p = resume_handle;
795 return WERR_OK;
798 /*******************************************************************
799 ********************************************************************/
801 static void sess_file_fn( const struct share_mode_entry *e,
802 const char *sharepath, const char *fname,
803 void *data )
805 struct sess_file_count *sess = (struct sess_file_count *)data;
807 if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
808 sess->count++;
811 return;
814 /*******************************************************************
815 ********************************************************************/
817 static int net_count_files( uid_t uid, struct server_id pid )
819 struct sess_file_count s_file_cnt;
821 s_file_cnt.count = 0;
822 s_file_cnt.uid = uid;
823 s_file_cnt.pid = pid;
825 share_mode_forall( sess_file_fn, &s_file_cnt );
827 return s_file_cnt.count;
830 /*******************************************************************
831 fill in a sess info level 1 structure.
832 ********************************************************************/
834 static WERROR init_srv_sess_info_1(pipes_struct *p,
835 struct srvsvc_NetSessCtr1 *ctr1,
836 uint32_t *resume_handle_p,
837 uint32_t *total_entries)
839 struct sessionid *session_list;
840 uint32_t num_entries = 0;
841 time_t now = time(NULL);
842 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
844 ZERO_STRUCTP(ctr1);
846 if (ctr1 == NULL) {
847 if (resume_handle_p) {
848 *resume_handle_p = 0;
850 return WERR_OK;
853 *total_entries = list_sessions(p->mem_ctx, &session_list);
855 for (; resume_handle < *total_entries; resume_handle++) {
856 uint32 num_files;
857 uint32 connect_time;
858 struct passwd *pw = sys_getpwnam(session_list[resume_handle].username);
859 bool guest;
861 if ( !pw ) {
862 DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
863 session_list[resume_handle].username));
864 continue;
867 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
868 num_files = net_count_files(pw->pw_uid, session_list[resume_handle].pid);
869 guest = strequal( session_list[resume_handle].username, lp_guestaccount() );
871 ctr1->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
872 ctr1->array,
873 struct srvsvc_NetSessInfo1,
874 num_entries+1);
875 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
877 ctr1->array[num_entries].client = session_list[resume_handle].remote_machine;
878 ctr1->array[num_entries].user = session_list[resume_handle].username;
879 ctr1->array[num_entries].num_open = num_files;
880 ctr1->array[num_entries].time = connect_time;
881 ctr1->array[num_entries].idle_time = 0;
882 ctr1->array[num_entries].user_flags = guest;
884 num_entries++;
887 ctr1->count = num_entries;
889 if (resume_handle_p) {
890 if (*resume_handle_p >= *total_entries) {
891 *resume_handle_p = 0;
892 } else {
893 *resume_handle_p = resume_handle;
897 return WERR_OK;
900 /*******************************************************************
901 fill in a conn info level 0 structure.
902 ********************************************************************/
904 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
905 uint32_t *resume_handle_p,
906 uint32_t *total_entries)
908 uint32_t num_entries = 0;
909 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
911 DEBUG(5,("init_srv_conn_info_0\n"));
913 if (ctr0 == NULL) {
914 if (resume_handle_p) {
915 *resume_handle_p = 0;
917 return WERR_OK;
920 *total_entries = 1;
922 ZERO_STRUCTP(ctr0);
924 for (; resume_handle < *total_entries; resume_handle++) {
926 ctr0->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
927 ctr0->array,
928 struct srvsvc_NetConnInfo0,
929 num_entries+1);
930 if (!ctr0->array) {
931 return WERR_NOMEM;
934 ctr0->array[num_entries].conn_id = *total_entries;
936 /* move on to creating next connection */
937 num_entries++;
940 ctr0->count = num_entries;
941 *total_entries = num_entries;
943 if (resume_handle_p) {
944 if (*resume_handle_p >= *total_entries) {
945 *resume_handle_p = 0;
946 } else {
947 *resume_handle_p = resume_handle;
951 return WERR_OK;
954 /*******************************************************************
955 fill in a conn info level 1 structure.
956 ********************************************************************/
958 static WERROR init_srv_conn_info_1(struct srvsvc_NetConnCtr1 *ctr1,
959 uint32_t *resume_handle_p,
960 uint32_t *total_entries)
962 uint32_t num_entries = 0;
963 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
965 DEBUG(5,("init_srv_conn_info_1\n"));
967 if (ctr1 == NULL) {
968 if (resume_handle_p) {
969 *resume_handle_p = 0;
971 return WERR_OK;
974 *total_entries = 1;
976 ZERO_STRUCTP(ctr1);
978 for (; resume_handle < *total_entries; resume_handle++) {
980 ctr1->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
981 ctr1->array,
982 struct srvsvc_NetConnInfo1,
983 num_entries+1);
984 if (!ctr1->array) {
985 return WERR_NOMEM;
988 ctr1->array[num_entries].conn_id = *total_entries;
989 ctr1->array[num_entries].conn_type = 0x3;
990 ctr1->array[num_entries].num_open = 1;
991 ctr1->array[num_entries].num_users = 1;
992 ctr1->array[num_entries].conn_time = 3;
993 ctr1->array[num_entries].user = "dummy_user";
994 ctr1->array[num_entries].share = "IPC$";
996 /* move on to creating next connection */
997 num_entries++;
1000 ctr1->count = num_entries;
1001 *total_entries = num_entries;
1003 if (resume_handle_p) {
1004 if (*resume_handle_p >= *total_entries) {
1005 *resume_handle_p = 0;
1006 } else {
1007 *resume_handle_p = resume_handle;
1011 return WERR_OK;
1014 /*******************************************************************
1015 _srvsvc_NetFileEnum
1016 *******************************************************************/
1018 WERROR _srvsvc_NetFileEnum(pipes_struct *p,
1019 struct srvsvc_NetFileEnum *r)
1021 TALLOC_CTX *ctx = NULL;
1022 struct srvsvc_NetFileCtr3 *ctr3;
1023 uint32_t resume_hnd = 0;
1024 WERROR werr;
1026 switch (r->in.info_ctr->level) {
1027 case 3:
1028 break;
1029 default:
1030 return WERR_UNKNOWN_LEVEL;
1033 ctx = talloc_tos();
1034 ctr3 = r->in.info_ctr->ctr.ctr3;
1035 if (!ctr3) {
1036 werr = WERR_INVALID_PARAM;
1037 goto done;
1040 /* TODO -- Windows enumerates
1041 (b) active pipes
1042 (c) open directories and files */
1044 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1045 if (!W_ERROR_IS_OK(werr)) {
1046 goto done;
1049 werr = net_enum_pipes(ctx, r->in.user, &ctr3, resume_hnd);
1050 if (!W_ERROR_IS_OK(werr)) {
1051 goto done;
1054 *r->out.totalentries = ctr3->count;
1055 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1056 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1058 werr = WERR_OK;
1060 done:
1061 return werr;
1064 /*******************************************************************
1065 _srvsvc_NetSrvGetInfo
1066 ********************************************************************/
1068 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p,
1069 struct srvsvc_NetSrvGetInfo *r)
1071 WERROR status = WERR_OK;
1073 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1075 if (!pipe_access_check(p)) {
1076 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1077 return WERR_ACCESS_DENIED;
1080 switch (r->in.level) {
1082 /* Technically level 102 should only be available to
1083 Administrators but there isn't anything super-secret
1084 here, as most of it is made up. */
1086 case 102: {
1087 struct srvsvc_NetSrvInfo102 *info102;
1089 info102 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1090 if (!info102) {
1091 return WERR_NOMEM;
1094 info102->platform_id = PLATFORM_ID_NT;
1095 info102->server_name = global_myname();
1096 info102->version_major = lp_major_announce_version();
1097 info102->version_minor = lp_minor_announce_version();
1098 info102->server_type = lp_default_server_announce();
1099 info102->comment = string_truncate(lp_serverstring(),
1100 MAX_SERVER_STRING_LENGTH);
1101 info102->users = 0xffffffff;
1102 info102->disc = 0xf;
1103 info102->hidden = 0;
1104 info102->announce = 240;
1105 info102->anndelta = 3000;
1106 info102->licenses = 100000;
1107 info102->userpath = "C:\\";
1109 r->out.info->info102 = info102;
1110 break;
1112 case 101: {
1113 struct srvsvc_NetSrvInfo101 *info101;
1115 info101 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1116 if (!info101) {
1117 return WERR_NOMEM;
1120 info101->platform_id = PLATFORM_ID_NT;
1121 info101->server_name = global_myname();
1122 info101->version_major = lp_major_announce_version();
1123 info101->version_minor = lp_minor_announce_version();
1124 info101->server_type = lp_default_server_announce();
1125 info101->comment = string_truncate(lp_serverstring(),
1126 MAX_SERVER_STRING_LENGTH);
1128 r->out.info->info101 = info101;
1129 break;
1131 case 100: {
1132 struct srvsvc_NetSrvInfo100 *info100;
1134 info100 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1135 if (!info100) {
1136 return WERR_NOMEM;
1139 info100->platform_id = PLATFORM_ID_NT;
1140 info100->server_name = global_myname();
1142 r->out.info->info100 = info100;
1144 break;
1146 default:
1147 status = WERR_UNKNOWN_LEVEL;
1148 break;
1151 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1153 return status;
1156 /*******************************************************************
1157 _srvsvc_NetSrvSetInfo
1158 ********************************************************************/
1160 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p,
1161 struct srvsvc_NetSrvSetInfo *r)
1163 WERROR status = WERR_OK;
1165 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1167 /* Set up the net server set info structure. */
1169 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1171 return status;
1174 /*******************************************************************
1175 _srvsvc_NetConnEnum
1176 ********************************************************************/
1178 WERROR _srvsvc_NetConnEnum(pipes_struct *p,
1179 struct srvsvc_NetConnEnum *r)
1181 WERROR werr;
1183 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1185 switch (r->in.info_ctr->level) {
1186 case 0:
1187 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1188 r->in.resume_handle,
1189 r->out.totalentries);
1190 break;
1191 case 1:
1192 werr = init_srv_conn_info_1(r->in.info_ctr->ctr.ctr1,
1193 r->in.resume_handle,
1194 r->out.totalentries);
1195 break;
1196 default:
1197 return WERR_UNKNOWN_LEVEL;
1200 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1202 return werr;
1205 /*******************************************************************
1206 _srvsvc_NetSessEnum
1207 ********************************************************************/
1209 WERROR _srvsvc_NetSessEnum(pipes_struct *p,
1210 struct srvsvc_NetSessEnum *r)
1212 WERROR werr;
1214 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1216 switch (r->in.info_ctr->level) {
1217 case 0:
1218 werr = init_srv_sess_info_0(p,
1219 r->in.info_ctr->ctr.ctr0,
1220 r->in.resume_handle,
1221 r->out.totalentries);
1222 break;
1223 case 1:
1224 werr = init_srv_sess_info_1(p,
1225 r->in.info_ctr->ctr.ctr1,
1226 r->in.resume_handle,
1227 r->out.totalentries);
1228 break;
1229 default:
1230 return WERR_UNKNOWN_LEVEL;
1233 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1235 return werr;
1238 /*******************************************************************
1239 _srvsvc_NetSessDel
1240 ********************************************************************/
1242 WERROR _srvsvc_NetSessDel(pipes_struct *p,
1243 struct srvsvc_NetSessDel *r)
1245 struct sessionid *session_list;
1246 int num_sessions, snum;
1247 const char *username;
1248 const char *machine;
1249 bool not_root = False;
1250 WERROR werr;
1252 username = r->in.user;
1253 machine = r->in.client;
1255 /* strip leading backslashes if any */
1256 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1257 machine += 2;
1260 num_sessions = list_sessions(p->mem_ctx, &session_list);
1262 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1264 werr = WERR_ACCESS_DENIED;
1266 /* fail out now if you are not root or not a domain admin */
1268 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1269 ( ! nt_token_check_domain_rid(p->server_info->ptok,
1270 DOMAIN_GROUP_RID_ADMINS))) {
1272 goto done;
1275 for (snum = 0; snum < num_sessions; snum++) {
1277 if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
1278 strequal(session_list[snum].remote_machine, machine)) {
1280 NTSTATUS ntstat;
1282 if (p->server_info->utok.uid != sec_initial_uid()) {
1283 not_root = True;
1284 become_root();
1287 ntstat = messaging_send(smbd_messaging_context(),
1288 session_list[snum].pid,
1289 MSG_SHUTDOWN, &data_blob_null);
1291 if (NT_STATUS_IS_OK(ntstat))
1292 werr = WERR_OK;
1294 if (not_root)
1295 unbecome_root();
1299 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1301 done:
1303 return werr;
1306 /*******************************************************************
1307 _srvsvc_NetShareEnumAll
1308 ********************************************************************/
1310 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p,
1311 struct srvsvc_NetShareEnumAll *r)
1313 WERROR werr;
1315 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1317 if (!pipe_access_check(p)) {
1318 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1319 return WERR_ACCESS_DENIED;
1322 /* Create the list of shares for the response. */
1323 werr = init_srv_share_info_ctr(p,
1324 r->in.info_ctr,
1325 r->in.resume_handle,
1326 r->out.totalentries,
1327 true);
1329 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1331 return werr;
1334 /*******************************************************************
1335 _srvsvc_NetShareEnum
1336 ********************************************************************/
1338 WERROR _srvsvc_NetShareEnum(pipes_struct *p,
1339 struct srvsvc_NetShareEnum *r)
1341 WERROR werr;
1343 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1345 if (!pipe_access_check(p)) {
1346 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1347 return WERR_ACCESS_DENIED;
1350 /* Create the list of shares for the response. */
1351 werr = init_srv_share_info_ctr(p,
1352 r->in.info_ctr,
1353 r->in.resume_handle,
1354 r->out.totalentries,
1355 false);
1357 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1359 return werr;
1362 /*******************************************************************
1363 _srvsvc_NetShareGetInfo
1364 ********************************************************************/
1366 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p,
1367 struct srvsvc_NetShareGetInfo *r)
1369 WERROR status = WERR_OK;
1370 fstring share_name;
1371 int snum;
1372 union srvsvc_NetShareInfo *info = r->out.info;
1374 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1376 fstrcpy(share_name, r->in.share_name);
1378 snum = find_service(share_name);
1379 if (snum < 0) {
1380 return WERR_INVALID_NAME;
1383 switch (r->in.level) {
1384 case 0:
1385 info->info0 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo0);
1386 W_ERROR_HAVE_NO_MEMORY(info->info0);
1387 init_srv_share_info_0(p, info->info0, snum);
1388 break;
1389 case 1:
1390 info->info1 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1);
1391 W_ERROR_HAVE_NO_MEMORY(info->info1);
1392 init_srv_share_info_1(p, info->info1, snum);
1393 break;
1394 case 2:
1395 info->info2 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo2);
1396 W_ERROR_HAVE_NO_MEMORY(info->info2);
1397 init_srv_share_info_2(p, info->info2, snum);
1398 break;
1399 case 501:
1400 info->info501 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo501);
1401 W_ERROR_HAVE_NO_MEMORY(info->info501);
1402 init_srv_share_info_501(p, info->info501, snum);
1403 break;
1404 case 502:
1405 info->info502 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo502);
1406 W_ERROR_HAVE_NO_MEMORY(info->info502);
1407 init_srv_share_info_502(p, info->info502, snum);
1408 break;
1409 case 1004:
1410 info->info1004 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1411 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1412 init_srv_share_info_1004(p, info->info1004, snum);
1413 break;
1414 case 1005:
1415 info->info1005 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1416 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1417 init_srv_share_info_1005(p, info->info1005, snum);
1418 break;
1419 case 1006:
1420 info->info1006 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1421 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1422 init_srv_share_info_1006(p, info->info1006, snum);
1423 break;
1424 case 1007:
1425 info->info1007 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1426 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1427 init_srv_share_info_1007(p, info->info1007, snum);
1428 break;
1429 case 1501:
1430 init_srv_share_info_1501(p, info->info1501, snum);
1431 break;
1432 default:
1433 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1434 r->in.level));
1435 status = WERR_UNKNOWN_LEVEL;
1436 break;
1439 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1441 return status;
1444 /*******************************************************************
1445 Check a given DOS pathname is valid for a share.
1446 ********************************************************************/
1448 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
1450 char *ptr = NULL;
1452 if (!dos_pathname) {
1453 return NULL;
1456 ptr = talloc_strdup(ctx, dos_pathname);
1457 if (!ptr) {
1458 return NULL;
1460 /* Convert any '\' paths to '/' */
1461 unix_format(ptr);
1462 ptr = unix_clean_name(ctx, ptr);
1463 if (!ptr) {
1464 return NULL;
1467 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1468 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
1469 ptr += 2;
1471 /* Only absolute paths allowed. */
1472 if (*ptr != '/')
1473 return NULL;
1475 return ptr;
1478 /*******************************************************************
1479 _srvsvc_NetShareSetInfo. Modify share details.
1480 ********************************************************************/
1482 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p,
1483 struct srvsvc_NetShareSetInfo *r)
1485 char *command = NULL;
1486 char *share_name = NULL;
1487 char *comment = NULL;
1488 const char *pathname = NULL;
1489 int type;
1490 int snum;
1491 int ret;
1492 char *path = NULL;
1493 SEC_DESC *psd = NULL;
1494 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1495 bool is_disk_op = False;
1496 int max_connections = 0;
1497 TALLOC_CTX *ctx = p->mem_ctx;
1498 union srvsvc_NetShareInfo *info = r->in.info;
1500 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1502 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1503 if (!share_name) {
1504 return WERR_NOMEM;
1507 if (r->out.parm_error) {
1508 *r->out.parm_error = 0;
1511 if ( strequal(share_name,"IPC$")
1512 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1513 || strequal(share_name,"global") )
1515 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s cannot be "
1516 "modified by a remote user.\n",
1517 share_name ));
1518 return WERR_ACCESS_DENIED;
1521 snum = find_service(share_name);
1523 /* Does this share exist ? */
1524 if (snum < 0)
1525 return WERR_NET_NAME_NOT_FOUND;
1527 /* No change to printer shares. */
1528 if (lp_print_ok(snum))
1529 return WERR_ACCESS_DENIED;
1531 is_disk_op = user_has_privileges( p->server_info->ptok, &se_diskop );
1533 /* fail out now if you are not root and not a disk op */
1535 if ( p->server_info->utok.uid != sec_initial_uid() && !is_disk_op ) {
1536 DEBUG(2,("_srvsvc_NetShareSetInfo: uid %u doesn't have the "
1537 "SeDiskOperatorPrivilege privilege needed to modify "
1538 "share %s\n",
1539 (unsigned int)p->server_info->utok.uid,
1540 share_name ));
1541 return WERR_ACCESS_DENIED;
1544 switch (r->in.level) {
1545 case 1:
1546 pathname = talloc_strdup(ctx, lp_pathname(snum));
1547 comment = talloc_strdup(ctx, info->info1->comment);
1548 type = info->info1->type;
1549 psd = NULL;
1550 break;
1551 case 2:
1552 comment = talloc_strdup(ctx, info->info2->comment);
1553 pathname = info->info2->path;
1554 type = info->info2->type;
1555 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1556 0 : info->info2->max_users;
1557 psd = NULL;
1558 break;
1559 #if 0
1560 /* not supported on set but here for completeness */
1561 case 501:
1562 comment = talloc_strdup(ctx, info->info501->comment);
1563 type = info->info501->type;
1564 psd = NULL;
1565 break;
1566 #endif
1567 case 502:
1568 comment = talloc_strdup(ctx, info->info502->comment);
1569 pathname = info->info502->path;
1570 type = info->info502->type;
1571 psd = info->info502->sd_buf.sd;
1572 map_generic_share_sd_bits(psd);
1573 break;
1574 case 1004:
1575 pathname = talloc_strdup(ctx, lp_pathname(snum));
1576 comment = talloc_strdup(ctx, info->info1004->comment);
1577 type = STYPE_DISKTREE;
1578 break;
1579 case 1005:
1580 /* XP re-sets the csc policy even if it wasn't changed by the
1581 user, so we must compare it to see if it's what is set in
1582 smb.conf, so that we can contine other ops like setting
1583 ACLs on a share */
1584 if (((info->info1005->dfs_flags &
1585 SHARE_1005_CSC_POLICY_MASK) >>
1586 SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1587 return WERR_OK;
1588 else {
1589 DEBUG(3, ("_srvsvc_NetShareSetInfo: client is trying to change csc policy from the network; must be done with smb.conf\n"));
1590 return WERR_ACCESS_DENIED;
1592 case 1006:
1593 case 1007:
1594 return WERR_ACCESS_DENIED;
1595 case 1501:
1596 pathname = talloc_strdup(ctx, lp_pathname(snum));
1597 comment = talloc_strdup(ctx, lp_comment(snum));
1598 psd = info->info1501->sd;
1599 map_generic_share_sd_bits(psd);
1600 type = STYPE_DISKTREE;
1601 break;
1602 default:
1603 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1604 r->in.level));
1605 return WERR_UNKNOWN_LEVEL;
1608 /* We can only modify disk shares. */
1609 if (type != STYPE_DISKTREE) {
1610 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s is not a "
1611 "disk share\n",
1612 share_name ));
1613 return WERR_ACCESS_DENIED;
1616 if (comment == NULL) {
1617 return WERR_NOMEM;
1620 /* Check if the pathname is valid. */
1621 if (!(path = valid_share_pathname(p->mem_ctx, pathname ))) {
1622 DEBUG(5,("_srvsvc_NetShareSetInfo: invalid pathname %s\n",
1623 pathname ));
1624 return WERR_OBJECT_PATH_INVALID;
1627 /* Ensure share name, pathname and comment don't contain '"' characters. */
1628 string_replace(share_name, '"', ' ');
1629 string_replace(path, '"', ' ');
1630 string_replace(comment, '"', ' ');
1632 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1633 lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1635 /* Only call modify function if something changed. */
1637 if (strcmp(path, lp_pathname(snum)) || strcmp(comment, lp_comment(snum))
1638 || (lp_max_connections(snum) != max_connections)) {
1639 if (!lp_change_share_cmd() || !*lp_change_share_cmd()) {
1640 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1641 return WERR_ACCESS_DENIED;
1644 command = talloc_asprintf(p->mem_ctx,
1645 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1646 lp_change_share_cmd(),
1647 get_dyn_CONFIGFILE(),
1648 share_name,
1649 path,
1650 comment ? comment : "",
1651 max_connections);
1652 if (!command) {
1653 return WERR_NOMEM;
1656 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1658 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1660 if (is_disk_op)
1661 become_root();
1663 if ( (ret = smbrun(command, NULL)) == 0 ) {
1664 /* Tell everyone we updated smb.conf. */
1665 message_send_all(smbd_messaging_context(),
1666 MSG_SMB_CONF_UPDATED, NULL, 0,
1667 NULL);
1670 if ( is_disk_op )
1671 unbecome_root();
1673 /********* END SeDiskOperatorPrivilege BLOCK *********/
1675 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1676 command, ret ));
1678 TALLOC_FREE(command);
1680 if ( ret != 0 )
1681 return WERR_ACCESS_DENIED;
1682 } else {
1683 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1684 share_name ));
1687 /* Replace SD if changed. */
1688 if (psd) {
1689 SEC_DESC *old_sd;
1690 size_t sd_size;
1692 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum), &sd_size);
1694 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1695 if (!set_share_security(share_name, psd))
1696 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1697 share_name ));
1701 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1703 return WERR_OK;
1706 /*******************************************************************
1707 _srvsvc_NetShareAdd.
1708 Call 'add_share_command "sharename" "pathname"
1709 "comment" "max connections = "
1710 ********************************************************************/
1712 WERROR _srvsvc_NetShareAdd(pipes_struct *p,
1713 struct srvsvc_NetShareAdd *r)
1715 char *command = NULL;
1716 char *share_name = NULL;
1717 char *comment = NULL;
1718 char *pathname = NULL;
1719 int type;
1720 int snum;
1721 int ret;
1722 char *path;
1723 SEC_DESC *psd = NULL;
1724 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1725 bool is_disk_op;
1726 int max_connections = 0;
1727 TALLOC_CTX *ctx = p->mem_ctx;
1729 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1731 if (r->out.parm_error) {
1732 *r->out.parm_error = 0;
1735 is_disk_op = user_has_privileges( p->server_info->ptok, &se_diskop );
1737 if (p->server_info->utok.uid != sec_initial_uid() && !is_disk_op )
1738 return WERR_ACCESS_DENIED;
1740 if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
1741 DEBUG(10,("_srvsvc_NetShareAdd: No add share command\n"));
1742 return WERR_ACCESS_DENIED;
1745 switch (r->in.level) {
1746 case 0:
1747 /* No path. Not enough info in a level 0 to do anything. */
1748 return WERR_ACCESS_DENIED;
1749 case 1:
1750 /* Not enough info in a level 1 to do anything. */
1751 return WERR_ACCESS_DENIED;
1752 case 2:
1753 share_name = talloc_strdup(ctx, r->in.info->info2->name);
1754 comment = talloc_strdup(ctx, r->in.info->info2->comment);
1755 pathname = talloc_strdup(ctx, r->in.info->info2->path);
1756 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
1757 0 : r->in.info->info2->max_users;
1758 type = r->in.info->info2->type;
1759 break;
1760 case 501:
1761 /* No path. Not enough info in a level 501 to do anything. */
1762 return WERR_ACCESS_DENIED;
1763 case 502:
1764 share_name = talloc_strdup(ctx, r->in.info->info502->name);
1765 comment = talloc_strdup(ctx, r->in.info->info502->comment);
1766 pathname = talloc_strdup(ctx, r->in.info->info502->path);
1767 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
1768 0 : r->in.info->info502->max_users;
1769 type = r->in.info->info502->type;
1770 psd = r->in.info->info502->sd_buf.sd;
1771 map_generic_share_sd_bits(psd);
1772 break;
1774 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
1776 case 1004:
1777 case 1005:
1778 case 1006:
1779 case 1007:
1780 return WERR_ACCESS_DENIED;
1781 case 1501:
1782 /* DFS only level. */
1783 return WERR_ACCESS_DENIED;
1784 default:
1785 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
1786 r->in.level));
1787 return WERR_UNKNOWN_LEVEL;
1790 /* check for invalid share names */
1792 if (!share_name || !validate_net_name(share_name,
1793 INVALID_SHARENAME_CHARS,
1794 strlen(share_name))) {
1795 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
1796 share_name ? share_name : ""));
1797 return WERR_INVALID_NAME;
1800 if (strequal(share_name,"IPC$") || strequal(share_name,"global")
1801 || (lp_enable_asu_support() &&
1802 strequal(share_name,"ADMIN$"))) {
1803 return WERR_ACCESS_DENIED;
1806 snum = find_service(share_name);
1808 /* Share already exists. */
1809 if (snum >= 0) {
1810 return WERR_FILE_EXISTS;
1813 /* We can only add disk shares. */
1814 if (type != STYPE_DISKTREE) {
1815 return WERR_ACCESS_DENIED;
1818 /* Check if the pathname is valid. */
1819 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
1820 return WERR_OBJECT_PATH_INVALID;
1823 /* Ensure share name, pathname and comment don't contain '"' characters. */
1824 string_replace(share_name, '"', ' ');
1825 string_replace(path, '"', ' ');
1826 if (comment) {
1827 string_replace(comment, '"', ' ');
1830 command = talloc_asprintf(ctx,
1831 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1832 lp_add_share_cmd(),
1833 get_dyn_CONFIGFILE(),
1834 share_name,
1835 path,
1836 comment ? comment : "",
1837 max_connections);
1838 if (!command) {
1839 return WERR_NOMEM;
1842 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
1844 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1846 if ( is_disk_op )
1847 become_root();
1849 /* FIXME: use libnetconf here - gd */
1851 if ( (ret = smbrun(command, NULL)) == 0 ) {
1852 /* Tell everyone we updated smb.conf. */
1853 message_send_all(smbd_messaging_context(),
1854 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1857 if ( is_disk_op )
1858 unbecome_root();
1860 /********* END SeDiskOperatorPrivilege BLOCK *********/
1862 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
1863 command, ret ));
1865 TALLOC_FREE(command);
1867 if ( ret != 0 )
1868 return WERR_ACCESS_DENIED;
1870 if (psd) {
1871 if (!set_share_security(share_name, psd)) {
1872 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
1873 share_name ));
1878 * We don't call reload_services() here, the message will
1879 * cause this to be done before the next packet is read
1880 * from the client. JRA.
1883 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1885 return WERR_OK;
1888 /*******************************************************************
1889 _srvsvc_NetShareDel
1890 Call "delete share command" with the share name as
1891 a parameter.
1892 ********************************************************************/
1894 WERROR _srvsvc_NetShareDel(pipes_struct *p,
1895 struct srvsvc_NetShareDel *r)
1897 char *command = NULL;
1898 char *share_name = NULL;
1899 int ret;
1900 int snum;
1901 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1902 bool is_disk_op;
1903 struct share_params *params;
1904 TALLOC_CTX *ctx = p->mem_ctx;
1906 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
1908 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1909 if (!share_name) {
1910 return WERR_NET_NAME_NOT_FOUND;
1912 if ( strequal(share_name,"IPC$")
1913 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1914 || strequal(share_name,"global") )
1916 return WERR_ACCESS_DENIED;
1919 if (!(params = get_share_params(p->mem_ctx, share_name))) {
1920 return WERR_NO_SUCH_SHARE;
1923 snum = find_service(share_name);
1925 /* No change to printer shares. */
1926 if (lp_print_ok(snum))
1927 return WERR_ACCESS_DENIED;
1929 is_disk_op = user_has_privileges( p->server_info->ptok, &se_diskop );
1931 if (p->server_info->utok.uid != sec_initial_uid() && !is_disk_op )
1932 return WERR_ACCESS_DENIED;
1934 if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
1935 DEBUG(10,("_srvsvc_NetShareDel: No delete share command\n"));
1936 return WERR_ACCESS_DENIED;
1939 command = talloc_asprintf(ctx,
1940 "%s \"%s\" \"%s\"",
1941 lp_delete_share_cmd(),
1942 get_dyn_CONFIGFILE(),
1943 lp_servicename(snum));
1944 if (!command) {
1945 return WERR_NOMEM;
1948 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
1950 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1952 if ( is_disk_op )
1953 become_root();
1955 if ( (ret = smbrun(command, NULL)) == 0 ) {
1956 /* Tell everyone we updated smb.conf. */
1957 message_send_all(smbd_messaging_context(),
1958 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1961 if ( is_disk_op )
1962 unbecome_root();
1964 /********* END SeDiskOperatorPrivilege BLOCK *********/
1966 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
1968 if ( ret != 0 )
1969 return WERR_ACCESS_DENIED;
1971 /* Delete the SD in the database. */
1972 delete_share_security(lp_servicename(params->service));
1974 lp_killservice(params->service);
1976 return WERR_OK;
1979 /*******************************************************************
1980 _srvsvc_NetShareDelSticky
1981 ********************************************************************/
1983 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p,
1984 struct srvsvc_NetShareDelSticky *r)
1986 struct srvsvc_NetShareDel q;
1988 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
1990 q.in.server_unc = r->in.server_unc;
1991 q.in.share_name = r->in.share_name;
1992 q.in.reserved = r->in.reserved;
1994 return _srvsvc_NetShareDel(p, &q);
1997 /*******************************************************************
1998 _srvsvc_NetRemoteTOD
1999 ********************************************************************/
2001 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p,
2002 struct srvsvc_NetRemoteTOD *r)
2004 struct srvsvc_NetRemoteTODInfo *tod;
2005 struct tm *t;
2006 time_t unixdate = time(NULL);
2008 /* We do this call first as if we do it *after* the gmtime call
2009 it overwrites the pointed-to values. JRA */
2011 uint32 zone = get_time_zone(unixdate)/60;
2013 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2015 if ( !(tod = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
2016 return WERR_NOMEM;
2018 *r->out.info = tod;
2020 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2022 t = gmtime(&unixdate);
2024 /* set up the */
2025 tod->elapsed = unixdate;
2026 tod->msecs = 0;
2027 tod->hours = t->tm_hour;
2028 tod->mins = t->tm_min;
2029 tod->secs = t->tm_sec;
2030 tod->hunds = 0;
2031 tod->timezone = zone;
2032 tod->tinterval = 10000;
2033 tod->day = t->tm_mday;
2034 tod->month = t->tm_mon + 1;
2035 tod->year = 1900+t->tm_year;
2036 tod->weekday = t->tm_wday;
2038 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2040 return WERR_OK;
2043 /***********************************************************************************
2044 _srvsvc_NetGetFileSecurity
2045 Win9x NT tools get security descriptor.
2046 ***********************************************************************************/
2048 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p,
2049 struct srvsvc_NetGetFileSecurity *r)
2051 SEC_DESC *psd = NULL;
2052 size_t sd_size;
2053 fstring servicename;
2054 SMB_STRUCT_STAT st;
2055 NTSTATUS nt_status;
2056 WERROR werr;
2057 connection_struct *conn = NULL;
2058 struct sec_desc_buf *sd_buf = NULL;
2059 files_struct *fsp = NULL;
2060 int snum;
2061 char *oldcwd = NULL;
2063 ZERO_STRUCT(st);
2065 fstrcpy(servicename, r->in.share);
2067 snum = find_service(servicename);
2068 if (snum == -1) {
2069 DEBUG(10, ("Could not find service %s\n", servicename));
2070 werr = WERR_NET_NAME_NOT_FOUND;
2071 goto error_exit;
2074 nt_status = create_conn_struct(talloc_tos(), &conn, snum,
2075 lp_pathname(snum), p->server_info,
2076 &oldcwd);
2077 if (!NT_STATUS_IS_OK(nt_status)) {
2078 DEBUG(10, ("create_conn_struct failed: %s\n",
2079 nt_errstr(nt_status)));
2080 werr = ntstatus_to_werror(nt_status);
2081 goto error_exit;
2084 nt_status = SMB_VFS_CREATE_FILE(
2085 conn, /* conn */
2086 NULL, /* req */
2087 0, /* root_dir_fid */
2088 r->in.file, /* fname */
2089 CFF_DOS_PATH, /* create_file_flags */
2090 FILE_READ_ATTRIBUTES, /* access_mask */
2091 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2092 FILE_OPEN, /* create_disposition*/
2093 0, /* create_options */
2094 0, /* file_attributes */
2095 INTERNAL_OPEN_ONLY, /* oplock_request */
2096 0, /* allocation_size */
2097 NULL, /* sd */
2098 NULL, /* ea_list */
2099 &fsp, /* result */
2100 NULL, /* pinfo */
2101 NULL); /* psbuf */
2103 if (!NT_STATUS_IS_OK(nt_status)) {
2104 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2105 r->in.file));
2106 werr = ntstatus_to_werror(nt_status);
2107 goto error_exit;
2110 nt_status = SMB_VFS_FGET_NT_ACL(fsp,
2111 (OWNER_SECURITY_INFORMATION
2112 |GROUP_SECURITY_INFORMATION
2113 |DACL_SECURITY_INFORMATION), &psd);
2115 if (!NT_STATUS_IS_OK(nt_status)) {
2116 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2117 "for file %s\n", r->in.file));
2118 werr = ntstatus_to_werror(nt_status);
2119 goto error_exit;
2122 sd_size = ndr_size_security_descriptor(psd, NULL, 0);
2124 sd_buf = TALLOC_ZERO_P(p->mem_ctx, struct sec_desc_buf);
2125 if (!sd_buf) {
2126 werr = WERR_NOMEM;
2127 goto error_exit;
2130 sd_buf->sd_size = sd_size;
2131 sd_buf->sd = psd;
2133 *r->out.sd_buf = sd_buf;
2135 psd->dacl->revision = NT4_ACL_REVISION;
2137 close_file(NULL, fsp, NORMAL_CLOSE);
2138 vfs_ChDir(conn, oldcwd);
2139 conn_free_internal(conn);
2140 return WERR_OK;
2142 error_exit:
2144 if (fsp) {
2145 close_file(NULL, fsp, NORMAL_CLOSE);
2148 if (oldcwd) {
2149 vfs_ChDir(conn, oldcwd);
2152 if (conn) {
2153 conn_free_internal(conn);
2156 return werr;
2159 /***********************************************************************************
2160 _srvsvc_NetSetFileSecurity
2161 Win9x NT tools set security descriptor.
2162 ***********************************************************************************/
2164 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p,
2165 struct srvsvc_NetSetFileSecurity *r)
2167 fstring servicename;
2168 files_struct *fsp = NULL;
2169 SMB_STRUCT_STAT st;
2170 NTSTATUS nt_status;
2171 WERROR werr;
2172 connection_struct *conn = NULL;
2173 int snum;
2174 char *oldcwd = NULL;
2175 struct security_descriptor *psd = NULL;
2176 uint32_t security_info_sent = 0;
2178 ZERO_STRUCT(st);
2180 fstrcpy(servicename, r->in.share);
2182 snum = find_service(servicename);
2183 if (snum == -1) {
2184 DEBUG(10, ("Could not find service %s\n", servicename));
2185 werr = WERR_NET_NAME_NOT_FOUND;
2186 goto error_exit;
2189 nt_status = create_conn_struct(talloc_tos(), &conn, snum,
2190 lp_pathname(snum), p->server_info,
2191 &oldcwd);
2192 if (!NT_STATUS_IS_OK(nt_status)) {
2193 DEBUG(10, ("create_conn_struct failed: %s\n",
2194 nt_errstr(nt_status)));
2195 werr = ntstatus_to_werror(nt_status);
2196 goto error_exit;
2199 nt_status = SMB_VFS_CREATE_FILE(
2200 conn, /* conn */
2201 NULL, /* req */
2202 0, /* root_dir_fid */
2203 r->in.file, /* fname */
2204 CFF_DOS_PATH, /* create_file_flags */
2205 FILE_WRITE_ATTRIBUTES, /* access_mask */
2206 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2207 FILE_OPEN, /* create_disposition*/
2208 0, /* create_options */
2209 0, /* file_attributes */
2210 INTERNAL_OPEN_ONLY, /* oplock_request */
2211 0, /* allocation_size */
2212 NULL, /* sd */
2213 NULL, /* ea_list */
2214 &fsp, /* result */
2215 NULL, /* pinfo */
2216 NULL); /* psbuf */
2218 if (!NT_STATUS_IS_OK(nt_status)) {
2219 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2220 r->in.file));
2221 werr = ntstatus_to_werror(nt_status);
2222 goto error_exit;
2225 psd = r->in.sd_buf->sd;
2226 security_info_sent = r->in.securityinformation;
2228 if (psd->owner_sid==0) {
2229 security_info_sent &= ~OWNER_SECURITY_INFORMATION;
2231 if (psd->group_sid==0) {
2232 security_info_sent &= ~GROUP_SECURITY_INFORMATION;
2234 if (psd->sacl==0) {
2235 security_info_sent &= ~SACL_SECURITY_INFORMATION;
2237 if (psd->dacl==0) {
2238 security_info_sent &= ~DACL_SECURITY_INFORMATION;
2241 /* Convert all the generic bits. */
2242 security_acl_map_generic(psd->dacl, &file_generic_mapping);
2243 security_acl_map_generic(psd->sacl, &file_generic_mapping);
2245 nt_status = SMB_VFS_FSET_NT_ACL(fsp,
2246 security_info_sent,
2247 psd);
2249 if (!NT_STATUS_IS_OK(nt_status) ) {
2250 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2251 "on file %s\n", r->in.share));
2252 werr = WERR_ACCESS_DENIED;
2253 goto error_exit;
2256 close_file(NULL, fsp, NORMAL_CLOSE);
2257 vfs_ChDir(conn, oldcwd);
2258 conn_free_internal(conn);
2259 return WERR_OK;
2261 error_exit:
2263 if (fsp) {
2264 close_file(NULL, fsp, NORMAL_CLOSE);
2267 if (oldcwd) {
2268 vfs_ChDir(conn, oldcwd);
2271 if (conn) {
2272 conn_free_internal(conn);
2275 return werr;
2278 /***********************************************************************************
2279 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2280 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2281 These disks would the disks listed by this function.
2282 Users could then create shares relative to these disks. Watch out for moving these disks around.
2283 "Nigel Williams" <nigel@veritas.com>.
2284 ***********************************************************************************/
2286 static const char *server_disks[] = {"C:"};
2288 static uint32 get_server_disk_count(void)
2290 return sizeof(server_disks)/sizeof(server_disks[0]);
2293 static uint32 init_server_disk_enum(uint32 *resume)
2295 uint32 server_disk_count = get_server_disk_count();
2297 /*resume can be an offset into the list for now*/
2299 if(*resume & 0x80000000)
2300 *resume = 0;
2302 if(*resume > server_disk_count)
2303 *resume = server_disk_count;
2305 return server_disk_count - *resume;
2308 static const char *next_server_disk_enum(uint32 *resume)
2310 const char *disk;
2312 if(init_server_disk_enum(resume) == 0)
2313 return NULL;
2315 disk = server_disks[*resume];
2317 (*resume)++;
2319 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2321 return disk;
2324 /********************************************************************
2325 _srvsvc_NetDiskEnum
2326 ********************************************************************/
2328 WERROR _srvsvc_NetDiskEnum(pipes_struct *p,
2329 struct srvsvc_NetDiskEnum *r)
2331 uint32 i;
2332 const char *disk_name;
2333 TALLOC_CTX *ctx = p->mem_ctx;
2334 WERROR werr;
2335 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2337 werr = WERR_OK;
2339 *r->out.totalentries = init_server_disk_enum(&resume);
2341 r->out.info->disks = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetDiskInfo0,
2342 MAX_SERVER_DISK_ENTRIES);
2343 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2345 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2347 r->out.info->count = 0;
2349 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2351 r->out.info->count++;
2353 /*copy disk name into a unicode string*/
2355 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2356 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2359 /* add a terminating null string. Is this there if there is more data to come? */
2361 r->out.info->count++;
2363 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2364 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2366 if (r->out.resume_handle) {
2367 *r->out.resume_handle = resume;
2370 return werr;
2373 /********************************************************************
2374 _srvsvc_NetNameValidate
2375 ********************************************************************/
2377 WERROR _srvsvc_NetNameValidate(pipes_struct *p,
2378 struct srvsvc_NetNameValidate *r)
2380 switch (r->in.name_type) {
2381 case 0x9:
2382 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2383 strlen_m(r->in.name)))
2385 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2386 r->in.name));
2387 return WERR_INVALID_NAME;
2389 break;
2391 default:
2392 return WERR_UNKNOWN_LEVEL;
2395 return WERR_OK;
2398 /*******************************************************************
2399 ********************************************************************/
2401 static void enum_file_close_fn( const struct share_mode_entry *e,
2402 const char *sharepath, const char *fname,
2403 void *private_data )
2405 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2406 struct srvsvc_NetFileClose *r =
2407 (struct srvsvc_NetFileClose *)private_data;
2408 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2410 if (fid != r->in.fid) {
2411 return; /* Not this file. */
2414 if (!process_exists(e->pid) ) {
2415 return;
2418 /* Ok - send the close message. */
2419 DEBUG(10,("enum_file_close_fn: request to close file %s, %s\n",
2420 sharepath,
2421 share_mode_str(talloc_tos(), 0, e) ));
2423 share_mode_entry_to_message(msg, e);
2425 r->out.result = ntstatus_to_werror(
2426 messaging_send_buf(smbd_messaging_context(),
2427 e->pid, MSG_SMB_CLOSE_FILE,
2428 (uint8 *)msg,
2429 MSG_SMB_SHARE_MODE_ENTRY_SIZE));
2432 /********************************************************************
2433 Close a file given a 32-bit file id.
2434 ********************************************************************/
2436 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2438 SE_PRIV se_diskop = SE_DISK_OPERATOR;
2439 bool is_disk_op;
2441 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2443 is_disk_op = user_has_privileges( p->server_info->ptok, &se_diskop );
2445 if (p->server_info->utok.uid != sec_initial_uid() && !is_disk_op) {
2446 return WERR_ACCESS_DENIED;
2449 /* enum_file_close_fn sends the close message to
2450 * the relevent smbd process. */
2452 r->out.result = WERR_BADFILE;
2453 share_mode_forall( enum_file_close_fn, (void *)r);
2454 return r->out.result;
2457 /********************************************************************
2458 ********************************************************************/
2460 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2462 p->rng_fault_state = True;
2463 return WERR_NOT_SUPPORTED;
2466 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2468 p->rng_fault_state = True;
2469 return WERR_NOT_SUPPORTED;
2472 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2474 p->rng_fault_state = True;
2475 return WERR_NOT_SUPPORTED;
2478 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2480 p->rng_fault_state = True;
2481 return WERR_NOT_SUPPORTED;
2484 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2486 p->rng_fault_state = True;
2487 return WERR_NOT_SUPPORTED;
2490 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2492 p->rng_fault_state = True;
2493 return WERR_NOT_SUPPORTED;
2496 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2498 p->rng_fault_state = True;
2499 return WERR_NOT_SUPPORTED;
2502 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2504 p->rng_fault_state = True;
2505 return WERR_NOT_SUPPORTED;
2508 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2510 p->rng_fault_state = True;
2511 return WERR_NOT_SUPPORTED;
2514 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2516 p->rng_fault_state = True;
2517 return WERR_NOT_SUPPORTED;
2520 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2522 p->rng_fault_state = True;
2523 return WERR_NOT_SUPPORTED;
2526 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2528 p->rng_fault_state = True;
2529 return WERR_NOT_SUPPORTED;
2532 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2534 p->rng_fault_state = True;
2535 return WERR_NOT_SUPPORTED;
2538 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2540 p->rng_fault_state = True;
2541 return WERR_NOT_SUPPORTED;
2544 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2546 p->rng_fault_state = True;
2547 return WERR_NOT_SUPPORTED;
2550 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2552 p->rng_fault_state = True;
2553 return WERR_NOT_SUPPORTED;
2556 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2558 p->rng_fault_state = True;
2559 return WERR_NOT_SUPPORTED;
2562 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2564 p->rng_fault_state = True;
2565 return WERR_NOT_SUPPORTED;
2568 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2570 p->rng_fault_state = True;
2571 return WERR_NOT_SUPPORTED;
2574 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2576 p->rng_fault_state = True;
2577 return WERR_NOT_SUPPORTED;
2580 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2582 p->rng_fault_state = True;
2583 return WERR_NOT_SUPPORTED;
2586 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2588 p->rng_fault_state = True;
2589 return WERR_NOT_SUPPORTED;
2592 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2594 p->rng_fault_state = True;
2595 return WERR_NOT_SUPPORTED;
2598 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2600 p->rng_fault_state = True;
2601 return WERR_NOT_SUPPORTED;
2604 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2606 p->rng_fault_state = True;
2607 return WERR_NOT_SUPPORTED;
2610 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2612 p->rng_fault_state = True;
2613 return WERR_NOT_SUPPORTED;
2616 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2618 p->rng_fault_state = True;
2619 return WERR_NOT_SUPPORTED;
2622 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
2624 p->rng_fault_state = True;
2625 return WERR_NOT_SUPPORTED;
2628 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2630 p->rng_fault_state = True;
2631 return WERR_NOT_SUPPORTED;
2634 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2636 p->rng_fault_state = True;
2637 return WERR_NOT_SUPPORTED;
2640 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2642 p->rng_fault_state = True;
2643 return WERR_NOT_SUPPORTED;
2646 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2648 p->rng_fault_state = True;
2649 return WERR_NOT_SUPPORTED;
2652 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2654 p->rng_fault_state = True;
2655 return WERR_NOT_SUPPORTED;
2658 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2660 p->rng_fault_state = True;
2661 return WERR_NOT_SUPPORTED;
2664 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2666 p->rng_fault_state = True;
2667 return WERR_NOT_SUPPORTED;