Revert "Arggh. Got the path/user the wrong way around. IDL is correct :-)."
[Samba.git] / source / rpc_server / srv_srvsvc_nt.c
blobebbc39c304f8079d4b5fb93d1b9041d9b04c4333
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 /***************************/
37 /* oops - this is going to take up a *massive* amount of stack. */
38 /* the UNISTR2s already have 1024 uint16 chars in them... */
40 #define MAX_SESS_ENTRIES 32
42 /***************************/
44 /* oops - this is going to take up a *massive* amount of stack. */
45 /* the UNISTR2s already have 1024 uint16 chars in them... */
46 #define MAX_CONN_ENTRIES 32
48 /* Use for enumerating connections, pipes, & files */
50 struct file_enum_count {
51 TALLOC_CTX *ctx;
52 const char *username;
53 struct srvsvc_NetFileCtr3 *ctr3;
56 struct sess_file_count {
57 struct server_id pid;
58 uid_t uid;
59 int count;
62 /****************************************************************************
63 Count the entries belonging to a service in the connection db.
64 ****************************************************************************/
66 static int pipe_enum_fn( struct db_record *rec, void *p)
68 struct pipe_open_rec prec;
69 struct file_enum_count *fenum = (struct file_enum_count *)p;
70 struct srvsvc_NetFileInfo3 *f;
71 int i = fenum->ctr3->count;
72 char *fullpath = NULL;
73 const char *username;
75 if (rec->value.dsize != sizeof(struct pipe_open_rec))
76 return 0;
78 memcpy(&prec, rec->value.dptr, sizeof(struct pipe_open_rec));
80 if ( !process_exists(prec.pid) ) {
81 return 0;
84 username = uidtoname(prec.uid);
86 if ((fenum->username != NULL)
87 && !strequal(username, fenum->username)) {
88 return 0;
91 fullpath = talloc_asprintf(fenum->ctx, "\\PIPE\\%s", prec.name );
92 if (!fullpath) {
93 return 1;
96 f = TALLOC_REALLOC_ARRAY(fenum->ctx, fenum->ctr3->array,
97 struct srvsvc_NetFileInfo3, i+1);
98 if ( !f ) {
99 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
100 return 1;
102 fenum->ctr3->array = f;
104 init_srvsvc_NetFileInfo3(&fenum->ctr3->array[i],
105 (uint32_t)((procid_to_pid(&prec.pid)<<16) & prec.pnum),
106 (FILE_READ_DATA|FILE_WRITE_DATA),
108 fullpath,
109 username);
111 fenum->ctr3->count++;
113 return 0;
116 /*******************************************************************
117 ********************************************************************/
119 static WERROR net_enum_pipes(TALLOC_CTX *ctx,
120 const char *username,
121 struct srvsvc_NetFileCtr3 **ctr3,
122 uint32_t resume )
124 struct file_enum_count fenum;
126 fenum.ctx = ctx;
127 fenum.username = username;
128 fenum.ctr3 = *ctr3;
130 if (connections_traverse(pipe_enum_fn, &fenum) == -1) {
131 DEBUG(0,("net_enum_pipes: traverse of connections.tdb "
132 "failed\n"));
133 return WERR_NOMEM;
136 *ctr3 = fenum.ctr3;
138 return WERR_OK;
141 /*******************************************************************
142 ********************************************************************/
144 static void enum_file_fn( const struct share_mode_entry *e,
145 const char *sharepath, const char *fname,
146 void *private_data )
148 struct file_enum_count *fenum =
149 (struct file_enum_count *)private_data;
151 struct srvsvc_NetFileInfo3 *f;
152 int i = fenum->ctr3->count;
153 files_struct fsp;
154 struct byte_range_lock *brl;
155 int num_locks = 0;
156 char *fullpath = NULL;
157 uint32 permissions;
158 const char *username;
160 /* If the pid was not found delete the entry from connections.tdb */
162 if ( !process_exists(e->pid) ) {
163 return;
166 username = uidtoname(e->uid);
168 if ((fenum->username != NULL)
169 && !strequal(username, fenum->username)) {
170 return;
173 f = TALLOC_REALLOC_ARRAY(fenum->ctx, fenum->ctr3->array,
174 struct srvsvc_NetFileInfo3, i+1);
175 if ( !f ) {
176 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
177 return;
179 fenum->ctr3->array = f;
181 /* need to count the number of locks on a file */
183 ZERO_STRUCT( fsp );
184 fsp.file_id = e->id;
186 if ( (brl = brl_get_locks(talloc_tos(), &fsp)) != NULL ) {
187 num_locks = brl->num_locks;
188 TALLOC_FREE(brl);
191 if ( strcmp( fname, "." ) == 0 ) {
192 fullpath = talloc_asprintf(fenum->ctx, "C:%s", sharepath );
193 } else {
194 fullpath = talloc_asprintf(fenum->ctx, "C:%s/%s",
195 sharepath, fname );
197 if (!fullpath) {
198 return;
200 string_replace( fullpath, '/', '\\' );
202 /* mask out create (what ever that is) */
203 permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
205 /* now fill in the srvsvc_NetFileInfo3 struct */
206 init_srvsvc_NetFileInfo3(&fenum->ctr3->array[i],
207 e->share_file_id,
208 permissions,
209 num_locks,
210 fullpath,
211 username);
212 fenum->ctr3->count++;
215 /*******************************************************************
216 ********************************************************************/
218 static WERROR net_enum_files(TALLOC_CTX *ctx,
219 const char *username,
220 struct srvsvc_NetFileCtr3 **ctr3,
221 uint32_t resume)
223 struct file_enum_count f_enum_cnt;
225 f_enum_cnt.ctx = ctx;
226 f_enum_cnt.username = username;
227 f_enum_cnt.ctr3 = *ctr3;
229 share_mode_forall( enum_file_fn, (void *)&f_enum_cnt );
231 *ctr3 = f_enum_cnt.ctr3;
233 return WERR_OK;
236 /*******************************************************************
237 Utility function to get the 'type' of a share from an snum.
238 ********************************************************************/
239 static uint32 get_share_type(int snum)
241 /* work out the share type */
242 uint32 type = STYPE_DISKTREE;
244 if (lp_print_ok(snum))
245 type = STYPE_PRINTQ;
246 if (strequal(lp_fstype(snum), "IPC"))
247 type = STYPE_IPC;
248 if (lp_administrative_share(snum))
249 type |= STYPE_HIDDEN;
251 return type;
254 /*******************************************************************
255 Fill in a share info level 0 structure.
256 ********************************************************************/
258 static void init_srv_share_info_0(pipes_struct *p, struct srvsvc_NetShareInfo0 *r, int snum)
260 const char *net_name = lp_servicename(snum);
262 init_srvsvc_NetShareInfo0(r, net_name);
265 /*******************************************************************
266 Fill in a share info level 1 structure.
267 ********************************************************************/
269 static void init_srv_share_info_1(pipes_struct *p, struct srvsvc_NetShareInfo1 *r, int snum)
271 char *net_name = lp_servicename(snum);
272 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
274 if (remark) {
275 remark = standard_sub_conn(p->mem_ctx,
276 p->conn,
277 remark);
280 init_srvsvc_NetShareInfo1(r, net_name,
281 get_share_type(snum),
282 remark ? remark : "");
285 /*******************************************************************
286 Fill in a share info level 2 structure.
287 ********************************************************************/
289 static void init_srv_share_info_2(pipes_struct *p, struct srvsvc_NetShareInfo2 *r, int snum)
291 char *remark = NULL;
292 char *path = NULL;
293 int max_connections = lp_max_connections(snum);
294 uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
295 int count = 0;
296 char *net_name = lp_servicename(snum);
298 remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
299 if (remark) {
300 remark = standard_sub_conn(p->mem_ctx,
301 p->conn,
302 remark);
304 path = talloc_asprintf(p->mem_ctx,
305 "C:%s", lp_pathname(snum));
307 if (path) {
309 * Change / to \\ so that win2k will see it as a valid path.
310 * This was added to enable use of browsing in win2k add
311 * share dialog.
314 string_replace(path, '/', '\\');
317 count = count_current_connections(net_name, false);
319 init_srvsvc_NetShareInfo2(r, net_name,
320 get_share_type(snum),
321 remark ? remark : "",
323 max_uses,
324 count,
325 path ? path : "",
326 "");
329 /*******************************************************************
330 Map any generic bits to file specific bits.
331 ********************************************************************/
333 static void map_generic_share_sd_bits(SEC_DESC *psd)
335 int i;
336 SEC_ACL *ps_dacl = NULL;
338 if (!psd)
339 return;
341 ps_dacl = psd->dacl;
342 if (!ps_dacl)
343 return;
345 for (i = 0; i < ps_dacl->num_aces; i++) {
346 SEC_ACE *psa = &ps_dacl->aces[i];
347 uint32 orig_mask = psa->access_mask;
349 se_map_generic(&psa->access_mask, &file_generic_mapping);
350 psa->access_mask |= orig_mask;
354 /*******************************************************************
355 Fill in a share info level 501 structure.
356 ********************************************************************/
358 static void init_srv_share_info_501(pipes_struct *p, struct srvsvc_NetShareInfo501 *r, int snum)
360 const char *net_name = lp_servicename(snum);
361 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
363 if (remark) {
364 remark = standard_sub_conn(p->mem_ctx, p->conn, remark);
367 init_srvsvc_NetShareInfo501(r, net_name,
368 get_share_type(snum),
369 remark ? remark : "",
370 (lp_csc_policy(snum) << 4));
373 /*******************************************************************
374 Fill in a share info level 502 structure.
375 ********************************************************************/
377 static void init_srv_share_info_502(pipes_struct *p, struct srvsvc_NetShareInfo502 *r, int snum)
379 const char *net_name = lp_servicename(snum);
380 char *path = NULL;
381 SEC_DESC *sd = NULL;
382 struct sec_desc_buf *sd_buf = NULL;
383 size_t sd_size = 0;
384 TALLOC_CTX *ctx = p->mem_ctx;
385 char *remark = talloc_strdup(ctx, lp_comment(snum));;
387 if (remark) {
388 remark = standard_sub_conn(ctx, p->conn, remark);
390 path = talloc_asprintf(ctx, "C:%s", lp_pathname(snum));
391 if (path) {
393 * Change / to \\ so that win2k will see it as a valid path. This was added to
394 * enable use of browsing in win2k add share dialog.
396 string_replace(path, '/', '\\');
399 sd = get_share_security(ctx, lp_servicename(snum), &sd_size);
401 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
403 init_srvsvc_NetShareInfo502(r, net_name,
404 get_share_type(snum),
405 remark ? remark : "",
407 (uint32_t)-1,
409 path ? path : "",
411 sd_buf);
414 /***************************************************************************
415 Fill in a share info level 1004 structure.
416 ***************************************************************************/
418 static void init_srv_share_info_1004(pipes_struct *p, struct srvsvc_NetShareInfo1004 *r, int snum)
420 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
422 if (remark) {
423 remark = standard_sub_conn(p->mem_ctx, p->conn, remark);
426 init_srvsvc_NetShareInfo1004(r, remark ? remark : "");
429 /***************************************************************************
430 Fill in a share info level 1005 structure.
431 ***************************************************************************/
433 static void init_srv_share_info_1005(pipes_struct *p, struct srvsvc_NetShareInfo1005 *r, int snum)
435 uint32_t dfs_flags = 0;
437 if (lp_host_msdfs() && lp_msdfs_root(snum)) {
438 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
441 dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
443 init_srvsvc_NetShareInfo1005(r, dfs_flags);
446 /***************************************************************************
447 Fill in a share info level 1006 structure.
448 ***************************************************************************/
450 static void init_srv_share_info_1006(pipes_struct *p, struct srvsvc_NetShareInfo1006 *r, int snum)
452 init_srvsvc_NetShareInfo1006(r, (uint32_t)-1);
455 /***************************************************************************
456 Fill in a share info level 1007 structure.
457 ***************************************************************************/
459 static void init_srv_share_info_1007(pipes_struct *p, struct srvsvc_NetShareInfo1007 *r, int snum)
461 uint32 flags = 0;
463 init_srvsvc_NetShareInfo1007(r, flags, "");
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 Fill in a share info structure.
494 ********************************************************************/
496 static WERROR init_srv_share_info_ctr(pipes_struct *p,
497 struct srvsvc_NetShareInfoCtr *info_ctr,
498 uint32_t *resume_handle_p,
499 uint32_t *total_entries,
500 bool all_shares)
502 int num_entries = 0;
503 int alloc_entries = 0;
504 int num_services = 0;
505 int snum;
506 TALLOC_CTX *ctx = p->mem_ctx;
507 int i = 0;
508 int valid_share_count = 0;
509 union srvsvc_NetShareCtr ctr;
510 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
512 DEBUG(5,("init_srv_share_info_ctr\n"));
514 /* Ensure all the usershares are loaded. */
515 become_root();
516 load_usershare_shares();
517 load_registry_shares();
518 num_services = lp_numservices();
519 unbecome_root();
521 /* Count the number of entries. */
522 for (snum = 0; snum < num_services; snum++) {
523 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
524 DEBUG(10, ("counting service %s\n", lp_servicename(snum)));
525 num_entries++;
526 } else {
527 DEBUG(10, ("NOT counting service %s\n", lp_servicename(snum)));
531 if (!num_entries || (resume_handle >= num_entries)) {
532 return WERR_OK;
535 /* Calculate alloc entries. */
536 alloc_entries = num_entries - resume_handle;
537 switch (info_ctr->level) {
538 case 0:
539 ctr.ctr0 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr0);
540 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
542 ctr.ctr0->count = alloc_entries;
543 ctr.ctr0->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
544 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
546 for (snum = 0; snum < num_services; snum++) {
547 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
548 (resume_handle <= (i + valid_share_count++)) ) {
549 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
553 break;
555 case 1:
556 ctr.ctr1 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1);
557 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
559 ctr.ctr1->count = alloc_entries;
560 ctr.ctr1->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
561 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
563 for (snum = 0; snum < num_services; snum++) {
564 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
565 (resume_handle <= (i + valid_share_count++)) ) {
566 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
570 break;
572 case 2:
573 ctr.ctr2 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr2);
574 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
576 ctr.ctr2->count = alloc_entries;
577 ctr.ctr2->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
578 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
580 for (snum = 0; snum < num_services; snum++) {
581 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
582 (resume_handle <= (i + valid_share_count++)) ) {
583 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
587 break;
589 case 501:
590 ctr.ctr501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr501);
591 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
593 ctr.ctr501->count = alloc_entries;
594 ctr.ctr501->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
595 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
597 for (snum = 0; snum < num_services; snum++) {
598 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
599 (resume_handle <= (i + valid_share_count++)) ) {
600 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
604 break;
606 case 502:
607 ctr.ctr502 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr502);
608 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
610 ctr.ctr502->count = alloc_entries;
611 ctr.ctr502->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
612 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
614 for (snum = 0; snum < num_services; snum++) {
615 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
616 (resume_handle <= (i + valid_share_count++)) ) {
617 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
621 break;
623 case 1004:
624 ctr.ctr1004 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1004);
625 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
627 ctr.ctr1004->count = alloc_entries;
628 ctr.ctr1004->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
629 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
631 for (snum = 0; snum < num_services; snum++) {
632 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
633 (resume_handle <= (i + valid_share_count++)) ) {
634 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
638 break;
640 case 1005:
641 ctr.ctr1005 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1005);
642 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
644 ctr.ctr1005->count = alloc_entries;
645 ctr.ctr1005->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
646 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
648 for (snum = 0; snum < num_services; snum++) {
649 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
650 (resume_handle <= (i + valid_share_count++)) ) {
651 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
655 break;
657 case 1006:
658 ctr.ctr1006 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1006);
659 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
661 ctr.ctr1006->count = alloc_entries;
662 ctr.ctr1006->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
663 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
665 for (snum = 0; snum < num_services; snum++) {
666 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
667 (resume_handle <= (i + valid_share_count++)) ) {
668 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
672 break;
674 case 1007:
675 ctr.ctr1007 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1007);
676 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
678 ctr.ctr1007->count = alloc_entries;
679 ctr.ctr1007->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
680 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
682 for (snum = 0; snum < num_services; snum++) {
683 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
684 (resume_handle <= (i + valid_share_count++)) ) {
685 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
689 break;
691 case 1501:
692 ctr.ctr1501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1501);
693 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
695 ctr.ctr1501->count = alloc_entries;
696 ctr.ctr1501->array = TALLOC_ZERO_ARRAY(ctx, struct sec_desc_buf, alloc_entries);
697 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
699 for (snum = 0; snum < num_services; snum++) {
700 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
701 (resume_handle <= (i + valid_share_count++)) ) {
702 init_srv_share_info_1501(p, &ctr.ctr1501->array[i++], snum);
706 break;
708 default:
709 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
710 info_ctr->level));
711 return WERR_UNKNOWN_LEVEL;
714 *total_entries = alloc_entries;
715 if (resume_handle_p) {
716 if (all_shares) {
717 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
718 } else {
719 *resume_handle_p = num_entries;
723 info_ctr->ctr = ctr;
725 return WERR_OK;
728 /*******************************************************************
729 fill in a sess info level 0 structure.
730 ********************************************************************/
732 static WERROR init_srv_sess_info_0(pipes_struct *p,
733 struct srvsvc_NetSessCtr0 *ctr0,
734 uint32_t *resume_handle_p,
735 uint32_t *total_entries)
737 struct sessionid *session_list;
738 uint32_t num_entries = 0;
739 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
740 *total_entries = list_sessions(p->mem_ctx, &session_list);
742 DEBUG(5,("init_srv_sess_info_0\n"));
744 if (ctr0 == NULL) {
745 if (resume_handle_p) {
746 *resume_handle_p = 0;
748 return WERR_OK;
751 for (; resume_handle < *total_entries && num_entries < MAX_SESS_ENTRIES; resume_handle++) {
753 ctr0->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
754 ctr0->array,
755 struct srvsvc_NetSessInfo0,
756 num_entries+1);
757 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
759 init_srvsvc_NetSessInfo0(&ctr0->array[num_entries],
760 session_list[resume_handle].remote_machine);
761 num_entries++;
764 ctr0->count = num_entries;
766 if (resume_handle_p) {
767 if (*resume_handle_p >= *total_entries) {
768 *resume_handle_p = 0;
769 } else {
770 *resume_handle_p = resume_handle;
774 return WERR_OK;
777 /*******************************************************************
778 ********************************************************************/
780 static void sess_file_fn( const struct share_mode_entry *e,
781 const char *sharepath, const char *fname,
782 void *data )
784 struct sess_file_count *sess = (struct sess_file_count *)data;
786 if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
787 sess->count++;
790 return;
793 /*******************************************************************
794 ********************************************************************/
796 static int net_count_files( uid_t uid, struct server_id pid )
798 struct sess_file_count s_file_cnt;
800 s_file_cnt.count = 0;
801 s_file_cnt.uid = uid;
802 s_file_cnt.pid = pid;
804 share_mode_forall( sess_file_fn, &s_file_cnt );
806 return s_file_cnt.count;
809 /*******************************************************************
810 fill in a sess info level 1 structure.
811 ********************************************************************/
813 static WERROR init_srv_sess_info_1(pipes_struct *p,
814 struct srvsvc_NetSessCtr1 *ctr1,
815 uint32_t *resume_handle_p,
816 uint32_t *total_entries)
818 struct sessionid *session_list;
819 uint32_t num_entries = 0;
820 time_t now = time(NULL);
821 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
823 ZERO_STRUCTP(ctr1);
825 if (ctr1 == NULL) {
826 if (resume_handle_p) {
827 *resume_handle_p = 0;
829 return WERR_OK;
832 *total_entries = list_sessions(p->mem_ctx, &session_list);
834 for (; resume_handle < *total_entries && num_entries < MAX_SESS_ENTRIES; resume_handle++) {
835 uint32 num_files;
836 uint32 connect_time;
837 struct passwd *pw = sys_getpwnam(session_list[resume_handle].username);
838 bool guest;
840 if ( !pw ) {
841 DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
842 session_list[resume_handle].username));
843 continue;
846 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
847 num_files = net_count_files(pw->pw_uid, session_list[resume_handle].pid);
848 guest = strequal( session_list[resume_handle].username, lp_guestaccount() );
850 ctr1->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
851 ctr1->array,
852 struct srvsvc_NetSessInfo1,
853 num_entries+1);
854 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
856 init_srvsvc_NetSessInfo1(&ctr1->array[num_entries],
857 session_list[resume_handle].remote_machine,
858 session_list[resume_handle].username,
859 num_files,
860 connect_time,
862 guest);
863 num_entries++;
866 ctr1->count = num_entries;
868 if (resume_handle_p) {
869 if (*resume_handle_p >= *total_entries) {
870 *resume_handle_p = 0;
871 } else {
872 *resume_handle_p = resume_handle;
876 return WERR_OK;
879 /*******************************************************************
880 fill in a conn info level 0 structure.
881 ********************************************************************/
883 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
884 uint32_t *resume_handle_p,
885 uint32_t *total_entries)
887 uint32_t num_entries = 0;
888 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
890 DEBUG(5,("init_srv_conn_info_0\n"));
892 if (ctr0 == NULL) {
893 if (resume_handle_p) {
894 *resume_handle_p = 0;
896 return WERR_OK;
899 *total_entries = 1;
901 ZERO_STRUCTP(ctr0);
903 for (; resume_handle < *total_entries && num_entries < MAX_CONN_ENTRIES; resume_handle++) {
905 ctr0->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
906 ctr0->array,
907 struct srvsvc_NetConnInfo0,
908 num_entries+1);
909 if (!ctr0->array) {
910 return WERR_NOMEM;
913 init_srvsvc_NetConnInfo0(&ctr0->array[num_entries],
914 (*total_entries));
916 /* move on to creating next connection */
917 num_entries++;
920 ctr0->count = num_entries;
921 *total_entries = num_entries;
923 if (resume_handle_p) {
924 if (*resume_handle_p >= *total_entries) {
925 *resume_handle_p = 0;
926 } else {
927 *resume_handle_p = resume_handle;
931 return WERR_OK;
934 /*******************************************************************
935 fill in a conn info level 1 structure.
936 ********************************************************************/
938 static WERROR init_srv_conn_info_1(struct srvsvc_NetConnCtr1 *ctr1,
939 uint32_t *resume_handle_p,
940 uint32_t *total_entries)
942 uint32_t num_entries = 0;
943 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
945 DEBUG(5,("init_srv_conn_info_1\n"));
947 if (ctr1 == NULL) {
948 if (resume_handle_p) {
949 *resume_handle_p = 0;
951 return WERR_OK;
954 *total_entries = 1;
956 ZERO_STRUCTP(ctr1);
958 for (; (resume_handle < *total_entries) && num_entries < MAX_CONN_ENTRIES; resume_handle++) {
960 ctr1->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
961 ctr1->array,
962 struct srvsvc_NetConnInfo1,
963 num_entries+1);
964 if (!ctr1->array) {
965 return WERR_NOMEM;
968 init_srvsvc_NetConnInfo1(&ctr1->array[num_entries],
969 (*total_entries),
970 0x3,
974 "dummy_user",
975 "IPC$");
977 /* move on to creating next connection */
978 num_entries++;
981 ctr1->count = num_entries;
982 *total_entries = num_entries;
984 if (resume_handle_p) {
985 if (*resume_handle_p >= *total_entries) {
986 *resume_handle_p = 0;
987 } else {
988 *resume_handle_p = resume_handle;
992 return WERR_OK;
995 /*******************************************************************
996 _srvsvc_NetFileEnum
997 *******************************************************************/
999 WERROR _srvsvc_NetFileEnum(pipes_struct *p,
1000 struct srvsvc_NetFileEnum *r)
1002 TALLOC_CTX *ctx = NULL;
1003 struct srvsvc_NetFileCtr3 *ctr3;
1004 uint32_t resume_hnd = 0;
1005 WERROR werr;
1007 switch (r->in.info_ctr->level) {
1008 case 3:
1009 break;
1010 default:
1011 return WERR_UNKNOWN_LEVEL;
1014 ctx = talloc_tos();
1015 ctr3 = r->in.info_ctr->ctr.ctr3;
1016 if (!ctr3) {
1017 werr = WERR_INVALID_PARAM;
1018 goto done;
1021 /* TODO -- Windows enumerates
1022 (b) active pipes
1023 (c) open directories and files */
1025 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1026 if (!W_ERROR_IS_OK(werr)) {
1027 goto done;
1030 werr = net_enum_pipes(ctx, r->in.user, &ctr3, resume_hnd);
1031 if (!W_ERROR_IS_OK(werr)) {
1032 goto done;
1035 *r->out.totalentries = ctr3->count;
1036 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1037 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1039 werr = WERR_OK;
1041 done:
1042 return werr;
1045 /*******************************************************************
1046 _srvsvc_NetSrvGetInfo
1047 ********************************************************************/
1049 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p,
1050 struct srvsvc_NetSrvGetInfo *r)
1052 WERROR status = WERR_OK;
1054 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1056 if (!pipe_access_check(p)) {
1057 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1058 return WERR_ACCESS_DENIED;
1061 switch (r->in.level) {
1063 /* Technically level 102 should only be available to
1064 Administrators but there isn't anything super-secret
1065 here, as most of it is made up. */
1067 case 102: {
1068 struct srvsvc_NetSrvInfo102 *info102;
1070 info102 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1071 if (!info102) {
1072 return WERR_NOMEM;
1075 init_srvsvc_NetSrvInfo102(info102,
1076 PLATFORM_ID_NT,
1077 global_myname(),
1078 lp_major_announce_version(),
1079 lp_minor_announce_version(),
1080 lp_default_server_announce(),
1081 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
1082 0xffffffff, /* users */
1083 0xf, /* disc */
1084 0, /* hidden */
1085 240, /* announce */
1086 3000, /* announce delta */
1087 100000, /* licenses */
1088 "c:\\"); /* user path */
1089 r->out.info->info102 = info102;
1090 break;
1092 case 101: {
1093 struct srvsvc_NetSrvInfo101 *info101;
1095 info101 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1096 if (!info101) {
1097 return WERR_NOMEM;
1100 init_srvsvc_NetSrvInfo101(info101,
1101 PLATFORM_ID_NT,
1102 global_myname(),
1103 lp_major_announce_version(),
1104 lp_minor_announce_version(),
1105 lp_default_server_announce(),
1106 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1107 r->out.info->info101 = info101;
1108 break;
1110 case 100: {
1111 struct srvsvc_NetSrvInfo100 *info100;
1113 info100 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1114 if (!info100) {
1115 return WERR_NOMEM;
1118 init_srvsvc_NetSrvInfo100(info100,
1119 PLATFORM_ID_NT,
1120 global_myname());
1121 r->out.info->info100 = info100;
1123 break;
1125 default:
1126 status = WERR_UNKNOWN_LEVEL;
1127 break;
1130 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1132 return status;
1135 /*******************************************************************
1136 _srvsvc_NetSrvSetInfo
1137 ********************************************************************/
1139 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p,
1140 struct srvsvc_NetSrvSetInfo *r)
1142 WERROR status = WERR_OK;
1144 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1146 /* Set up the net server set info structure. */
1148 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1150 return status;
1153 /*******************************************************************
1154 _srvsvc_NetConnEnum
1155 ********************************************************************/
1157 WERROR _srvsvc_NetConnEnum(pipes_struct *p,
1158 struct srvsvc_NetConnEnum *r)
1160 WERROR werr;
1162 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1164 switch (r->in.info_ctr->level) {
1165 case 0:
1166 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1167 r->in.resume_handle,
1168 r->out.totalentries);
1169 break;
1170 case 1:
1171 werr = init_srv_conn_info_1(r->in.info_ctr->ctr.ctr1,
1172 r->in.resume_handle,
1173 r->out.totalentries);
1174 break;
1175 default:
1176 return WERR_UNKNOWN_LEVEL;
1179 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1181 return werr;
1184 /*******************************************************************
1185 _srvsvc_NetSessEnum
1186 ********************************************************************/
1188 WERROR _srvsvc_NetSessEnum(pipes_struct *p,
1189 struct srvsvc_NetSessEnum *r)
1191 WERROR werr;
1193 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1195 switch (r->in.info_ctr->level) {
1196 case 0:
1197 werr = init_srv_sess_info_0(p,
1198 r->in.info_ctr->ctr.ctr0,
1199 r->in.resume_handle,
1200 r->out.totalentries);
1201 break;
1202 case 1:
1203 werr = init_srv_sess_info_1(p,
1204 r->in.info_ctr->ctr.ctr1,
1205 r->in.resume_handle,
1206 r->out.totalentries);
1207 break;
1208 default:
1209 return WERR_UNKNOWN_LEVEL;
1212 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1214 return werr;
1217 /*******************************************************************
1218 _srvsvc_NetSessDel
1219 ********************************************************************/
1221 WERROR _srvsvc_NetSessDel(pipes_struct *p,
1222 struct srvsvc_NetSessDel *r)
1224 struct sessionid *session_list;
1225 struct current_user user;
1226 int num_sessions, snum;
1227 const char *username;
1228 const char *machine;
1229 bool not_root = False;
1230 WERROR werr;
1232 username = r->in.user;
1233 machine = r->in.client;
1235 /* strip leading backslashes if any */
1236 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1237 machine += 2;
1240 num_sessions = list_sessions(p->mem_ctx, &session_list);
1242 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1244 werr = WERR_ACCESS_DENIED;
1246 get_current_user(&user, p);
1248 /* fail out now if you are not root or not a domain admin */
1250 if ((user.ut.uid != sec_initial_uid()) &&
1251 ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
1253 goto done;
1256 for (snum = 0; snum < num_sessions; snum++) {
1258 if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
1259 strequal(session_list[snum].remote_machine, machine)) {
1261 NTSTATUS ntstat;
1263 if (user.ut.uid != sec_initial_uid()) {
1264 not_root = True;
1265 become_root();
1268 ntstat = messaging_send(smbd_messaging_context(),
1269 session_list[snum].pid,
1270 MSG_SHUTDOWN, &data_blob_null);
1272 if (NT_STATUS_IS_OK(ntstat))
1273 werr = WERR_OK;
1275 if (not_root)
1276 unbecome_root();
1280 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1282 done:
1284 return werr;
1287 /*******************************************************************
1288 _srvsvc_NetShareEnumAll
1289 ********************************************************************/
1291 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p,
1292 struct srvsvc_NetShareEnumAll *r)
1294 WERROR werr;
1296 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1298 if (!pipe_access_check(p)) {
1299 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1300 return WERR_ACCESS_DENIED;
1303 /* Create the list of shares for the response. */
1304 werr = init_srv_share_info_ctr(p,
1305 r->in.info_ctr,
1306 r->in.resume_handle,
1307 r->out.totalentries,
1308 true);
1310 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1312 return werr;
1315 /*******************************************************************
1316 _srvsvc_NetShareEnum
1317 ********************************************************************/
1319 WERROR _srvsvc_NetShareEnum(pipes_struct *p,
1320 struct srvsvc_NetShareEnum *r)
1322 WERROR werr;
1324 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1326 if (!pipe_access_check(p)) {
1327 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1328 return WERR_ACCESS_DENIED;
1331 /* Create the list of shares for the response. */
1332 werr = init_srv_share_info_ctr(p,
1333 r->in.info_ctr,
1334 r->in.resume_handle,
1335 r->out.totalentries,
1336 false);
1338 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1340 return werr;
1343 /*******************************************************************
1344 _srvsvc_NetShareGetInfo
1345 ********************************************************************/
1347 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p,
1348 struct srvsvc_NetShareGetInfo *r)
1350 WERROR status = WERR_OK;
1351 fstring share_name;
1352 int snum;
1353 union srvsvc_NetShareInfo *info = r->out.info;
1355 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1357 fstrcpy(share_name, r->in.share_name);
1359 snum = find_service(share_name);
1360 if (snum < 0) {
1361 return WERR_INVALID_NAME;
1364 switch (r->in.level) {
1365 case 0:
1366 info->info0 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo0);
1367 W_ERROR_HAVE_NO_MEMORY(info->info0);
1368 init_srv_share_info_0(p, info->info0, snum);
1369 break;
1370 case 1:
1371 info->info1 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1);
1372 W_ERROR_HAVE_NO_MEMORY(info->info1);
1373 init_srv_share_info_1(p, info->info1, snum);
1374 break;
1375 case 2:
1376 info->info2 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo2);
1377 W_ERROR_HAVE_NO_MEMORY(info->info2);
1378 init_srv_share_info_2(p, info->info2, snum);
1379 break;
1380 case 501:
1381 info->info501 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo501);
1382 W_ERROR_HAVE_NO_MEMORY(info->info501);
1383 init_srv_share_info_501(p, info->info501, snum);
1384 break;
1385 case 502:
1386 info->info502 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo502);
1387 W_ERROR_HAVE_NO_MEMORY(info->info502);
1388 init_srv_share_info_502(p, info->info502, snum);
1389 break;
1390 case 1004:
1391 info->info1004 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1392 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1393 init_srv_share_info_1004(p, info->info1004, snum);
1394 break;
1395 case 1005:
1396 info->info1005 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1397 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1398 init_srv_share_info_1005(p, info->info1005, snum);
1399 break;
1400 case 1006:
1401 info->info1006 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1402 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1403 init_srv_share_info_1006(p, info->info1006, snum);
1404 break;
1405 case 1007:
1406 info->info1007 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1407 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1408 init_srv_share_info_1007(p, info->info1007, snum);
1409 break;
1410 case 1501:
1411 init_srv_share_info_1501(p, info->info1501, snum);
1412 break;
1413 default:
1414 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1415 r->in.level));
1416 status = WERR_UNKNOWN_LEVEL;
1417 break;
1420 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1422 return status;
1425 /*******************************************************************
1426 Check a given DOS pathname is valid for a share.
1427 ********************************************************************/
1429 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
1431 char *ptr = NULL;
1433 if (!dos_pathname) {
1434 return NULL;
1437 ptr = talloc_strdup(ctx, dos_pathname);
1438 if (!ptr) {
1439 return NULL;
1441 /* Convert any '\' paths to '/' */
1442 unix_format(ptr);
1443 ptr = unix_clean_name(ctx, ptr);
1444 if (!ptr) {
1445 return NULL;
1448 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1449 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
1450 ptr += 2;
1452 /* Only absolute paths allowed. */
1453 if (*ptr != '/')
1454 return NULL;
1456 return ptr;
1459 /*******************************************************************
1460 _srvsvc_NetShareSetInfo. Modify share details.
1461 ********************************************************************/
1463 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p,
1464 struct srvsvc_NetShareSetInfo *r)
1466 struct current_user user;
1467 char *command = NULL;
1468 char *share_name = NULL;
1469 char *comment = NULL;
1470 const char *pathname = NULL;
1471 int type;
1472 int snum;
1473 int ret;
1474 char *path = NULL;
1475 SEC_DESC *psd = NULL;
1476 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1477 bool is_disk_op = False;
1478 int max_connections = 0;
1479 TALLOC_CTX *ctx = p->mem_ctx;
1480 union srvsvc_NetShareInfo *info = r->in.info;
1482 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1484 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1485 if (!share_name) {
1486 return WERR_NOMEM;
1489 if (r->out.parm_error) {
1490 *r->out.parm_error = 0;
1493 if ( strequal(share_name,"IPC$")
1494 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1495 || strequal(share_name,"global") )
1497 return WERR_ACCESS_DENIED;
1500 snum = find_service(share_name);
1502 /* Does this share exist ? */
1503 if (snum < 0)
1504 return WERR_NET_NAME_NOT_FOUND;
1506 /* No change to printer shares. */
1507 if (lp_print_ok(snum))
1508 return WERR_ACCESS_DENIED;
1510 get_current_user(&user,p);
1512 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1514 /* fail out now if you are not root and not a disk op */
1516 if ( user.ut.uid != sec_initial_uid() && !is_disk_op )
1517 return WERR_ACCESS_DENIED;
1519 switch (r->in.level) {
1520 case 1:
1521 pathname = talloc_strdup(ctx, lp_pathname(snum));
1522 comment = talloc_strdup(ctx, info->info1->comment);
1523 type = info->info1->type;
1524 psd = NULL;
1525 break;
1526 case 2:
1527 comment = talloc_strdup(ctx, info->info2->comment);
1528 pathname = info->info2->path;
1529 type = info->info2->type;
1530 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1531 0 : info->info2->max_users;
1532 psd = NULL;
1533 break;
1534 #if 0
1535 /* not supported on set but here for completeness */
1536 case 501:
1537 comment = talloc_strdup(ctx, info->info501->comment);
1538 type = info->info501->type;
1539 psd = NULL;
1540 break;
1541 #endif
1542 case 502:
1543 comment = talloc_strdup(ctx, info->info502->comment);
1544 pathname = info->info502->path;
1545 type = info->info502->type;
1546 psd = info->info502->sd_buf.sd;
1547 map_generic_share_sd_bits(psd);
1548 break;
1549 case 1004:
1550 pathname = talloc_strdup(ctx, lp_pathname(snum));
1551 comment = talloc_strdup(ctx, info->info1004->comment);
1552 type = STYPE_DISKTREE;
1553 break;
1554 case 1005:
1555 /* XP re-sets the csc policy even if it wasn't changed by the
1556 user, so we must compare it to see if it's what is set in
1557 smb.conf, so that we can contine other ops like setting
1558 ACLs on a share */
1559 if (((info->info1005->dfs_flags &
1560 SHARE_1005_CSC_POLICY_MASK) >>
1561 SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1562 return WERR_OK;
1563 else {
1564 DEBUG(3, ("_srvsvc_NetShareSetInfo: client is trying to change csc policy from the network; must be done with smb.conf\n"));
1565 return WERR_ACCESS_DENIED;
1567 case 1006:
1568 case 1007:
1569 return WERR_ACCESS_DENIED;
1570 case 1501:
1571 pathname = talloc_strdup(ctx, lp_pathname(snum));
1572 comment = talloc_strdup(ctx, lp_comment(snum));
1573 psd = info->info1501->sd;
1574 map_generic_share_sd_bits(psd);
1575 type = STYPE_DISKTREE;
1576 break;
1577 default:
1578 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1579 r->in.level));
1580 return WERR_UNKNOWN_LEVEL;
1583 /* We can only modify disk shares. */
1584 if (type != STYPE_DISKTREE)
1585 return WERR_ACCESS_DENIED;
1587 if (comment == NULL) {
1588 return WERR_NOMEM;
1591 /* Check if the pathname is valid. */
1592 if (!(path = valid_share_pathname(p->mem_ctx, pathname )))
1593 return WERR_OBJECT_PATH_INVALID;
1595 /* Ensure share name, pathname and comment don't contain '"' characters. */
1596 string_replace(share_name, '"', ' ');
1597 string_replace(path, '"', ' ');
1598 string_replace(comment, '"', ' ');
1600 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1601 lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1603 /* Only call modify function if something changed. */
1605 if (strcmp(path, lp_pathname(snum)) || strcmp(comment, lp_comment(snum))
1606 || (lp_max_connections(snum) != max_connections)) {
1607 if (!lp_change_share_cmd() || !*lp_change_share_cmd()) {
1608 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1609 return WERR_ACCESS_DENIED;
1612 command = talloc_asprintf(p->mem_ctx,
1613 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1614 lp_change_share_cmd(),
1615 get_dyn_CONFIGFILE(),
1616 share_name,
1617 path,
1618 comment ? comment : "",
1619 max_connections);
1620 if (!command) {
1621 return WERR_NOMEM;
1624 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1626 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1628 if (is_disk_op)
1629 become_root();
1631 if ( (ret = smbrun(command, NULL)) == 0 ) {
1632 /* Tell everyone we updated smb.conf. */
1633 message_send_all(smbd_messaging_context(),
1634 MSG_SMB_CONF_UPDATED, NULL, 0,
1635 NULL);
1638 if ( is_disk_op )
1639 unbecome_root();
1641 /********* END SeDiskOperatorPrivilege BLOCK *********/
1643 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1644 command, ret ));
1646 TALLOC_FREE(command);
1648 if ( ret != 0 )
1649 return WERR_ACCESS_DENIED;
1650 } else {
1651 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1652 share_name ));
1655 /* Replace SD if changed. */
1656 if (psd) {
1657 SEC_DESC *old_sd;
1658 size_t sd_size;
1660 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum), &sd_size);
1662 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1663 if (!set_share_security(share_name, psd))
1664 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1665 share_name ));
1669 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1671 return WERR_OK;
1674 /*******************************************************************
1675 _srvsvc_NetShareAdd.
1676 Call 'add_share_command "sharename" "pathname"
1677 "comment" "max connections = "
1678 ********************************************************************/
1680 WERROR _srvsvc_NetShareAdd(pipes_struct *p,
1681 struct srvsvc_NetShareAdd *r)
1683 struct current_user user;
1684 char *command = NULL;
1685 char *share_name = NULL;
1686 char *comment = NULL;
1687 char *pathname = NULL;
1688 int type;
1689 int snum;
1690 int ret;
1691 char *path;
1692 SEC_DESC *psd = NULL;
1693 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1694 bool is_disk_op;
1695 int max_connections = 0;
1696 TALLOC_CTX *ctx = p->mem_ctx;
1698 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1700 *r->out.parm_error = 0;
1702 get_current_user(&user,p);
1704 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1706 if (user.ut.uid != sec_initial_uid() && !is_disk_op )
1707 return WERR_ACCESS_DENIED;
1709 if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
1710 DEBUG(10,("_srvsvc_NetShareAdd: No add share command\n"));
1711 return WERR_ACCESS_DENIED;
1714 switch (r->in.level) {
1715 case 0:
1716 /* No path. Not enough info in a level 0 to do anything. */
1717 return WERR_ACCESS_DENIED;
1718 case 1:
1719 /* Not enough info in a level 1 to do anything. */
1720 return WERR_ACCESS_DENIED;
1721 case 2:
1722 share_name = talloc_strdup(ctx, r->in.info->info2->name);
1723 comment = talloc_strdup(ctx, r->in.info->info2->comment);
1724 pathname = talloc_strdup(ctx, r->in.info->info2->path);
1725 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
1726 0 : r->in.info->info2->max_users;
1727 type = r->in.info->info2->type;
1728 break;
1729 case 501:
1730 /* No path. Not enough info in a level 501 to do anything. */
1731 return WERR_ACCESS_DENIED;
1732 case 502:
1733 share_name = talloc_strdup(ctx, r->in.info->info502->name);
1734 comment = talloc_strdup(ctx, r->in.info->info502->comment);
1735 pathname = talloc_strdup(ctx, r->in.info->info502->path);
1736 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
1737 0 : r->in.info->info502->max_users;
1738 type = r->in.info->info502->type;
1739 psd = r->in.info->info502->sd_buf.sd;
1740 map_generic_share_sd_bits(psd);
1741 break;
1743 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
1745 case 1004:
1746 case 1005:
1747 case 1006:
1748 case 1007:
1749 return WERR_ACCESS_DENIED;
1750 case 1501:
1751 /* DFS only level. */
1752 return WERR_ACCESS_DENIED;
1753 default:
1754 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
1755 r->in.level));
1756 return WERR_UNKNOWN_LEVEL;
1759 /* check for invalid share names */
1761 if (!share_name || !validate_net_name(share_name,
1762 INVALID_SHARENAME_CHARS,
1763 strlen(share_name))) {
1764 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
1765 share_name ? share_name : ""));
1766 return WERR_INVALID_NAME;
1769 if (strequal(share_name,"IPC$") || strequal(share_name,"global")
1770 || (lp_enable_asu_support() &&
1771 strequal(share_name,"ADMIN$"))) {
1772 return WERR_ACCESS_DENIED;
1775 snum = find_service(share_name);
1777 /* Share already exists. */
1778 if (snum >= 0) {
1779 return WERR_ALREADY_EXISTS;
1782 /* We can only add disk shares. */
1783 if (type != STYPE_DISKTREE) {
1784 return WERR_ACCESS_DENIED;
1787 /* Check if the pathname is valid. */
1788 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
1789 return WERR_OBJECT_PATH_INVALID;
1792 /* Ensure share name, pathname and comment don't contain '"' characters. */
1793 string_replace(share_name, '"', ' ');
1794 string_replace(path, '"', ' ');
1795 if (comment) {
1796 string_replace(comment, '"', ' ');
1799 command = talloc_asprintf(ctx,
1800 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1801 lp_add_share_cmd(),
1802 get_dyn_CONFIGFILE(),
1803 share_name,
1804 path,
1805 comment ? comment : "",
1806 max_connections);
1807 if (!command) {
1808 return WERR_NOMEM;
1811 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
1813 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1815 if ( is_disk_op )
1816 become_root();
1818 /* FIXME: use libnetconf here - gd */
1820 if ( (ret = smbrun(command, NULL)) == 0 ) {
1821 /* Tell everyone we updated smb.conf. */
1822 message_send_all(smbd_messaging_context(),
1823 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1826 if ( is_disk_op )
1827 unbecome_root();
1829 /********* END SeDiskOperatorPrivilege BLOCK *********/
1831 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
1832 command, ret ));
1834 TALLOC_FREE(command);
1836 if ( ret != 0 )
1837 return WERR_ACCESS_DENIED;
1839 if (psd) {
1840 if (!set_share_security(share_name, psd)) {
1841 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
1842 share_name ));
1847 * We don't call reload_services() here, the message will
1848 * cause this to be done before the next packet is read
1849 * from the client. JRA.
1852 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1854 return WERR_OK;
1857 /*******************************************************************
1858 _srvsvc_NetShareDel
1859 Call "delete share command" with the share name as
1860 a parameter.
1861 ********************************************************************/
1863 WERROR _srvsvc_NetShareDel(pipes_struct *p,
1864 struct srvsvc_NetShareDel *r)
1866 struct current_user user;
1867 char *command = NULL;
1868 char *share_name = NULL;
1869 int ret;
1870 int snum;
1871 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1872 bool is_disk_op;
1873 struct share_params *params;
1874 TALLOC_CTX *ctx = p->mem_ctx;
1876 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
1878 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1879 if (!share_name) {
1880 return WERR_NET_NAME_NOT_FOUND;
1882 if ( strequal(share_name,"IPC$")
1883 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1884 || strequal(share_name,"global") )
1886 return WERR_ACCESS_DENIED;
1889 if (!(params = get_share_params(p->mem_ctx, share_name))) {
1890 return WERR_NO_SUCH_SHARE;
1893 snum = find_service(share_name);
1895 /* No change to printer shares. */
1896 if (lp_print_ok(snum))
1897 return WERR_ACCESS_DENIED;
1899 get_current_user(&user,p);
1901 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1903 if (user.ut.uid != sec_initial_uid() && !is_disk_op )
1904 return WERR_ACCESS_DENIED;
1906 if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
1907 DEBUG(10,("_srvsvc_NetShareDel: No delete share command\n"));
1908 return WERR_ACCESS_DENIED;
1911 command = talloc_asprintf(ctx,
1912 "%s \"%s\" \"%s\"",
1913 lp_delete_share_cmd(),
1914 get_dyn_CONFIGFILE(),
1915 lp_servicename(snum));
1916 if (!command) {
1917 return WERR_NOMEM;
1920 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
1922 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1924 if ( is_disk_op )
1925 become_root();
1927 if ( (ret = smbrun(command, NULL)) == 0 ) {
1928 /* Tell everyone we updated smb.conf. */
1929 message_send_all(smbd_messaging_context(),
1930 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1933 if ( is_disk_op )
1934 unbecome_root();
1936 /********* END SeDiskOperatorPrivilege BLOCK *********/
1938 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
1940 if ( ret != 0 )
1941 return WERR_ACCESS_DENIED;
1943 /* Delete the SD in the database. */
1944 delete_share_security(lp_servicename(params->service));
1946 lp_killservice(params->service);
1948 return WERR_OK;
1951 /*******************************************************************
1952 _srvsvc_NetShareDelSticky
1953 ********************************************************************/
1955 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p,
1956 struct srvsvc_NetShareDelSticky *r)
1958 struct srvsvc_NetShareDel q;
1960 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
1962 q.in.server_unc = r->in.server_unc;
1963 q.in.share_name = r->in.share_name;
1964 q.in.reserved = r->in.reserved;
1966 return _srvsvc_NetShareDel(p, &q);
1969 /*******************************************************************
1970 _srvsvc_NetRemoteTOD
1971 ********************************************************************/
1973 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p,
1974 struct srvsvc_NetRemoteTOD *r)
1976 struct srvsvc_NetRemoteTODInfo *tod;
1977 struct tm *t;
1978 time_t unixdate = time(NULL);
1980 /* We do this call first as if we do it *after* the gmtime call
1981 it overwrites the pointed-to values. JRA */
1983 uint32 zone = get_time_zone(unixdate)/60;
1985 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
1987 if ( !(tod = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
1988 return WERR_NOMEM;
1990 *r->out.info = tod;
1992 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
1994 t = gmtime(&unixdate);
1996 /* set up the */
1997 init_srvsvc_NetRemoteTODInfo(tod,
1998 unixdate,
2000 t->tm_hour,
2001 t->tm_min,
2002 t->tm_sec,
2004 zone,
2005 10000,
2006 t->tm_mday,
2007 t->tm_mon + 1,
2008 1900+t->tm_year,
2009 t->tm_wday);
2011 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2013 return WERR_OK;
2016 /***********************************************************************************
2017 _srvsvc_NetGetFileSecurity
2018 Win9x NT tools get security descriptor.
2019 ***********************************************************************************/
2021 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p,
2022 struct srvsvc_NetGetFileSecurity *r)
2024 SEC_DESC *psd = NULL;
2025 size_t sd_size;
2026 DATA_BLOB null_pw;
2027 char *filename_in = NULL;
2028 char *filename = NULL;
2029 char *qualname = NULL;
2030 SMB_STRUCT_STAT st;
2031 NTSTATUS nt_status;
2032 WERROR werr = WERR_ACCESS_DENIED;
2033 struct current_user user;
2034 connection_struct *conn = NULL;
2035 bool became_user = False;
2036 TALLOC_CTX *ctx = p->mem_ctx;
2037 struct sec_desc_buf *sd_buf = NULL;
2038 files_struct *fsp = NULL;
2040 ZERO_STRUCT(st);
2042 qualname = talloc_strdup(ctx, r->in.share);
2043 if (!qualname) {
2044 goto error_exit;
2047 /* Null password is ok - we are already an authenticated user... */
2048 null_pw = data_blob_null;
2050 get_current_user(&user, p);
2052 become_root();
2053 conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
2054 unbecome_root();
2056 if (conn == NULL) {
2057 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to connect to %s\n",
2058 qualname));
2059 werr = ntstatus_to_werror(nt_status);
2060 goto error_exit;
2063 if (!become_user(conn, conn->vuid)) {
2064 DEBUG(0,("_srvsvc_NetGetFileSecurity: Can't become connected user!\n"));
2065 goto error_exit;
2067 became_user = True;
2069 filename_in = talloc_strdup(ctx, r->in.file);
2070 if (!filename_in) {
2071 goto error_exit;
2074 nt_status = unix_convert(ctx, conn, filename_in, False, &filename, NULL, &st);
2075 if (!NT_STATUS_IS_OK(nt_status)) {
2076 DEBUG(3,("_srvsvc_NetGetFileSecurity: bad pathname %s\n",
2077 filename));
2078 goto error_exit;
2081 nt_status = check_name(conn, filename);
2082 if (!NT_STATUS_IS_OK(nt_status)) {
2083 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't access %s\n",
2084 filename));
2085 goto error_exit;
2088 if (!(S_ISDIR(st.st_mode))) {
2089 nt_status = open_file_ntcreate(conn, NULL, filename, &st,
2090 FILE_READ_ATTRIBUTES,
2091 FILE_SHARE_READ|FILE_SHARE_WRITE,
2092 FILE_OPEN,
2094 FILE_ATTRIBUTE_NORMAL,
2096 NULL, &fsp);
2098 } else {
2099 nt_status = open_directory(conn, NULL, filename, &st,
2100 FILE_READ_ATTRIBUTES,
2101 FILE_SHARE_READ|FILE_SHARE_WRITE,
2102 FILE_OPEN,
2104 FILE_ATTRIBUTE_DIRECTORY,
2105 NULL, &fsp);
2108 if (!NT_STATUS_IS_OK(nt_status)) {
2109 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2110 filename));
2111 werr = ntstatus_to_werror(nt_status);
2112 goto error_exit;
2115 nt_status = SMB_VFS_FGET_NT_ACL(fsp,
2116 (OWNER_SECURITY_INFORMATION
2117 |GROUP_SECURITY_INFORMATION
2118 |DACL_SECURITY_INFORMATION), &psd);
2120 if (!NT_STATUS_IS_OK(nt_status)) {
2121 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL for file %s\n",
2122 filename));
2123 werr = ntstatus_to_werror(nt_status);
2124 goto error_exit;
2127 sd_size = ndr_size_security_descriptor(psd, 0);
2129 sd_buf = TALLOC_ZERO_P(ctx, struct sec_desc_buf);
2130 if (!sd_buf) {
2131 werr = WERR_NOMEM;
2132 goto error_exit;
2135 sd_buf->sd_size = sd_size;
2136 sd_buf->sd = psd;
2138 *r->out.sd_buf = sd_buf;
2140 psd->dacl->revision = NT4_ACL_REVISION;
2142 close_file(fsp, NORMAL_CLOSE);
2144 unbecome_user();
2145 close_cnum(conn, user.vuid);
2146 return WERR_OK;
2148 error_exit:
2150 if(fsp) {
2151 close_file(fsp, NORMAL_CLOSE);
2154 if (became_user) {
2155 unbecome_user();
2158 if (conn) {
2159 close_cnum(conn, user.vuid);
2162 return werr;
2165 /***********************************************************************************
2166 _srvsvc_NetSetFileSecurity
2167 Win9x NT tools set security descriptor.
2168 ***********************************************************************************/
2170 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p,
2171 struct srvsvc_NetSetFileSecurity *r)
2173 char *filename_in = NULL;
2174 char *filename = NULL;
2175 char *qualname = NULL;
2176 DATA_BLOB null_pw;
2177 files_struct *fsp = NULL;
2178 SMB_STRUCT_STAT st;
2179 NTSTATUS nt_status;
2180 WERROR werr;
2181 struct current_user user;
2182 connection_struct *conn = NULL;
2183 bool became_user = False;
2184 TALLOC_CTX *ctx = p->mem_ctx;
2186 ZERO_STRUCT(st);
2188 werr = WERR_OK;
2190 qualname = talloc_strdup(ctx, r->in.share);
2191 if (!qualname) {
2192 werr = WERR_ACCESS_DENIED;
2193 goto error_exit;
2196 /* Null password is ok - we are already an authenticated user... */
2197 null_pw = data_blob_null;
2199 get_current_user(&user, p);
2201 become_root();
2202 conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
2203 unbecome_root();
2205 if (conn == NULL) {
2206 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to connect to %s\n", qualname));
2207 werr = ntstatus_to_werror(nt_status);
2208 goto error_exit;
2211 if (!become_user(conn, conn->vuid)) {
2212 DEBUG(0,("_srvsvc_NetSetFileSecurity: Can't become connected user!\n"));
2213 werr = WERR_ACCESS_DENIED;
2214 goto error_exit;
2216 became_user = True;
2218 filename_in = talloc_strdup(ctx, r->in.file);
2219 if (!filename_in) {
2220 werr = WERR_ACCESS_DENIED;
2221 goto error_exit;
2224 nt_status = unix_convert(ctx, conn, filename, False, &filename, NULL, &st);
2225 if (!NT_STATUS_IS_OK(nt_status)) {
2226 DEBUG(3,("_srvsvc_NetSetFileSecurity: bad pathname %s\n", filename));
2227 werr = WERR_ACCESS_DENIED;
2228 goto error_exit;
2231 nt_status = check_name(conn, filename);
2232 if (!NT_STATUS_IS_OK(nt_status)) {
2233 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't access %s\n", filename));
2234 werr = WERR_ACCESS_DENIED;
2235 goto error_exit;
2238 nt_status = open_file_ntcreate(conn, NULL, filename, &st,
2239 FILE_WRITE_ATTRIBUTES,
2240 FILE_SHARE_READ|FILE_SHARE_WRITE,
2241 FILE_OPEN,
2243 FILE_ATTRIBUTE_NORMAL,
2244 INTERNAL_OPEN_ONLY,
2245 NULL, &fsp);
2247 if ( !NT_STATUS_IS_OK(nt_status) ) {
2248 /* Perhaps it is a directory */
2249 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2250 nt_status = open_directory(conn, NULL, filename, &st,
2251 FILE_WRITE_ATTRIBUTES,
2252 FILE_SHARE_READ|FILE_SHARE_WRITE,
2253 FILE_OPEN,
2255 FILE_ATTRIBUTE_DIRECTORY,
2256 NULL, &fsp);
2258 if ( !NT_STATUS_IS_OK(nt_status) ) {
2259 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to open file %s\n", filename));
2260 werr = ntstatus_to_werror(nt_status);
2261 goto error_exit;
2265 nt_status = SMB_VFS_FSET_NT_ACL(fsp,
2266 r->in.securityinformation,
2267 r->in.sd_buf->sd);
2269 if (!NT_STATUS_IS_OK(nt_status) ) {
2270 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL on file %s\n", filename));
2271 werr = WERR_ACCESS_DENIED;
2272 goto error_exit;
2275 close_file(fsp, NORMAL_CLOSE);
2276 unbecome_user();
2277 close_cnum(conn, user.vuid);
2278 return werr;
2280 error_exit:
2282 if(fsp) {
2283 close_file(fsp, NORMAL_CLOSE);
2286 if (became_user) {
2287 unbecome_user();
2290 if (conn) {
2291 close_cnum(conn, user.vuid);
2294 return werr;
2297 /***********************************************************************************
2298 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2299 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2300 These disks would the disks listed by this function.
2301 Users could then create shares relative to these disks. Watch out for moving these disks around.
2302 "Nigel Williams" <nigel@veritas.com>.
2303 ***********************************************************************************/
2305 static const char *server_disks[] = {"C:"};
2307 static uint32 get_server_disk_count(void)
2309 return sizeof(server_disks)/sizeof(server_disks[0]);
2312 static uint32 init_server_disk_enum(uint32 *resume)
2314 uint32 server_disk_count = get_server_disk_count();
2316 /*resume can be an offset into the list for now*/
2318 if(*resume & 0x80000000)
2319 *resume = 0;
2321 if(*resume > server_disk_count)
2322 *resume = server_disk_count;
2324 return server_disk_count - *resume;
2327 static const char *next_server_disk_enum(uint32 *resume)
2329 const char *disk;
2331 if(init_server_disk_enum(resume) == 0)
2332 return NULL;
2334 disk = server_disks[*resume];
2336 (*resume)++;
2338 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2340 return disk;
2343 /********************************************************************
2344 _srvsvc_NetDiskEnum
2345 ********************************************************************/
2347 WERROR _srvsvc_NetDiskEnum(pipes_struct *p,
2348 struct srvsvc_NetDiskEnum *r)
2350 uint32 i;
2351 const char *disk_name;
2352 TALLOC_CTX *ctx = p->mem_ctx;
2353 WERROR werr;
2354 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2356 werr = WERR_OK;
2358 *r->out.totalentries = init_server_disk_enum(&resume);
2360 r->out.info->disks = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetDiskInfo0,
2361 MAX_SERVER_DISK_ENTRIES);
2362 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2364 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2366 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2368 r->out.info->count++;
2370 /*copy disk name into a unicode string*/
2372 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2373 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2376 /* add a terminating null string. Is this there if there is more data to come? */
2378 r->out.info->count++;
2380 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2381 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2383 if (r->out.resume_handle) {
2384 *r->out.resume_handle = resume;
2387 return werr;
2390 /********************************************************************
2391 _srvsvc_NetNameValidate
2392 ********************************************************************/
2394 WERROR _srvsvc_NetNameValidate(pipes_struct *p,
2395 struct srvsvc_NetNameValidate *r)
2397 switch (r->in.name_type) {
2398 case 0x9:
2399 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2400 strlen_m(r->in.name)))
2402 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2403 r->in.name));
2404 return WERR_INVALID_NAME;
2406 break;
2408 default:
2409 return WERR_UNKNOWN_LEVEL;
2412 return WERR_OK;
2415 /********************************************************************
2416 ********************************************************************/
2418 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2420 return WERR_ACCESS_DENIED;
2424 /********************************************************************
2425 ********************************************************************/
2427 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2429 p->rng_fault_state = True;
2430 return WERR_NOT_SUPPORTED;
2433 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2435 p->rng_fault_state = True;
2436 return WERR_NOT_SUPPORTED;
2439 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2441 p->rng_fault_state = True;
2442 return WERR_NOT_SUPPORTED;
2445 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2447 p->rng_fault_state = True;
2448 return WERR_NOT_SUPPORTED;
2451 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2453 p->rng_fault_state = True;
2454 return WERR_NOT_SUPPORTED;
2457 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2459 p->rng_fault_state = True;
2460 return WERR_NOT_SUPPORTED;
2463 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2465 p->rng_fault_state = True;
2466 return WERR_NOT_SUPPORTED;
2469 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2471 p->rng_fault_state = True;
2472 return WERR_NOT_SUPPORTED;
2475 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2477 p->rng_fault_state = True;
2478 return WERR_NOT_SUPPORTED;
2481 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2483 p->rng_fault_state = True;
2484 return WERR_NOT_SUPPORTED;
2487 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2489 p->rng_fault_state = True;
2490 return WERR_NOT_SUPPORTED;
2493 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2495 p->rng_fault_state = True;
2496 return WERR_NOT_SUPPORTED;
2499 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2501 p->rng_fault_state = True;
2502 return WERR_NOT_SUPPORTED;
2505 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2507 p->rng_fault_state = True;
2508 return WERR_NOT_SUPPORTED;
2511 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2513 p->rng_fault_state = True;
2514 return WERR_NOT_SUPPORTED;
2517 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2519 p->rng_fault_state = True;
2520 return WERR_NOT_SUPPORTED;
2523 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2525 p->rng_fault_state = True;
2526 return WERR_NOT_SUPPORTED;
2529 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2531 p->rng_fault_state = True;
2532 return WERR_NOT_SUPPORTED;
2535 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2537 p->rng_fault_state = True;
2538 return WERR_NOT_SUPPORTED;
2541 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2543 p->rng_fault_state = True;
2544 return WERR_NOT_SUPPORTED;
2547 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2549 p->rng_fault_state = True;
2550 return WERR_NOT_SUPPORTED;
2553 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2555 p->rng_fault_state = True;
2556 return WERR_NOT_SUPPORTED;
2559 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2561 p->rng_fault_state = True;
2562 return WERR_NOT_SUPPORTED;
2565 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2567 p->rng_fault_state = True;
2568 return WERR_NOT_SUPPORTED;
2571 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2573 p->rng_fault_state = True;
2574 return WERR_NOT_SUPPORTED;
2577 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2579 p->rng_fault_state = True;
2580 return WERR_NOT_SUPPORTED;
2583 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2585 p->rng_fault_state = True;
2586 return WERR_NOT_SUPPORTED;
2589 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
2591 p->rng_fault_state = True;
2592 return WERR_NOT_SUPPORTED;
2595 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2597 p->rng_fault_state = True;
2598 return WERR_NOT_SUPPORTED;
2601 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2603 p->rng_fault_state = True;
2604 return WERR_NOT_SUPPORTED;
2607 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2609 p->rng_fault_state = True;
2610 return WERR_NOT_SUPPORTED;
2613 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2615 p->rng_fault_state = True;
2616 return WERR_NOT_SUPPORTED;
2619 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2621 p->rng_fault_state = True;
2622 return WERR_NOT_SUPPORTED;
2625 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2627 p->rng_fault_state = True;
2628 return WERR_NOT_SUPPORTED;
2631 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2633 p->rng_fault_state = True;
2634 return WERR_NOT_SUPPORTED;