Fix bug 6097
[Samba.git] / source / rpc_server / srv_srvsvc_nt.c
blobc22363e6a16323189a537864755e619ebae2048b
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997,
5 * Copyright (C) Jeremy Allison 2001.
6 * Copyright (C) Nigel Williams 2001.
7 * Copyright (C) Gerald (Jerry) Carter 2006.
8 * Copyright (C) Guenther Deschner 2008.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
24 /* This is the implementation of the srvsvc pipe. */
26 #include "includes.h"
28 extern const struct generic_mapping file_generic_mapping;
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
33 #define MAX_SERVER_DISK_ENTRIES 15
35 /* Use for enumerating connections, pipes, & files */
37 struct file_enum_count {
38 TALLOC_CTX *ctx;
39 const char *username;
40 struct srvsvc_NetFileCtr3 *ctr3;
43 struct sess_file_count {
44 struct server_id pid;
45 uid_t uid;
46 int count;
49 /****************************************************************************
50 Count the entries belonging to a service in the connection db.
51 ****************************************************************************/
53 static int pipe_enum_fn( struct db_record *rec, void *p)
55 struct pipe_open_rec prec;
56 struct file_enum_count *fenum = (struct file_enum_count *)p;
57 struct srvsvc_NetFileInfo3 *f;
58 int i = fenum->ctr3->count;
59 char *fullpath = NULL;
60 const char *username;
62 if (rec->value.dsize != sizeof(struct pipe_open_rec))
63 return 0;
65 memcpy(&prec, rec->value.dptr, sizeof(struct pipe_open_rec));
67 if ( !process_exists(prec.pid) ) {
68 return 0;
71 username = uidtoname(prec.uid);
73 if ((fenum->username != NULL)
74 && !strequal(username, fenum->username)) {
75 return 0;
78 fullpath = talloc_asprintf(fenum->ctx, "\\PIPE\\%s", prec.name );
79 if (!fullpath) {
80 return 1;
83 f = TALLOC_REALLOC_ARRAY(fenum->ctx, fenum->ctr3->array,
84 struct srvsvc_NetFileInfo3, i+1);
85 if ( !f ) {
86 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
87 return 1;
89 fenum->ctr3->array = f;
91 init_srvsvc_NetFileInfo3(&fenum->ctr3->array[i],
92 (((uint32_t)(procid_to_pid(&prec.pid))<<16) | prec.pnum),
93 (FILE_READ_DATA|FILE_WRITE_DATA),
95 fullpath,
96 username);
98 fenum->ctr3->count++;
100 return 0;
103 /*******************************************************************
104 ********************************************************************/
106 static WERROR net_enum_pipes(TALLOC_CTX *ctx,
107 const char *username,
108 struct srvsvc_NetFileCtr3 **ctr3,
109 uint32_t resume )
111 struct file_enum_count fenum;
113 fenum.ctx = ctx;
114 fenum.username = username;
115 fenum.ctr3 = *ctr3;
117 if (connections_traverse(pipe_enum_fn, &fenum) == -1) {
118 DEBUG(0,("net_enum_pipes: traverse of connections.tdb "
119 "failed\n"));
120 return WERR_NOMEM;
123 *ctr3 = fenum.ctr3;
125 return WERR_OK;
128 /*******************************************************************
129 ********************************************************************/
131 static void enum_file_fn( const struct share_mode_entry *e,
132 const char *sharepath, const char *fname,
133 void *private_data )
135 struct file_enum_count *fenum =
136 (struct file_enum_count *)private_data;
138 struct srvsvc_NetFileInfo3 *f;
139 int i = fenum->ctr3->count;
140 files_struct fsp;
141 struct byte_range_lock *brl;
142 int num_locks = 0;
143 char *fullpath = NULL;
144 uint32 permissions;
145 const char *username;
147 /* If the pid was not found delete the entry from connections.tdb */
149 if ( !process_exists(e->pid) ) {
150 return;
153 username = uidtoname(e->uid);
155 if ((fenum->username != NULL)
156 && !strequal(username, fenum->username)) {
157 return;
160 f = TALLOC_REALLOC_ARRAY(fenum->ctx, fenum->ctr3->array,
161 struct srvsvc_NetFileInfo3, i+1);
162 if ( !f ) {
163 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
164 return;
166 fenum->ctr3->array = f;
168 /* need to count the number of locks on a file */
170 ZERO_STRUCT( fsp );
171 fsp.file_id = e->id;
173 if ( (brl = brl_get_locks(talloc_tos(), &fsp)) != NULL ) {
174 num_locks = brl->num_locks;
175 TALLOC_FREE(brl);
178 if ( strcmp( fname, "." ) == 0 ) {
179 fullpath = talloc_asprintf(fenum->ctx, "C:%s", sharepath );
180 } else {
181 fullpath = talloc_asprintf(fenum->ctx, "C:%s/%s",
182 sharepath, fname );
184 if (!fullpath) {
185 return;
187 string_replace( fullpath, '/', '\\' );
189 /* mask out create (what ever that is) */
190 permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
192 /* now fill in the srvsvc_NetFileInfo3 struct */
193 init_srvsvc_NetFileInfo3(&fenum->ctr3->array[i],
194 (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id),
195 permissions,
196 num_locks,
197 fullpath,
198 username);
199 fenum->ctr3->count++;
202 /*******************************************************************
203 ********************************************************************/
205 static WERROR net_enum_files(TALLOC_CTX *ctx,
206 const char *username,
207 struct srvsvc_NetFileCtr3 **ctr3,
208 uint32_t resume)
210 struct file_enum_count f_enum_cnt;
212 f_enum_cnt.ctx = ctx;
213 f_enum_cnt.username = username;
214 f_enum_cnt.ctr3 = *ctr3;
216 share_mode_forall( enum_file_fn, (void *)&f_enum_cnt );
218 *ctr3 = f_enum_cnt.ctr3;
220 return WERR_OK;
223 /*******************************************************************
224 Utility function to get the 'type' of a share from an snum.
225 ********************************************************************/
226 static uint32 get_share_type(int snum)
228 /* work out the share type */
229 uint32 type = STYPE_DISKTREE;
231 if (lp_print_ok(snum))
232 type = STYPE_PRINTQ;
233 if (strequal(lp_fstype(snum), "IPC"))
234 type = STYPE_IPC;
235 if (lp_administrative_share(snum))
236 type |= STYPE_HIDDEN;
238 return type;
241 /*******************************************************************
242 Fill in a share info level 0 structure.
243 ********************************************************************/
245 static void init_srv_share_info_0(pipes_struct *p, struct srvsvc_NetShareInfo0 *r, int snum)
247 const char *net_name = lp_servicename(snum);
249 init_srvsvc_NetShareInfo0(r, net_name);
252 /*******************************************************************
253 Fill in a share info level 1 structure.
254 ********************************************************************/
256 static void init_srv_share_info_1(pipes_struct *p, struct srvsvc_NetShareInfo1 *r, int snum)
258 char *net_name = lp_servicename(snum);
259 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
261 if (remark) {
262 remark = standard_sub_conn(p->mem_ctx,
263 p->conn,
264 remark);
267 init_srvsvc_NetShareInfo1(r, net_name,
268 get_share_type(snum),
269 remark ? remark : "");
272 /*******************************************************************
273 Fill in a share info level 2 structure.
274 ********************************************************************/
276 static void init_srv_share_info_2(pipes_struct *p, struct srvsvc_NetShareInfo2 *r, int snum)
278 char *remark = NULL;
279 char *path = NULL;
280 int max_connections = lp_max_connections(snum);
281 uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
282 int count = 0;
283 char *net_name = lp_servicename(snum);
285 remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
286 if (remark) {
287 remark = standard_sub_conn(p->mem_ctx,
288 p->conn,
289 remark);
291 path = talloc_asprintf(p->mem_ctx,
292 "C:%s", lp_pathname(snum));
294 if (path) {
296 * Change / to \\ so that win2k will see it as a valid path.
297 * This was added to enable use of browsing in win2k add
298 * share dialog.
301 string_replace(path, '/', '\\');
304 count = count_current_connections(net_name, false);
306 init_srvsvc_NetShareInfo2(r, net_name,
307 get_share_type(snum),
308 remark ? remark : "",
310 max_uses,
311 count,
312 path ? path : "",
313 "");
316 /*******************************************************************
317 Map any generic bits to file specific bits.
318 ********************************************************************/
320 static void map_generic_share_sd_bits(SEC_DESC *psd)
322 int i;
323 SEC_ACL *ps_dacl = NULL;
325 if (!psd)
326 return;
328 ps_dacl = psd->dacl;
329 if (!ps_dacl)
330 return;
332 for (i = 0; i < ps_dacl->num_aces; i++) {
333 SEC_ACE *psa = &ps_dacl->aces[i];
334 uint32 orig_mask = psa->access_mask;
336 se_map_generic(&psa->access_mask, &file_generic_mapping);
337 psa->access_mask |= orig_mask;
341 /*******************************************************************
342 Fill in a share info level 501 structure.
343 ********************************************************************/
345 static void init_srv_share_info_501(pipes_struct *p, struct srvsvc_NetShareInfo501 *r, int snum)
347 const char *net_name = lp_servicename(snum);
348 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
350 if (remark) {
351 remark = standard_sub_conn(p->mem_ctx, p->conn, remark);
354 init_srvsvc_NetShareInfo501(r, net_name,
355 get_share_type(snum),
356 remark ? remark : "",
357 (lp_csc_policy(snum) << 4));
360 /*******************************************************************
361 Fill in a share info level 502 structure.
362 ********************************************************************/
364 static void init_srv_share_info_502(pipes_struct *p, struct srvsvc_NetShareInfo502 *r, int snum)
366 const char *net_name = lp_servicename(snum);
367 char *path = NULL;
368 SEC_DESC *sd = NULL;
369 struct sec_desc_buf *sd_buf = NULL;
370 size_t sd_size = 0;
371 TALLOC_CTX *ctx = p->mem_ctx;
372 char *remark = talloc_strdup(ctx, lp_comment(snum));;
374 if (remark) {
375 remark = standard_sub_conn(ctx, p->conn, remark);
377 path = talloc_asprintf(ctx, "C:%s", lp_pathname(snum));
378 if (path) {
380 * Change / to \\ so that win2k will see it as a valid path. This was added to
381 * enable use of browsing in win2k add share dialog.
383 string_replace(path, '/', '\\');
386 sd = get_share_security(ctx, lp_servicename(snum), &sd_size);
388 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
390 init_srvsvc_NetShareInfo502(r, net_name,
391 get_share_type(snum),
392 remark ? remark : "",
394 (uint32_t)-1,
396 path ? path : "",
398 sd_buf);
401 /***************************************************************************
402 Fill in a share info level 1004 structure.
403 ***************************************************************************/
405 static void init_srv_share_info_1004(pipes_struct *p, struct srvsvc_NetShareInfo1004 *r, int snum)
407 char *remark = talloc_strdup(p->mem_ctx, lp_comment(snum));
409 if (remark) {
410 remark = standard_sub_conn(p->mem_ctx, p->conn, remark);
413 init_srvsvc_NetShareInfo1004(r, remark ? remark : "");
416 /***************************************************************************
417 Fill in a share info level 1005 structure.
418 ***************************************************************************/
420 static void init_srv_share_info_1005(pipes_struct *p, struct srvsvc_NetShareInfo1005 *r, int snum)
422 uint32_t dfs_flags = 0;
424 if (lp_host_msdfs() && lp_msdfs_root(snum)) {
425 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
428 dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
430 init_srvsvc_NetShareInfo1005(r, dfs_flags);
433 /***************************************************************************
434 Fill in a share info level 1006 structure.
435 ***************************************************************************/
437 static void init_srv_share_info_1006(pipes_struct *p, struct srvsvc_NetShareInfo1006 *r, int snum)
439 init_srvsvc_NetShareInfo1006(r, (uint32_t)-1);
442 /***************************************************************************
443 Fill in a share info level 1007 structure.
444 ***************************************************************************/
446 static void init_srv_share_info_1007(pipes_struct *p, struct srvsvc_NetShareInfo1007 *r, int snum)
448 uint32 flags = 0;
450 init_srvsvc_NetShareInfo1007(r, flags, "");
453 /*******************************************************************
454 Fill in a share info level 1501 structure.
455 ********************************************************************/
457 static void init_srv_share_info_1501(pipes_struct *p, struct sec_desc_buf *r, int snum)
459 SEC_DESC *sd;
460 size_t sd_size;
461 TALLOC_CTX *ctx = p->mem_ctx;
463 sd = get_share_security(ctx, lp_servicename(snum), &sd_size);
465 r = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
468 /*******************************************************************
469 True if it ends in '$'.
470 ********************************************************************/
472 static bool is_hidden_share(int snum)
474 const char *net_name = lp_servicename(snum);
476 return (net_name[strlen(net_name) - 1] == '$') ? True : False;
479 /*******************************************************************
480 Fill in a share info structure.
481 ********************************************************************/
483 static WERROR init_srv_share_info_ctr(pipes_struct *p,
484 struct srvsvc_NetShareInfoCtr *info_ctr,
485 uint32_t *resume_handle_p,
486 uint32_t *total_entries,
487 bool all_shares)
489 int num_entries = 0;
490 int alloc_entries = 0;
491 int num_services = 0;
492 int snum;
493 TALLOC_CTX *ctx = p->mem_ctx;
494 int i = 0;
495 int valid_share_count = 0;
496 union srvsvc_NetShareCtr ctr;
497 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
499 DEBUG(5,("init_srv_share_info_ctr\n"));
501 /* Ensure all the usershares are loaded. */
502 become_root();
503 load_usershare_shares();
504 load_registry_shares();
505 num_services = lp_numservices();
506 unbecome_root();
508 /* Count the number of entries. */
509 for (snum = 0; snum < num_services; snum++) {
510 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
511 DEBUG(10, ("counting service %s\n", lp_servicename(snum)));
512 num_entries++;
513 } else {
514 DEBUG(10, ("NOT counting service %s\n", lp_servicename(snum)));
518 if (!num_entries || (resume_handle >= num_entries)) {
519 return WERR_OK;
522 /* Calculate alloc entries. */
523 alloc_entries = num_entries - resume_handle;
524 switch (info_ctr->level) {
525 case 0:
526 ctr.ctr0 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr0);
527 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
529 ctr.ctr0->count = alloc_entries;
530 ctr.ctr0->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
531 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
533 for (snum = 0; snum < num_services; snum++) {
534 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
535 (resume_handle <= (i + valid_share_count++)) ) {
536 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
540 break;
542 case 1:
543 ctr.ctr1 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1);
544 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
546 ctr.ctr1->count = alloc_entries;
547 ctr.ctr1->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
548 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
550 for (snum = 0; snum < num_services; snum++) {
551 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
552 (resume_handle <= (i + valid_share_count++)) ) {
553 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
557 break;
559 case 2:
560 ctr.ctr2 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr2);
561 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
563 ctr.ctr2->count = alloc_entries;
564 ctr.ctr2->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
565 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
567 for (snum = 0; snum < num_services; snum++) {
568 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
569 (resume_handle <= (i + valid_share_count++)) ) {
570 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
574 break;
576 case 501:
577 ctr.ctr501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr501);
578 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
580 ctr.ctr501->count = alloc_entries;
581 ctr.ctr501->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
582 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
584 for (snum = 0; snum < num_services; snum++) {
585 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
586 (resume_handle <= (i + valid_share_count++)) ) {
587 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
591 break;
593 case 502:
594 ctr.ctr502 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr502);
595 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
597 ctr.ctr502->count = alloc_entries;
598 ctr.ctr502->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
599 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
601 for (snum = 0; snum < num_services; snum++) {
602 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
603 (resume_handle <= (i + valid_share_count++)) ) {
604 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
608 break;
610 case 1004:
611 ctr.ctr1004 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1004);
612 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
614 ctr.ctr1004->count = alloc_entries;
615 ctr.ctr1004->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
616 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
618 for (snum = 0; snum < num_services; snum++) {
619 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
620 (resume_handle <= (i + valid_share_count++)) ) {
621 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
625 break;
627 case 1005:
628 ctr.ctr1005 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1005);
629 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
631 ctr.ctr1005->count = alloc_entries;
632 ctr.ctr1005->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
633 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
635 for (snum = 0; snum < num_services; snum++) {
636 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
637 (resume_handle <= (i + valid_share_count++)) ) {
638 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
642 break;
644 case 1006:
645 ctr.ctr1006 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1006);
646 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
648 ctr.ctr1006->count = alloc_entries;
649 ctr.ctr1006->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
650 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
652 for (snum = 0; snum < num_services; snum++) {
653 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
654 (resume_handle <= (i + valid_share_count++)) ) {
655 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
659 break;
661 case 1007:
662 ctr.ctr1007 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1007);
663 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
665 ctr.ctr1007->count = alloc_entries;
666 ctr.ctr1007->array = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
667 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
669 for (snum = 0; snum < num_services; snum++) {
670 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
671 (resume_handle <= (i + valid_share_count++)) ) {
672 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
676 break;
678 case 1501:
679 ctr.ctr1501 = TALLOC_ZERO_P(ctx, struct srvsvc_NetShareCtr1501);
680 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
682 ctr.ctr1501->count = alloc_entries;
683 ctr.ctr1501->array = TALLOC_ZERO_ARRAY(ctx, struct sec_desc_buf, alloc_entries);
684 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
686 for (snum = 0; snum < num_services; snum++) {
687 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
688 (resume_handle <= (i + valid_share_count++)) ) {
689 init_srv_share_info_1501(p, &ctr.ctr1501->array[i++], snum);
693 break;
695 default:
696 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
697 info_ctr->level));
698 return WERR_UNKNOWN_LEVEL;
701 *total_entries = alloc_entries;
702 if (resume_handle_p) {
703 if (all_shares) {
704 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
705 } else {
706 *resume_handle_p = num_entries;
710 info_ctr->ctr = ctr;
712 return WERR_OK;
715 /*******************************************************************
716 fill in a sess info level 0 structure.
717 ********************************************************************/
719 static WERROR init_srv_sess_info_0(pipes_struct *p,
720 struct srvsvc_NetSessCtr0 *ctr0,
721 uint32_t *resume_handle_p,
722 uint32_t *total_entries)
724 struct sessionid *session_list;
725 uint32_t num_entries = 0;
726 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
727 *total_entries = list_sessions(p->mem_ctx, &session_list);
729 DEBUG(5,("init_srv_sess_info_0\n"));
731 if (ctr0 == NULL) {
732 if (resume_handle_p) {
733 *resume_handle_p = 0;
735 return WERR_OK;
738 for (; resume_handle < *total_entries; resume_handle++) {
740 ctr0->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
741 ctr0->array,
742 struct srvsvc_NetSessInfo0,
743 num_entries+1);
744 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
746 init_srvsvc_NetSessInfo0(&ctr0->array[num_entries],
747 session_list[resume_handle].remote_machine);
748 num_entries++;
751 ctr0->count = num_entries;
753 if (resume_handle_p) {
754 if (*resume_handle_p >= *total_entries) {
755 *resume_handle_p = 0;
756 } else {
757 *resume_handle_p = resume_handle;
761 return WERR_OK;
764 /*******************************************************************
765 ********************************************************************/
767 static void sess_file_fn( const struct share_mode_entry *e,
768 const char *sharepath, const char *fname,
769 void *data )
771 struct sess_file_count *sess = (struct sess_file_count *)data;
773 if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
774 sess->count++;
777 return;
780 /*******************************************************************
781 ********************************************************************/
783 static int net_count_files( uid_t uid, struct server_id pid )
785 struct sess_file_count s_file_cnt;
787 s_file_cnt.count = 0;
788 s_file_cnt.uid = uid;
789 s_file_cnt.pid = pid;
791 share_mode_forall( sess_file_fn, &s_file_cnt );
793 return s_file_cnt.count;
796 /*******************************************************************
797 fill in a sess info level 1 structure.
798 ********************************************************************/
800 static WERROR init_srv_sess_info_1(pipes_struct *p,
801 struct srvsvc_NetSessCtr1 *ctr1,
802 uint32_t *resume_handle_p,
803 uint32_t *total_entries)
805 struct sessionid *session_list;
806 uint32_t num_entries = 0;
807 time_t now = time(NULL);
808 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
810 ZERO_STRUCTP(ctr1);
812 if (ctr1 == NULL) {
813 if (resume_handle_p) {
814 *resume_handle_p = 0;
816 return WERR_OK;
819 *total_entries = list_sessions(p->mem_ctx, &session_list);
821 for (; resume_handle < *total_entries; resume_handle++) {
822 uint32 num_files;
823 uint32 connect_time;
824 struct passwd *pw = sys_getpwnam(session_list[resume_handle].username);
825 bool guest;
827 if ( !pw ) {
828 DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
829 session_list[resume_handle].username));
830 continue;
833 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
834 num_files = net_count_files(pw->pw_uid, session_list[resume_handle].pid);
835 guest = strequal( session_list[resume_handle].username, lp_guestaccount() );
837 ctr1->array = TALLOC_REALLOC_ARRAY(p->mem_ctx,
838 ctr1->array,
839 struct srvsvc_NetSessInfo1,
840 num_entries+1);
841 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
843 init_srvsvc_NetSessInfo1(&ctr1->array[num_entries],
844 session_list[resume_handle].remote_machine,
845 session_list[resume_handle].username,
846 num_files,
847 connect_time,
849 guest);
850 num_entries++;
853 ctr1->count = num_entries;
855 if (resume_handle_p) {
856 if (*resume_handle_p >= *total_entries) {
857 *resume_handle_p = 0;
858 } else {
859 *resume_handle_p = resume_handle;
863 return WERR_OK;
866 /*******************************************************************
867 fill in a conn info level 0 structure.
868 ********************************************************************/
870 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
871 uint32_t *resume_handle_p,
872 uint32_t *total_entries)
874 uint32_t num_entries = 0;
875 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
877 DEBUG(5,("init_srv_conn_info_0\n"));
879 if (ctr0 == NULL) {
880 if (resume_handle_p) {
881 *resume_handle_p = 0;
883 return WERR_OK;
886 *total_entries = 1;
888 ZERO_STRUCTP(ctr0);
890 for (; resume_handle < *total_entries; resume_handle++) {
892 ctr0->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
893 ctr0->array,
894 struct srvsvc_NetConnInfo0,
895 num_entries+1);
896 if (!ctr0->array) {
897 return WERR_NOMEM;
900 init_srvsvc_NetConnInfo0(&ctr0->array[num_entries],
901 (*total_entries));
903 /* move on to creating next connection */
904 num_entries++;
907 ctr0->count = num_entries;
908 *total_entries = num_entries;
910 if (resume_handle_p) {
911 if (*resume_handle_p >= *total_entries) {
912 *resume_handle_p = 0;
913 } else {
914 *resume_handle_p = resume_handle;
918 return WERR_OK;
921 /*******************************************************************
922 fill in a conn info level 1 structure.
923 ********************************************************************/
925 static WERROR init_srv_conn_info_1(struct srvsvc_NetConnCtr1 *ctr1,
926 uint32_t *resume_handle_p,
927 uint32_t *total_entries)
929 uint32_t num_entries = 0;
930 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
932 DEBUG(5,("init_srv_conn_info_1\n"));
934 if (ctr1 == NULL) {
935 if (resume_handle_p) {
936 *resume_handle_p = 0;
938 return WERR_OK;
941 *total_entries = 1;
943 ZERO_STRUCTP(ctr1);
945 for (; resume_handle < *total_entries; resume_handle++) {
947 ctr1->array = TALLOC_REALLOC_ARRAY(talloc_tos(),
948 ctr1->array,
949 struct srvsvc_NetConnInfo1,
950 num_entries+1);
951 if (!ctr1->array) {
952 return WERR_NOMEM;
955 init_srvsvc_NetConnInfo1(&ctr1->array[num_entries],
956 (*total_entries),
957 0x3,
961 "dummy_user",
962 "IPC$");
964 /* move on to creating next connection */
965 num_entries++;
968 ctr1->count = num_entries;
969 *total_entries = num_entries;
971 if (resume_handle_p) {
972 if (*resume_handle_p >= *total_entries) {
973 *resume_handle_p = 0;
974 } else {
975 *resume_handle_p = resume_handle;
979 return WERR_OK;
982 /*******************************************************************
983 _srvsvc_NetFileEnum
984 *******************************************************************/
986 WERROR _srvsvc_NetFileEnum(pipes_struct *p,
987 struct srvsvc_NetFileEnum *r)
989 TALLOC_CTX *ctx = NULL;
990 struct srvsvc_NetFileCtr3 *ctr3;
991 uint32_t resume_hnd = 0;
992 WERROR werr;
994 switch (r->in.info_ctr->level) {
995 case 3:
996 break;
997 default:
998 return WERR_UNKNOWN_LEVEL;
1001 ctx = talloc_tos();
1002 ctr3 = r->in.info_ctr->ctr.ctr3;
1003 if (!ctr3) {
1004 werr = WERR_INVALID_PARAM;
1005 goto done;
1008 /* TODO -- Windows enumerates
1009 (b) active pipes
1010 (c) open directories and files */
1012 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1013 if (!W_ERROR_IS_OK(werr)) {
1014 goto done;
1017 werr = net_enum_pipes(ctx, r->in.user, &ctr3, resume_hnd);
1018 if (!W_ERROR_IS_OK(werr)) {
1019 goto done;
1022 *r->out.totalentries = ctr3->count;
1023 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1024 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1026 werr = WERR_OK;
1028 done:
1029 return werr;
1032 /*******************************************************************
1033 _srvsvc_NetSrvGetInfo
1034 ********************************************************************/
1036 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p,
1037 struct srvsvc_NetSrvGetInfo *r)
1039 WERROR status = WERR_OK;
1041 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1043 if (!pipe_access_check(p)) {
1044 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1045 return WERR_ACCESS_DENIED;
1048 switch (r->in.level) {
1050 /* Technically level 102 should only be available to
1051 Administrators but there isn't anything super-secret
1052 here, as most of it is made up. */
1054 case 102: {
1055 struct srvsvc_NetSrvInfo102 *info102;
1057 info102 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1058 if (!info102) {
1059 return WERR_NOMEM;
1062 init_srvsvc_NetSrvInfo102(info102,
1063 PLATFORM_ID_NT,
1064 global_myname(),
1065 lp_major_announce_version(),
1066 lp_minor_announce_version(),
1067 lp_default_server_announce(),
1068 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
1069 0xffffffff, /* users */
1070 0xf, /* disc */
1071 0, /* hidden */
1072 240, /* announce */
1073 3000, /* announce delta */
1074 100000, /* licenses */
1075 "c:\\"); /* user path */
1076 r->out.info->info102 = info102;
1077 break;
1079 case 101: {
1080 struct srvsvc_NetSrvInfo101 *info101;
1082 info101 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1083 if (!info101) {
1084 return WERR_NOMEM;
1087 init_srvsvc_NetSrvInfo101(info101,
1088 PLATFORM_ID_NT,
1089 global_myname(),
1090 lp_major_announce_version(),
1091 lp_minor_announce_version(),
1092 lp_default_server_announce(),
1093 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1094 r->out.info->info101 = info101;
1095 break;
1097 case 100: {
1098 struct srvsvc_NetSrvInfo100 *info100;
1100 info100 = TALLOC_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1101 if (!info100) {
1102 return WERR_NOMEM;
1105 init_srvsvc_NetSrvInfo100(info100,
1106 PLATFORM_ID_NT,
1107 global_myname());
1108 r->out.info->info100 = info100;
1110 break;
1112 default:
1113 status = WERR_UNKNOWN_LEVEL;
1114 break;
1117 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1119 return status;
1122 /*******************************************************************
1123 _srvsvc_NetSrvSetInfo
1124 ********************************************************************/
1126 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p,
1127 struct srvsvc_NetSrvSetInfo *r)
1129 WERROR status = WERR_OK;
1131 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1133 /* Set up the net server set info structure. */
1135 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1137 return status;
1140 /*******************************************************************
1141 _srvsvc_NetConnEnum
1142 ********************************************************************/
1144 WERROR _srvsvc_NetConnEnum(pipes_struct *p,
1145 struct srvsvc_NetConnEnum *r)
1147 WERROR werr;
1149 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1151 switch (r->in.info_ctr->level) {
1152 case 0:
1153 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1154 r->in.resume_handle,
1155 r->out.totalentries);
1156 break;
1157 case 1:
1158 werr = init_srv_conn_info_1(r->in.info_ctr->ctr.ctr1,
1159 r->in.resume_handle,
1160 r->out.totalentries);
1161 break;
1162 default:
1163 return WERR_UNKNOWN_LEVEL;
1166 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1168 return werr;
1171 /*******************************************************************
1172 _srvsvc_NetSessEnum
1173 ********************************************************************/
1175 WERROR _srvsvc_NetSessEnum(pipes_struct *p,
1176 struct srvsvc_NetSessEnum *r)
1178 WERROR werr;
1180 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1182 switch (r->in.info_ctr->level) {
1183 case 0:
1184 werr = init_srv_sess_info_0(p,
1185 r->in.info_ctr->ctr.ctr0,
1186 r->in.resume_handle,
1187 r->out.totalentries);
1188 break;
1189 case 1:
1190 werr = init_srv_sess_info_1(p,
1191 r->in.info_ctr->ctr.ctr1,
1192 r->in.resume_handle,
1193 r->out.totalentries);
1194 break;
1195 default:
1196 return WERR_UNKNOWN_LEVEL;
1199 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1201 return werr;
1204 /*******************************************************************
1205 _srvsvc_NetSessDel
1206 ********************************************************************/
1208 WERROR _srvsvc_NetSessDel(pipes_struct *p,
1209 struct srvsvc_NetSessDel *r)
1211 struct sessionid *session_list;
1212 struct current_user user;
1213 int num_sessions, snum;
1214 const char *username;
1215 const char *machine;
1216 bool not_root = False;
1217 WERROR werr;
1219 username = r->in.user;
1220 machine = r->in.client;
1222 /* strip leading backslashes if any */
1223 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1224 machine += 2;
1227 num_sessions = list_sessions(p->mem_ctx, &session_list);
1229 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1231 werr = WERR_ACCESS_DENIED;
1233 get_current_user(&user, p);
1235 /* fail out now if you are not root or not a domain admin */
1237 if ((user.ut.uid != sec_initial_uid()) &&
1238 ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
1240 goto done;
1243 for (snum = 0; snum < num_sessions; snum++) {
1245 if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
1246 strequal(session_list[snum].remote_machine, machine)) {
1248 NTSTATUS ntstat;
1250 if (user.ut.uid != sec_initial_uid()) {
1251 not_root = True;
1252 become_root();
1255 ntstat = messaging_send(smbd_messaging_context(),
1256 session_list[snum].pid,
1257 MSG_SHUTDOWN, &data_blob_null);
1259 if (NT_STATUS_IS_OK(ntstat))
1260 werr = WERR_OK;
1262 if (not_root)
1263 unbecome_root();
1267 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1269 done:
1271 return werr;
1274 /*******************************************************************
1275 _srvsvc_NetShareEnumAll
1276 ********************************************************************/
1278 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p,
1279 struct srvsvc_NetShareEnumAll *r)
1281 WERROR werr;
1283 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1285 if (!pipe_access_check(p)) {
1286 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1287 return WERR_ACCESS_DENIED;
1290 /* Create the list of shares for the response. */
1291 werr = init_srv_share_info_ctr(p,
1292 r->in.info_ctr,
1293 r->in.resume_handle,
1294 r->out.totalentries,
1295 true);
1297 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1299 return werr;
1302 /*******************************************************************
1303 _srvsvc_NetShareEnum
1304 ********************************************************************/
1306 WERROR _srvsvc_NetShareEnum(pipes_struct *p,
1307 struct srvsvc_NetShareEnum *r)
1309 WERROR werr;
1311 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1313 if (!pipe_access_check(p)) {
1314 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1315 return WERR_ACCESS_DENIED;
1318 /* Create the list of shares for the response. */
1319 werr = init_srv_share_info_ctr(p,
1320 r->in.info_ctr,
1321 r->in.resume_handle,
1322 r->out.totalentries,
1323 false);
1325 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1327 return werr;
1330 /*******************************************************************
1331 _srvsvc_NetShareGetInfo
1332 ********************************************************************/
1334 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p,
1335 struct srvsvc_NetShareGetInfo *r)
1337 WERROR status = WERR_OK;
1338 fstring share_name;
1339 int snum;
1340 union srvsvc_NetShareInfo *info = r->out.info;
1342 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1344 fstrcpy(share_name, r->in.share_name);
1346 snum = find_service(share_name);
1347 if (snum < 0) {
1348 return WERR_INVALID_NAME;
1351 switch (r->in.level) {
1352 case 0:
1353 info->info0 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo0);
1354 W_ERROR_HAVE_NO_MEMORY(info->info0);
1355 init_srv_share_info_0(p, info->info0, snum);
1356 break;
1357 case 1:
1358 info->info1 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1);
1359 W_ERROR_HAVE_NO_MEMORY(info->info1);
1360 init_srv_share_info_1(p, info->info1, snum);
1361 break;
1362 case 2:
1363 info->info2 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo2);
1364 W_ERROR_HAVE_NO_MEMORY(info->info2);
1365 init_srv_share_info_2(p, info->info2, snum);
1366 break;
1367 case 501:
1368 info->info501 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo501);
1369 W_ERROR_HAVE_NO_MEMORY(info->info501);
1370 init_srv_share_info_501(p, info->info501, snum);
1371 break;
1372 case 502:
1373 info->info502 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo502);
1374 W_ERROR_HAVE_NO_MEMORY(info->info502);
1375 init_srv_share_info_502(p, info->info502, snum);
1376 break;
1377 case 1004:
1378 info->info1004 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1379 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1380 init_srv_share_info_1004(p, info->info1004, snum);
1381 break;
1382 case 1005:
1383 info->info1005 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1384 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1385 init_srv_share_info_1005(p, info->info1005, snum);
1386 break;
1387 case 1006:
1388 info->info1006 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1389 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1390 init_srv_share_info_1006(p, info->info1006, snum);
1391 break;
1392 case 1007:
1393 info->info1007 = TALLOC_P(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1394 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1395 init_srv_share_info_1007(p, info->info1007, snum);
1396 break;
1397 case 1501:
1398 init_srv_share_info_1501(p, info->info1501, snum);
1399 break;
1400 default:
1401 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1402 r->in.level));
1403 status = WERR_UNKNOWN_LEVEL;
1404 break;
1407 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1409 return status;
1412 /*******************************************************************
1413 Check a given DOS pathname is valid for a share.
1414 ********************************************************************/
1416 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
1418 char *ptr = NULL;
1420 if (!dos_pathname) {
1421 return NULL;
1424 ptr = talloc_strdup(ctx, dos_pathname);
1425 if (!ptr) {
1426 return NULL;
1428 /* Convert any '\' paths to '/' */
1429 unix_format(ptr);
1430 ptr = unix_clean_name(ctx, ptr);
1431 if (!ptr) {
1432 return NULL;
1435 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1436 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
1437 ptr += 2;
1439 /* Only absolute paths allowed. */
1440 if (*ptr != '/')
1441 return NULL;
1443 return ptr;
1446 /*******************************************************************
1447 _srvsvc_NetShareSetInfo. Modify share details.
1448 ********************************************************************/
1450 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p,
1451 struct srvsvc_NetShareSetInfo *r)
1453 struct current_user user;
1454 char *command = NULL;
1455 char *share_name = NULL;
1456 char *comment = NULL;
1457 const char *pathname = NULL;
1458 int type;
1459 int snum;
1460 int ret;
1461 char *path = NULL;
1462 SEC_DESC *psd = NULL;
1463 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1464 bool is_disk_op = False;
1465 int max_connections = 0;
1466 TALLOC_CTX *ctx = p->mem_ctx;
1467 union srvsvc_NetShareInfo *info = r->in.info;
1469 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1471 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1472 if (!share_name) {
1473 return WERR_NOMEM;
1476 if (r->out.parm_error) {
1477 *r->out.parm_error = 0;
1480 if ( strequal(share_name,"IPC$")
1481 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1482 || strequal(share_name,"global") )
1484 return WERR_ACCESS_DENIED;
1487 snum = find_service(share_name);
1489 /* Does this share exist ? */
1490 if (snum < 0)
1491 return WERR_NET_NAME_NOT_FOUND;
1493 /* No change to printer shares. */
1494 if (lp_print_ok(snum))
1495 return WERR_ACCESS_DENIED;
1497 get_current_user(&user,p);
1499 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1501 /* fail out now if you are not root and not a disk op */
1503 if ( user.ut.uid != sec_initial_uid() && !is_disk_op )
1504 return WERR_ACCESS_DENIED;
1506 switch (r->in.level) {
1507 case 1:
1508 pathname = talloc_strdup(ctx, lp_pathname(snum));
1509 comment = talloc_strdup(ctx, info->info1->comment);
1510 type = info->info1->type;
1511 psd = NULL;
1512 break;
1513 case 2:
1514 comment = talloc_strdup(ctx, info->info2->comment);
1515 pathname = info->info2->path;
1516 type = info->info2->type;
1517 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1518 0 : info->info2->max_users;
1519 psd = NULL;
1520 break;
1521 #if 0
1522 /* not supported on set but here for completeness */
1523 case 501:
1524 comment = talloc_strdup(ctx, info->info501->comment);
1525 type = info->info501->type;
1526 psd = NULL;
1527 break;
1528 #endif
1529 case 502:
1530 comment = talloc_strdup(ctx, info->info502->comment);
1531 pathname = info->info502->path;
1532 type = info->info502->type;
1533 psd = info->info502->sd_buf.sd;
1534 map_generic_share_sd_bits(psd);
1535 break;
1536 case 1004:
1537 pathname = talloc_strdup(ctx, lp_pathname(snum));
1538 comment = talloc_strdup(ctx, info->info1004->comment);
1539 type = STYPE_DISKTREE;
1540 break;
1541 case 1005:
1542 /* XP re-sets the csc policy even if it wasn't changed by the
1543 user, so we must compare it to see if it's what is set in
1544 smb.conf, so that we can contine other ops like setting
1545 ACLs on a share */
1546 if (((info->info1005->dfs_flags &
1547 SHARE_1005_CSC_POLICY_MASK) >>
1548 SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1549 return WERR_OK;
1550 else {
1551 DEBUG(3, ("_srvsvc_NetShareSetInfo: client is trying to change csc policy from the network; must be done with smb.conf\n"));
1552 return WERR_ACCESS_DENIED;
1554 case 1006:
1555 case 1007:
1556 return WERR_ACCESS_DENIED;
1557 case 1501:
1558 pathname = talloc_strdup(ctx, lp_pathname(snum));
1559 comment = talloc_strdup(ctx, lp_comment(snum));
1560 psd = info->info1501->sd;
1561 map_generic_share_sd_bits(psd);
1562 type = STYPE_DISKTREE;
1563 break;
1564 default:
1565 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1566 r->in.level));
1567 return WERR_UNKNOWN_LEVEL;
1570 /* We can only modify disk shares. */
1571 if (type != STYPE_DISKTREE)
1572 return WERR_ACCESS_DENIED;
1574 if (comment == NULL) {
1575 return WERR_NOMEM;
1578 /* Check if the pathname is valid. */
1579 if (!(path = valid_share_pathname(p->mem_ctx, pathname )))
1580 return WERR_OBJECT_PATH_INVALID;
1582 /* Ensure share name, pathname and comment don't contain '"' characters. */
1583 string_replace(share_name, '"', ' ');
1584 string_replace(path, '"', ' ');
1585 string_replace(comment, '"', ' ');
1587 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1588 lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1590 /* Only call modify function if something changed. */
1592 if (strcmp(path, lp_pathname(snum)) || strcmp(comment, lp_comment(snum))
1593 || (lp_max_connections(snum) != max_connections)) {
1594 if (!lp_change_share_cmd() || !*lp_change_share_cmd()) {
1595 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1596 return WERR_ACCESS_DENIED;
1599 command = talloc_asprintf(p->mem_ctx,
1600 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1601 lp_change_share_cmd(),
1602 get_dyn_CONFIGFILE(),
1603 share_name,
1604 path,
1605 comment ? comment : "",
1606 max_connections);
1607 if (!command) {
1608 return WERR_NOMEM;
1611 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1613 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1615 if (is_disk_op)
1616 become_root();
1618 if ( (ret = smbrun(command, NULL)) == 0 ) {
1619 /* Tell everyone we updated smb.conf. */
1620 message_send_all(smbd_messaging_context(),
1621 MSG_SMB_CONF_UPDATED, NULL, 0,
1622 NULL);
1625 if ( is_disk_op )
1626 unbecome_root();
1628 /********* END SeDiskOperatorPrivilege BLOCK *********/
1630 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1631 command, ret ));
1633 TALLOC_FREE(command);
1635 if ( ret != 0 )
1636 return WERR_ACCESS_DENIED;
1637 } else {
1638 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1639 share_name ));
1642 /* Replace SD if changed. */
1643 if (psd) {
1644 SEC_DESC *old_sd;
1645 size_t sd_size;
1647 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum), &sd_size);
1649 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1650 if (!set_share_security(share_name, psd))
1651 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1652 share_name ));
1656 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1658 return WERR_OK;
1661 /*******************************************************************
1662 _srvsvc_NetShareAdd.
1663 Call 'add_share_command "sharename" "pathname"
1664 "comment" "max connections = "
1665 ********************************************************************/
1667 WERROR _srvsvc_NetShareAdd(pipes_struct *p,
1668 struct srvsvc_NetShareAdd *r)
1670 struct current_user user;
1671 char *command = NULL;
1672 char *share_name = NULL;
1673 char *comment = NULL;
1674 char *pathname = NULL;
1675 int type;
1676 int snum;
1677 int ret;
1678 char *path;
1679 SEC_DESC *psd = NULL;
1680 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1681 bool is_disk_op;
1682 int max_connections = 0;
1683 TALLOC_CTX *ctx = p->mem_ctx;
1685 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1687 if (r->out.parm_error) {
1688 *r->out.parm_error = 0;
1691 get_current_user(&user,p);
1693 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1695 if (user.ut.uid != sec_initial_uid() && !is_disk_op )
1696 return WERR_ACCESS_DENIED;
1698 if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
1699 DEBUG(10,("_srvsvc_NetShareAdd: No add share command\n"));
1700 return WERR_ACCESS_DENIED;
1703 switch (r->in.level) {
1704 case 0:
1705 /* No path. Not enough info in a level 0 to do anything. */
1706 return WERR_ACCESS_DENIED;
1707 case 1:
1708 /* Not enough info in a level 1 to do anything. */
1709 return WERR_ACCESS_DENIED;
1710 case 2:
1711 share_name = talloc_strdup(ctx, r->in.info->info2->name);
1712 comment = talloc_strdup(ctx, r->in.info->info2->comment);
1713 pathname = talloc_strdup(ctx, r->in.info->info2->path);
1714 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
1715 0 : r->in.info->info2->max_users;
1716 type = r->in.info->info2->type;
1717 break;
1718 case 501:
1719 /* No path. Not enough info in a level 501 to do anything. */
1720 return WERR_ACCESS_DENIED;
1721 case 502:
1722 share_name = talloc_strdup(ctx, r->in.info->info502->name);
1723 comment = talloc_strdup(ctx, r->in.info->info502->comment);
1724 pathname = talloc_strdup(ctx, r->in.info->info502->path);
1725 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
1726 0 : r->in.info->info502->max_users;
1727 type = r->in.info->info502->type;
1728 psd = r->in.info->info502->sd_buf.sd;
1729 map_generic_share_sd_bits(psd);
1730 break;
1732 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
1734 case 1004:
1735 case 1005:
1736 case 1006:
1737 case 1007:
1738 return WERR_ACCESS_DENIED;
1739 case 1501:
1740 /* DFS only level. */
1741 return WERR_ACCESS_DENIED;
1742 default:
1743 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
1744 r->in.level));
1745 return WERR_UNKNOWN_LEVEL;
1748 /* check for invalid share names */
1750 if (!share_name || !validate_net_name(share_name,
1751 INVALID_SHARENAME_CHARS,
1752 strlen(share_name))) {
1753 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
1754 share_name ? share_name : ""));
1755 return WERR_INVALID_NAME;
1758 if (strequal(share_name,"IPC$") || strequal(share_name,"global")
1759 || (lp_enable_asu_support() &&
1760 strequal(share_name,"ADMIN$"))) {
1761 return WERR_ACCESS_DENIED;
1764 snum = find_service(share_name);
1766 /* Share already exists. */
1767 if (snum >= 0) {
1768 return WERR_ALREADY_EXISTS;
1771 /* We can only add disk shares. */
1772 if (type != STYPE_DISKTREE) {
1773 return WERR_ACCESS_DENIED;
1776 /* Check if the pathname is valid. */
1777 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
1778 return WERR_OBJECT_PATH_INVALID;
1781 /* Ensure share name, pathname and comment don't contain '"' characters. */
1782 string_replace(share_name, '"', ' ');
1783 string_replace(path, '"', ' ');
1784 if (comment) {
1785 string_replace(comment, '"', ' ');
1788 command = talloc_asprintf(ctx,
1789 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1790 lp_add_share_cmd(),
1791 get_dyn_CONFIGFILE(),
1792 share_name,
1793 path,
1794 comment ? comment : "",
1795 max_connections);
1796 if (!command) {
1797 return WERR_NOMEM;
1800 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
1802 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1804 if ( is_disk_op )
1805 become_root();
1807 /* FIXME: use libnetconf here - gd */
1809 if ( (ret = smbrun(command, NULL)) == 0 ) {
1810 /* Tell everyone we updated smb.conf. */
1811 message_send_all(smbd_messaging_context(),
1812 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1815 if ( is_disk_op )
1816 unbecome_root();
1818 /********* END SeDiskOperatorPrivilege BLOCK *********/
1820 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
1821 command, ret ));
1823 TALLOC_FREE(command);
1825 if ( ret != 0 )
1826 return WERR_ACCESS_DENIED;
1828 if (psd) {
1829 if (!set_share_security(share_name, psd)) {
1830 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
1831 share_name ));
1836 * We don't call reload_services() here, the message will
1837 * cause this to be done before the next packet is read
1838 * from the client. JRA.
1841 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1843 return WERR_OK;
1846 /*******************************************************************
1847 _srvsvc_NetShareDel
1848 Call "delete share command" with the share name as
1849 a parameter.
1850 ********************************************************************/
1852 WERROR _srvsvc_NetShareDel(pipes_struct *p,
1853 struct srvsvc_NetShareDel *r)
1855 struct current_user user;
1856 char *command = NULL;
1857 char *share_name = NULL;
1858 int ret;
1859 int snum;
1860 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1861 bool is_disk_op;
1862 struct share_params *params;
1863 TALLOC_CTX *ctx = p->mem_ctx;
1865 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
1867 share_name = talloc_strdup(p->mem_ctx, r->in.share_name);
1868 if (!share_name) {
1869 return WERR_NET_NAME_NOT_FOUND;
1871 if ( strequal(share_name,"IPC$")
1872 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
1873 || strequal(share_name,"global") )
1875 return WERR_ACCESS_DENIED;
1878 if (!(params = get_share_params(p->mem_ctx, share_name))) {
1879 return WERR_NO_SUCH_SHARE;
1882 snum = find_service(share_name);
1884 /* No change to printer shares. */
1885 if (lp_print_ok(snum))
1886 return WERR_ACCESS_DENIED;
1888 get_current_user(&user,p);
1890 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
1892 if (user.ut.uid != sec_initial_uid() && !is_disk_op )
1893 return WERR_ACCESS_DENIED;
1895 if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
1896 DEBUG(10,("_srvsvc_NetShareDel: No delete share command\n"));
1897 return WERR_ACCESS_DENIED;
1900 command = talloc_asprintf(ctx,
1901 "%s \"%s\" \"%s\"",
1902 lp_delete_share_cmd(),
1903 get_dyn_CONFIGFILE(),
1904 lp_servicename(snum));
1905 if (!command) {
1906 return WERR_NOMEM;
1909 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
1911 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1913 if ( is_disk_op )
1914 become_root();
1916 if ( (ret = smbrun(command, NULL)) == 0 ) {
1917 /* Tell everyone we updated smb.conf. */
1918 message_send_all(smbd_messaging_context(),
1919 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1922 if ( is_disk_op )
1923 unbecome_root();
1925 /********* END SeDiskOperatorPrivilege BLOCK *********/
1927 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
1929 if ( ret != 0 )
1930 return WERR_ACCESS_DENIED;
1932 /* Delete the SD in the database. */
1933 delete_share_security(lp_servicename(params->service));
1935 lp_killservice(params->service);
1937 return WERR_OK;
1940 /*******************************************************************
1941 _srvsvc_NetShareDelSticky
1942 ********************************************************************/
1944 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p,
1945 struct srvsvc_NetShareDelSticky *r)
1947 struct srvsvc_NetShareDel q;
1949 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
1951 q.in.server_unc = r->in.server_unc;
1952 q.in.share_name = r->in.share_name;
1953 q.in.reserved = r->in.reserved;
1955 return _srvsvc_NetShareDel(p, &q);
1958 /*******************************************************************
1959 _srvsvc_NetRemoteTOD
1960 ********************************************************************/
1962 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p,
1963 struct srvsvc_NetRemoteTOD *r)
1965 struct srvsvc_NetRemoteTODInfo *tod;
1966 struct tm *t;
1967 time_t unixdate = time(NULL);
1969 /* We do this call first as if we do it *after* the gmtime call
1970 it overwrites the pointed-to values. JRA */
1972 uint32 zone = get_time_zone(unixdate)/60;
1974 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
1976 if ( !(tod = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
1977 return WERR_NOMEM;
1979 *r->out.info = tod;
1981 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
1983 t = gmtime(&unixdate);
1985 /* set up the */
1986 init_srvsvc_NetRemoteTODInfo(tod,
1987 unixdate,
1989 t->tm_hour,
1990 t->tm_min,
1991 t->tm_sec,
1993 zone,
1994 10000,
1995 t->tm_mday,
1996 t->tm_mon + 1,
1997 1900+t->tm_year,
1998 t->tm_wday);
2000 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2002 return WERR_OK;
2005 /***********************************************************************************
2006 _srvsvc_NetGetFileSecurity
2007 Win9x NT tools get security descriptor.
2008 ***********************************************************************************/
2010 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p,
2011 struct srvsvc_NetGetFileSecurity *r)
2013 SEC_DESC *psd = NULL;
2014 size_t sd_size;
2015 DATA_BLOB null_pw;
2016 char *filename_in = NULL;
2017 char *filename = NULL;
2018 char *qualname = NULL;
2019 SMB_STRUCT_STAT st;
2020 NTSTATUS nt_status;
2021 WERROR werr;
2022 struct current_user user;
2023 connection_struct *conn = NULL;
2024 bool became_user = False;
2025 TALLOC_CTX *ctx = p->mem_ctx;
2026 struct sec_desc_buf *sd_buf;
2028 ZERO_STRUCT(st);
2030 werr = WERR_OK;
2032 qualname = talloc_strdup(ctx, r->in.share);
2033 if (!qualname) {
2034 werr = WERR_ACCESS_DENIED;
2035 goto error_exit;
2038 /* Null password is ok - we are already an authenticated user... */
2039 null_pw = data_blob_null;
2041 get_current_user(&user, p);
2043 become_root();
2044 conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
2045 unbecome_root();
2047 if (conn == NULL) {
2048 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to connect to %s\n",
2049 qualname));
2050 werr = ntstatus_to_werror(nt_status);
2051 goto error_exit;
2054 if (!become_user(conn, conn->vuid)) {
2055 DEBUG(0,("_srvsvc_NetGetFileSecurity: Can't become connected user!\n"));
2056 werr = WERR_ACCESS_DENIED;
2057 goto error_exit;
2059 became_user = True;
2061 filename_in = talloc_strdup(ctx, r->in.file);
2062 if (!filename_in) {
2063 werr = WERR_ACCESS_DENIED;
2064 goto error_exit;
2067 nt_status = unix_convert(ctx, conn, filename_in, False, &filename, NULL, &st);
2068 if (!NT_STATUS_IS_OK(nt_status)) {
2069 DEBUG(3,("_srvsvc_NetGetFileSecurity: bad pathname %s\n",
2070 filename));
2071 werr = WERR_ACCESS_DENIED;
2072 goto error_exit;
2075 nt_status = check_name(conn, filename);
2076 if (!NT_STATUS_IS_OK(nt_status)) {
2077 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't access %s\n",
2078 filename));
2079 werr = WERR_ACCESS_DENIED;
2080 goto error_exit;
2083 nt_status = SMB_VFS_GET_NT_ACL(conn, filename,
2084 (OWNER_SECURITY_INFORMATION
2085 |GROUP_SECURITY_INFORMATION
2086 |DACL_SECURITY_INFORMATION), &psd);
2088 if (!NT_STATUS_IS_OK(nt_status)) {
2089 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL for file %s\n",
2090 filename));
2091 werr = ntstatus_to_werror(nt_status);
2092 goto error_exit;
2095 sd_size = ndr_size_security_descriptor(psd, 0);
2097 sd_buf = TALLOC_ZERO_P(ctx, struct sec_desc_buf);
2098 if (!sd_buf) {
2099 werr = WERR_NOMEM;
2100 goto error_exit;
2103 sd_buf->sd_size = sd_size;
2104 sd_buf->sd = psd;
2106 *r->out.sd_buf = sd_buf;
2108 psd->dacl->revision = NT4_ACL_REVISION;
2110 unbecome_user();
2111 close_cnum(conn, user.vuid);
2112 return werr;
2114 error_exit:
2116 if (became_user)
2117 unbecome_user();
2119 if (conn)
2120 close_cnum(conn, user.vuid);
2122 return werr;
2125 /***********************************************************************************
2126 _srvsvc_NetSetFileSecurity
2127 Win9x NT tools set security descriptor.
2128 ***********************************************************************************/
2130 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p,
2131 struct srvsvc_NetSetFileSecurity *r)
2133 char *filename_in = NULL;
2134 char *filename = NULL;
2135 char *qualname = NULL;
2136 DATA_BLOB null_pw;
2137 files_struct *fsp = NULL;
2138 SMB_STRUCT_STAT st;
2139 NTSTATUS nt_status;
2140 WERROR werr;
2141 struct current_user user;
2142 connection_struct *conn = NULL;
2143 bool became_user = False;
2144 TALLOC_CTX *ctx = p->mem_ctx;
2146 ZERO_STRUCT(st);
2148 werr = WERR_OK;
2150 qualname = talloc_strdup(ctx, r->in.share);
2151 if (!qualname) {
2152 werr = WERR_ACCESS_DENIED;
2153 goto error_exit;
2156 /* Null password is ok - we are already an authenticated user... */
2157 null_pw = data_blob_null;
2159 get_current_user(&user, p);
2161 become_root();
2162 conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
2163 unbecome_root();
2165 if (conn == NULL) {
2166 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to connect to %s\n", qualname));
2167 werr = ntstatus_to_werror(nt_status);
2168 goto error_exit;
2171 if (!become_user(conn, conn->vuid)) {
2172 DEBUG(0,("_srvsvc_NetSetFileSecurity: Can't become connected user!\n"));
2173 werr = WERR_ACCESS_DENIED;
2174 goto error_exit;
2176 became_user = True;
2178 filename_in = talloc_strdup(ctx, r->in.file);
2179 if (!filename_in) {
2180 werr = WERR_ACCESS_DENIED;
2181 goto error_exit;
2184 nt_status = unix_convert(ctx, conn, filename, False, &filename, NULL, &st);
2185 if (!NT_STATUS_IS_OK(nt_status)) {
2186 DEBUG(3,("_srvsvc_NetSetFileSecurity: bad pathname %s\n", filename));
2187 werr = WERR_ACCESS_DENIED;
2188 goto error_exit;
2191 nt_status = check_name(conn, filename);
2192 if (!NT_STATUS_IS_OK(nt_status)) {
2193 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't access %s\n", filename));
2194 werr = WERR_ACCESS_DENIED;
2195 goto error_exit;
2198 nt_status = open_file_stat(conn, NULL, filename, &st, &fsp);
2200 if ( !NT_STATUS_IS_OK(nt_status) ) {
2201 /* Perhaps it is a directory */
2202 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2203 nt_status = open_directory(conn, NULL, filename, &st,
2204 FILE_READ_ATTRIBUTES,
2205 FILE_SHARE_READ|FILE_SHARE_WRITE,
2206 FILE_OPEN,
2208 FILE_ATTRIBUTE_DIRECTORY,
2209 NULL, &fsp);
2211 if ( !NT_STATUS_IS_OK(nt_status) ) {
2212 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to open file %s\n", filename));
2213 werr = ntstatus_to_werror(nt_status);
2214 goto error_exit;
2218 nt_status = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name,
2219 r->in.securityinformation,
2220 r->in.sd_buf->sd);
2222 if (!NT_STATUS_IS_OK(nt_status) ) {
2223 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL on file %s\n", filename));
2224 werr = WERR_ACCESS_DENIED;
2225 goto error_exit;
2228 close_file(fsp, NORMAL_CLOSE);
2229 unbecome_user();
2230 close_cnum(conn, user.vuid);
2231 return werr;
2233 error_exit:
2235 if(fsp) {
2236 close_file(fsp, NORMAL_CLOSE);
2239 if (became_user) {
2240 unbecome_user();
2243 if (conn) {
2244 close_cnum(conn, user.vuid);
2247 return werr;
2250 /***********************************************************************************
2251 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2252 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2253 These disks would the disks listed by this function.
2254 Users could then create shares relative to these disks. Watch out for moving these disks around.
2255 "Nigel Williams" <nigel@veritas.com>.
2256 ***********************************************************************************/
2258 static const char *server_disks[] = {"C:"};
2260 static uint32 get_server_disk_count(void)
2262 return sizeof(server_disks)/sizeof(server_disks[0]);
2265 static uint32 init_server_disk_enum(uint32 *resume)
2267 uint32 server_disk_count = get_server_disk_count();
2269 /*resume can be an offset into the list for now*/
2271 if(*resume & 0x80000000)
2272 *resume = 0;
2274 if(*resume > server_disk_count)
2275 *resume = server_disk_count;
2277 return server_disk_count - *resume;
2280 static const char *next_server_disk_enum(uint32 *resume)
2282 const char *disk;
2284 if(init_server_disk_enum(resume) == 0)
2285 return NULL;
2287 disk = server_disks[*resume];
2289 (*resume)++;
2291 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2293 return disk;
2296 /********************************************************************
2297 _srvsvc_NetDiskEnum
2298 ********************************************************************/
2300 WERROR _srvsvc_NetDiskEnum(pipes_struct *p,
2301 struct srvsvc_NetDiskEnum *r)
2303 uint32 i;
2304 const char *disk_name;
2305 TALLOC_CTX *ctx = p->mem_ctx;
2306 WERROR werr;
2307 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2309 werr = WERR_OK;
2311 *r->out.totalentries = init_server_disk_enum(&resume);
2313 r->out.info->disks = TALLOC_ZERO_ARRAY(ctx, struct srvsvc_NetDiskInfo0,
2314 MAX_SERVER_DISK_ENTRIES);
2315 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2317 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2319 r->out.info->count = 0;
2321 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2323 r->out.info->count++;
2325 /*copy disk name into a unicode string*/
2327 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2328 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2331 /* add a terminating null string. Is this there if there is more data to come? */
2333 r->out.info->count++;
2335 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2336 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2338 if (r->out.resume_handle) {
2339 *r->out.resume_handle = resume;
2342 return werr;
2345 /********************************************************************
2346 _srvsvc_NetNameValidate
2347 ********************************************************************/
2349 WERROR _srvsvc_NetNameValidate(pipes_struct *p,
2350 struct srvsvc_NetNameValidate *r)
2352 switch (r->in.name_type) {
2353 case 0x9:
2354 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2355 strlen_m(r->in.name)))
2357 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2358 r->in.name));
2359 return WERR_INVALID_NAME;
2361 break;
2363 default:
2364 return WERR_UNKNOWN_LEVEL;
2367 return WERR_OK;
2370 /*******************************************************************
2371 ********************************************************************/
2373 static void enum_file_close_fn( const struct share_mode_entry *e,
2374 const char *sharepath, const char *fname,
2375 void *private_data )
2377 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2378 struct srvsvc_NetFileClose *r =
2379 (struct srvsvc_NetFileClose *)private_data;
2380 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2382 if (fid != r->in.fid) {
2383 return; /* Not this file. */
2386 if (!process_exists(e->pid) ) {
2387 return;
2390 /* Ok - send the close message. */
2391 DEBUG(10,("enum_file_close_fn: request to close file %s, %s\n",
2392 sharepath,
2393 share_mode_str(talloc_tos(), 0, e) ));
2395 share_mode_entry_to_message(msg, e);
2397 r->out.result = ntstatus_to_werror(
2398 messaging_send_buf(smbd_messaging_context(),
2399 e->pid, MSG_SMB_CLOSE_FILE,
2400 (uint8 *)msg,
2401 MSG_SMB_SHARE_MODE_ENTRY_SIZE));
2404 /********************************************************************
2405 Close a file given a 32-bit file id.
2406 ********************************************************************/
2408 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2410 struct current_user user;
2411 SE_PRIV se_diskop = SE_DISK_OPERATOR;
2412 bool is_disk_op;
2414 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2416 get_current_user(&user,p);
2418 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
2420 if (user.ut.uid != sec_initial_uid() && !is_disk_op) {
2421 return WERR_ACCESS_DENIED;
2424 /* enum_file_close_fn sends the close message to
2425 * the relevent smbd process. */
2427 r->out.result = WERR_BADFILE;
2428 share_mode_forall( enum_file_close_fn, (void *)r);
2429 return r->out.result;
2432 /********************************************************************
2433 ********************************************************************/
2435 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2437 p->rng_fault_state = True;
2438 return WERR_NOT_SUPPORTED;
2441 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2443 p->rng_fault_state = True;
2444 return WERR_NOT_SUPPORTED;
2447 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2449 p->rng_fault_state = True;
2450 return WERR_NOT_SUPPORTED;
2453 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2455 p->rng_fault_state = True;
2456 return WERR_NOT_SUPPORTED;
2459 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2461 p->rng_fault_state = True;
2462 return WERR_NOT_SUPPORTED;
2465 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2467 p->rng_fault_state = True;
2468 return WERR_NOT_SUPPORTED;
2471 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2473 p->rng_fault_state = True;
2474 return WERR_NOT_SUPPORTED;
2477 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2479 p->rng_fault_state = True;
2480 return WERR_NOT_SUPPORTED;
2483 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2485 p->rng_fault_state = True;
2486 return WERR_NOT_SUPPORTED;
2489 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2491 p->rng_fault_state = True;
2492 return WERR_NOT_SUPPORTED;
2495 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2497 p->rng_fault_state = True;
2498 return WERR_NOT_SUPPORTED;
2501 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2503 p->rng_fault_state = True;
2504 return WERR_NOT_SUPPORTED;
2507 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2509 p->rng_fault_state = True;
2510 return WERR_NOT_SUPPORTED;
2513 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2515 p->rng_fault_state = True;
2516 return WERR_NOT_SUPPORTED;
2519 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2521 p->rng_fault_state = True;
2522 return WERR_NOT_SUPPORTED;
2525 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2527 p->rng_fault_state = True;
2528 return WERR_NOT_SUPPORTED;
2531 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2533 p->rng_fault_state = True;
2534 return WERR_NOT_SUPPORTED;
2537 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2539 p->rng_fault_state = True;
2540 return WERR_NOT_SUPPORTED;
2543 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2545 p->rng_fault_state = True;
2546 return WERR_NOT_SUPPORTED;
2549 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2551 p->rng_fault_state = True;
2552 return WERR_NOT_SUPPORTED;
2555 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2557 p->rng_fault_state = True;
2558 return WERR_NOT_SUPPORTED;
2561 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2563 p->rng_fault_state = True;
2564 return WERR_NOT_SUPPORTED;
2567 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2569 p->rng_fault_state = True;
2570 return WERR_NOT_SUPPORTED;
2573 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2575 p->rng_fault_state = True;
2576 return WERR_NOT_SUPPORTED;
2579 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2581 p->rng_fault_state = True;
2582 return WERR_NOT_SUPPORTED;
2585 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2587 p->rng_fault_state = True;
2588 return WERR_NOT_SUPPORTED;
2591 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2593 p->rng_fault_state = True;
2594 return WERR_NOT_SUPPORTED;
2597 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
2599 p->rng_fault_state = True;
2600 return WERR_NOT_SUPPORTED;
2603 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2605 p->rng_fault_state = True;
2606 return WERR_NOT_SUPPORTED;
2609 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2611 p->rng_fault_state = True;
2612 return WERR_NOT_SUPPORTED;
2615 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2617 p->rng_fault_state = True;
2618 return WERR_NOT_SUPPORTED;
2621 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2623 p->rng_fault_state = True;
2624 return WERR_NOT_SUPPORTED;
2627 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2629 p->rng_fault_state = True;
2630 return WERR_NOT_SUPPORTED;
2633 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2635 p->rng_fault_state = True;
2636 return WERR_NOT_SUPPORTED;
2639 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2641 p->rng_fault_state = True;
2642 return WERR_NOT_SUPPORTED;