Move setting of psd->dacl->revision and protect against null SD's.
[Samba.git] / source3 / rpc_server / srvsvc / srv_srvsvc_nt.c
blob1d976e1e87d5cc7b39e5ff195da1c5a97d2b1ba2
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"
27 #include "system/passwd.h"
28 #include "ntdomain.h"
29 #include "../librpc/gen_ndr/srv_srvsvc.h"
30 #include "../libcli/security/security.h"
31 #include "../librpc/gen_ndr/ndr_security.h"
32 #include "../librpc/gen_ndr/open_files.h"
33 #include "dbwrap/dbwrap.h"
34 #include "session.h"
35 #include "../lib/util/util_pw.h"
36 #include "smbd/smbd.h"
37 #include "smbd/globals.h"
38 #include "auth.h"
39 #include "messages.h"
40 #include "lib/conn_tdb.h"
42 extern const struct generic_mapping file_generic_mapping;
44 #undef DBGC_CLASS
45 #define DBGC_CLASS DBGC_RPC_SRV
47 #define MAX_SERVER_DISK_ENTRIES 15
49 /* Use for enumerating connections, pipes, & files */
51 struct file_enum_count {
52 TALLOC_CTX *ctx;
53 const char *username;
54 struct srvsvc_NetFileCtr3 *ctr3;
57 struct sess_file_count {
58 struct server_id pid;
59 uid_t uid;
60 int count;
63 /* Used to store pipe open records for NetFileEnum() */
65 struct pipe_open_rec {
66 struct server_id pid;
67 uid_t uid;
68 int pnum;
69 fstring name;
72 /****************************************************************************
73 Count the entries belonging to a service in the connection db.
74 ****************************************************************************/
76 static int pipe_enum_fn( struct db_record *rec, void *p)
78 struct pipe_open_rec prec;
79 struct file_enum_count *fenum = (struct file_enum_count *)p;
80 struct srvsvc_NetFileInfo3 *f;
81 int i = fenum->ctr3->count;
82 char *fullpath = NULL;
83 const char *username;
84 TDB_DATA value;
86 value = dbwrap_record_get_value(rec);
88 if (value.dsize != sizeof(struct pipe_open_rec))
89 return 0;
91 memcpy(&prec, value.dptr, sizeof(struct pipe_open_rec));
93 if ( !process_exists(prec.pid) ) {
94 return 0;
97 username = uidtoname(prec.uid);
99 if ((fenum->username != NULL)
100 && !strequal(username, fenum->username)) {
101 return 0;
104 fullpath = talloc_asprintf(fenum->ctx, "\\PIPE\\%s", prec.name );
105 if (!fullpath) {
106 return 1;
109 f = talloc_realloc(fenum->ctx, fenum->ctr3->array,
110 struct srvsvc_NetFileInfo3, i+1);
111 if ( !f ) {
112 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
113 return 1;
115 fenum->ctr3->array = f;
117 fenum->ctr3->array[i].fid =
118 (((uint32_t)(procid_to_pid(&prec.pid))<<16) | prec.pnum);
119 fenum->ctr3->array[i].permissions =
120 (FILE_READ_DATA|FILE_WRITE_DATA);
121 fenum->ctr3->array[i].num_locks = 0;
122 fenum->ctr3->array[i].path = fullpath;
123 fenum->ctr3->array[i].user = username;
125 fenum->ctr3->count++;
127 return 0;
130 /*******************************************************************
131 ********************************************************************/
133 static WERROR net_enum_pipes(TALLOC_CTX *ctx,
134 const char *username,
135 struct srvsvc_NetFileCtr3 **ctr3,
136 uint32_t resume )
138 struct file_enum_count fenum;
140 fenum.ctx = ctx;
141 fenum.username = username;
142 fenum.ctr3 = *ctr3;
144 if (connections_traverse(pipe_enum_fn, &fenum) < 0) {
145 DEBUG(0,("net_enum_pipes: traverse of connections.tdb "
146 "failed\n"));
147 return WERR_NOMEM;
150 *ctr3 = fenum.ctr3;
152 return WERR_OK;
155 /*******************************************************************
156 ********************************************************************/
158 static void enum_file_fn( const struct share_mode_entry *e,
159 const char *sharepath, const char *fname,
160 void *private_data )
162 struct file_enum_count *fenum =
163 (struct file_enum_count *)private_data;
165 struct srvsvc_NetFileInfo3 *f;
166 int i = fenum->ctr3->count;
167 files_struct fsp;
168 struct byte_range_lock *brl;
169 int num_locks = 0;
170 char *fullpath = NULL;
171 uint32 permissions;
172 const char *username;
174 /* If the pid was not found delete the entry from connections.tdb */
176 if ( !process_exists(e->pid) ) {
177 return;
180 username = uidtoname(e->uid);
182 if ((fenum->username != NULL)
183 && !strequal(username, fenum->username)) {
184 return;
187 f = talloc_realloc(fenum->ctx, fenum->ctr3->array,
188 struct srvsvc_NetFileInfo3, i+1);
189 if ( !f ) {
190 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
191 return;
193 fenum->ctr3->array = f;
195 /* need to count the number of locks on a file */
197 ZERO_STRUCT( fsp );
198 fsp.file_id = e->id;
200 if ( (brl = brl_get_locks(talloc_tos(), &fsp)) != NULL ) {
201 num_locks = brl->num_locks;
202 TALLOC_FREE(brl);
205 if ( strcmp( fname, "." ) == 0 ) {
206 fullpath = talloc_asprintf(fenum->ctx, "C:%s", sharepath );
207 } else {
208 fullpath = talloc_asprintf(fenum->ctx, "C:%s/%s",
209 sharepath, fname );
211 if (!fullpath) {
212 return;
214 string_replace( fullpath, '/', '\\' );
216 /* mask out create (what ever that is) */
217 permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
219 /* now fill in the srvsvc_NetFileInfo3 struct */
221 fenum->ctr3->array[i].fid =
222 (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
223 fenum->ctr3->array[i].permissions = permissions;
224 fenum->ctr3->array[i].num_locks = num_locks;
225 fenum->ctr3->array[i].path = fullpath;
226 fenum->ctr3->array[i].user = username;
228 fenum->ctr3->count++;
231 /*******************************************************************
232 ********************************************************************/
234 static WERROR net_enum_files(TALLOC_CTX *ctx,
235 const char *username,
236 struct srvsvc_NetFileCtr3 **ctr3,
237 uint32_t resume)
239 struct file_enum_count f_enum_cnt;
241 f_enum_cnt.ctx = ctx;
242 f_enum_cnt.username = username;
243 f_enum_cnt.ctr3 = *ctr3;
245 share_mode_forall( enum_file_fn, (void *)&f_enum_cnt );
247 *ctr3 = f_enum_cnt.ctr3;
249 return WERR_OK;
252 /*******************************************************************
253 Utility function to get the 'type' of a share from an snum.
254 ********************************************************************/
255 static enum srvsvc_ShareType get_share_type(int snum)
257 /* work out the share type */
258 enum srvsvc_ShareType type = STYPE_DISKTREE;
260 if (lp_print_ok(snum)) {
261 type = lp_administrative_share(snum)
262 ? STYPE_PRINTQ_HIDDEN : STYPE_PRINTQ;
264 if (strequal(lp_fstype(talloc_tos(), snum), "IPC")) {
265 type = lp_administrative_share(snum)
266 ? STYPE_IPC_HIDDEN : STYPE_IPC;
268 return type;
271 /*******************************************************************
272 Fill in a share info level 0 structure.
273 ********************************************************************/
275 static void init_srv_share_info_0(struct pipes_struct *p,
276 struct srvsvc_NetShareInfo0 *r, int snum)
278 r->name = lp_servicename(talloc_tos(), snum);
281 /*******************************************************************
282 Fill in a share info level 1 structure.
283 ********************************************************************/
285 static void init_srv_share_info_1(struct pipes_struct *p,
286 struct srvsvc_NetShareInfo1 *r,
287 int snum)
289 char *net_name = lp_servicename(talloc_tos(), snum);
290 char *remark = lp_comment(p->mem_ctx, snum);
292 if (remark) {
293 remark = talloc_sub_advanced(
294 p->mem_ctx, lp_servicename(talloc_tos(), snum),
295 get_current_username(), lp_pathname(talloc_tos(), snum),
296 p->session_info->unix_token->uid, get_current_username(),
297 "", remark);
300 r->name = net_name;
301 r->type = get_share_type(snum);
302 r->comment = remark ? remark : "";
305 /*******************************************************************
306 Fill in a share info level 2 structure.
307 ********************************************************************/
309 static void init_srv_share_info_2(struct pipes_struct *p,
310 struct srvsvc_NetShareInfo2 *r,
311 int snum)
313 char *remark = NULL;
314 char *path = NULL;
315 int max_connections = lp_max_connections(snum);
316 uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
317 char *net_name = lp_servicename(talloc_tos(), snum);
319 remark = lp_comment(p->mem_ctx, snum);
320 if (remark) {
321 remark = talloc_sub_advanced(
322 p->mem_ctx, lp_servicename(talloc_tos(), snum),
323 get_current_username(), lp_pathname(talloc_tos(), snum),
324 p->session_info->unix_token->uid, get_current_username(),
325 "", remark);
327 path = talloc_asprintf(p->mem_ctx,
328 "C:%s", lp_pathname(talloc_tos(), snum));
330 if (path) {
332 * Change / to \\ so that win2k will see it as a valid path.
333 * This was added to enable use of browsing in win2k add
334 * share dialog.
337 string_replace(path, '/', '\\');
340 r->name = net_name;
341 r->type = get_share_type(snum);
342 r->comment = remark ? remark : "";
343 r->permissions = 0;
344 r->max_users = max_uses;
345 r->current_users = count_current_connections(net_name, false);
346 r->path = path ? path : "";
347 r->password = "";
350 /*******************************************************************
351 Map any generic bits to file specific bits.
352 ********************************************************************/
354 static void map_generic_share_sd_bits(struct security_descriptor *psd)
356 int i;
357 struct security_acl *ps_dacl = NULL;
359 if (!psd)
360 return;
362 ps_dacl = psd->dacl;
363 if (!ps_dacl)
364 return;
366 for (i = 0; i < ps_dacl->num_aces; i++) {
367 struct security_ace *psa = &ps_dacl->aces[i];
368 uint32 orig_mask = psa->access_mask;
370 se_map_generic(&psa->access_mask, &file_generic_mapping);
371 psa->access_mask |= orig_mask;
375 /*******************************************************************
376 Fill in a share info level 501 structure.
377 ********************************************************************/
379 static void init_srv_share_info_501(struct pipes_struct *p,
380 struct srvsvc_NetShareInfo501 *r, int snum)
382 const char *net_name = lp_servicename(talloc_tos(), snum);
383 char *remark = lp_comment(p->mem_ctx, snum);
385 if (remark) {
386 remark = talloc_sub_advanced(
387 p->mem_ctx, lp_servicename(talloc_tos(), snum),
388 get_current_username(), lp_pathname(talloc_tos(), snum),
389 p->session_info->unix_token->uid, get_current_username(),
390 "", remark);
393 r->name = net_name;
394 r->type = get_share_type(snum);
395 r->comment = remark ? remark : "";
396 r->csc_policy = (lp_csc_policy(snum) << 4);
399 /*******************************************************************
400 Fill in a share info level 502 structure.
401 ********************************************************************/
403 static void init_srv_share_info_502(struct pipes_struct *p,
404 struct srvsvc_NetShareInfo502 *r, int snum)
406 const char *net_name = lp_servicename(talloc_tos(), snum);
407 char *path = NULL;
408 struct security_descriptor *sd = NULL;
409 struct sec_desc_buf *sd_buf = NULL;
410 size_t sd_size = 0;
411 TALLOC_CTX *ctx = p->mem_ctx;
412 char *remark = lp_comment(ctx, snum);
414 if (remark) {
415 remark = talloc_sub_advanced(
416 p->mem_ctx, lp_servicename(talloc_tos(), snum),
417 get_current_username(), lp_pathname(talloc_tos(), snum),
418 p->session_info->unix_token->uid, get_current_username(),
419 "", remark);
421 path = talloc_asprintf(ctx, "C:%s", lp_pathname(talloc_tos(), snum));
422 if (path) {
424 * Change / to \\ so that win2k will see it as a valid path. This was added to
425 * enable use of browsing in win2k add share dialog.
427 string_replace(path, '/', '\\');
430 sd = get_share_security(ctx, lp_servicename(talloc_tos(), snum), &sd_size);
432 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
434 r->name = net_name;
435 r->type = get_share_type(snum);
436 r->comment = remark ? remark : "";
437 r->permissions = 0;
438 r->max_users = (uint32_t)-1;
439 r->current_users = 1; /* ??? */
440 r->path = path ? path : "";
441 r->password = "";
442 r->sd_buf = *sd_buf;
445 /***************************************************************************
446 Fill in a share info level 1004 structure.
447 ***************************************************************************/
449 static void init_srv_share_info_1004(struct pipes_struct *p,
450 struct srvsvc_NetShareInfo1004 *r,
451 int snum)
453 char *remark = lp_comment(p->mem_ctx, snum);
455 if (remark) {
456 remark = talloc_sub_advanced(
457 p->mem_ctx, lp_servicename(talloc_tos(), snum),
458 get_current_username(), lp_pathname(talloc_tos(), snum),
459 p->session_info->unix_token->uid, get_current_username(),
460 "", remark);
463 r->comment = remark ? remark : "";
466 /***************************************************************************
467 Fill in a share info level 1005 structure.
468 ***************************************************************************/
470 static void init_srv_share_info_1005(struct pipes_struct *p,
471 struct srvsvc_NetShareInfo1005 *r,
472 int snum)
474 uint32_t dfs_flags = 0;
476 if (lp_host_msdfs() && lp_msdfs_root(snum)) {
477 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
480 dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
482 r->dfs_flags = dfs_flags;
485 /***************************************************************************
486 Fill in a share info level 1006 structure.
487 ***************************************************************************/
489 static void init_srv_share_info_1006(struct pipes_struct *p,
490 struct srvsvc_NetShareInfo1006 *r,
491 int snum)
493 r->max_users = (uint32_t)-1;
496 /***************************************************************************
497 Fill in a share info level 1007 structure.
498 ***************************************************************************/
500 static void init_srv_share_info_1007(struct pipes_struct *p,
501 struct srvsvc_NetShareInfo1007 *r,
502 int snum)
504 r->flags = 0;
505 r->alternate_directory_name = "";
508 /*******************************************************************
509 Fill in a share info level 1501 structure.
510 ********************************************************************/
512 static void init_srv_share_info_1501(struct pipes_struct *p,
513 struct sec_desc_buf **r,
514 int snum)
516 struct security_descriptor *sd;
517 struct sec_desc_buf *sd_buf = NULL;
518 size_t sd_size;
519 TALLOC_CTX *ctx = p->mem_ctx;
521 sd = get_share_security(ctx, lp_servicename(talloc_tos(), snum), &sd_size);
522 if (sd) {
523 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
526 *r = sd_buf;
529 /*******************************************************************
530 True if it ends in '$'.
531 ********************************************************************/
533 static bool is_hidden_share(int snum)
535 const char *net_name = lp_servicename(talloc_tos(), snum);
537 return (net_name[strlen(net_name) - 1] == '$') ? True : False;
540 /*******************************************************************
541 Verify user is allowed to view share, access based enumeration
542 ********************************************************************/
543 static bool is_enumeration_allowed(struct pipes_struct *p,
544 int snum)
546 if (!lp_access_based_share_enum(snum))
547 return true;
549 return share_access_check(p->session_info->security_token,
550 lp_servicename(talloc_tos(), snum),
551 FILE_READ_DATA, NULL);
554 /*******************************************************************
555 Fill in a share info structure.
556 ********************************************************************/
558 static WERROR init_srv_share_info_ctr(struct pipes_struct *p,
559 struct srvsvc_NetShareInfoCtr *info_ctr,
560 uint32_t *resume_handle_p,
561 uint32_t *total_entries,
562 bool all_shares)
564 int num_entries = 0;
565 int alloc_entries = 0;
566 int num_services = 0;
567 int snum;
568 TALLOC_CTX *ctx = p->mem_ctx;
569 int i = 0;
570 int valid_share_count = 0;
571 bool *allowed = 0;
572 union srvsvc_NetShareCtr ctr;
573 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
575 DEBUG(5,("init_srv_share_info_ctr\n"));
577 /* Ensure all the usershares are loaded. */
578 become_root();
579 load_usershare_shares(NULL, connections_snum_used);
580 load_registry_shares();
581 num_services = lp_numservices();
582 unbecome_root();
584 allowed = talloc_zero_array(ctx, bool, num_services);
585 W_ERROR_HAVE_NO_MEMORY(allowed);
587 /* Count the number of entries. */
588 for (snum = 0; snum < num_services; snum++) {
589 if (lp_browseable(snum) && lp_snum_ok(snum) &&
590 is_enumeration_allowed(p, snum) &&
591 (all_shares || !is_hidden_share(snum)) ) {
592 DEBUG(10, ("counting service %s\n",
593 lp_servicename(talloc_tos(), snum) ? lp_servicename(talloc_tos(), snum) : "(null)"));
594 allowed[snum] = true;
595 num_entries++;
596 } else {
597 DEBUG(10, ("NOT counting service %s\n",
598 lp_servicename(talloc_tos(), snum) ? lp_servicename(talloc_tos(), snum) : "(null)"));
602 if (!num_entries || (resume_handle >= num_entries)) {
603 return WERR_OK;
606 /* Calculate alloc entries. */
607 alloc_entries = num_entries - resume_handle;
608 switch (info_ctr->level) {
609 case 0:
610 ctr.ctr0 = talloc_zero(ctx, struct srvsvc_NetShareCtr0);
611 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
613 ctr.ctr0->count = alloc_entries;
614 ctr.ctr0->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
615 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
617 for (snum = 0; snum < num_services; snum++) {
618 if (allowed[snum] &&
619 (resume_handle <= (i + valid_share_count++)) ) {
620 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
624 break;
626 case 1:
627 ctr.ctr1 = talloc_zero(ctx, struct srvsvc_NetShareCtr1);
628 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
630 ctr.ctr1->count = alloc_entries;
631 ctr.ctr1->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
632 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
634 for (snum = 0; snum < num_services; snum++) {
635 if (allowed[snum] &&
636 (resume_handle <= (i + valid_share_count++)) ) {
637 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
641 break;
643 case 2:
644 ctr.ctr2 = talloc_zero(ctx, struct srvsvc_NetShareCtr2);
645 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
647 ctr.ctr2->count = alloc_entries;
648 ctr.ctr2->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
649 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
651 for (snum = 0; snum < num_services; snum++) {
652 if (allowed[snum] &&
653 (resume_handle <= (i + valid_share_count++)) ) {
654 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
658 break;
660 case 501:
661 ctr.ctr501 = talloc_zero(ctx, struct srvsvc_NetShareCtr501);
662 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
664 ctr.ctr501->count = alloc_entries;
665 ctr.ctr501->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
666 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
668 for (snum = 0; snum < num_services; snum++) {
669 if (allowed[snum] &&
670 (resume_handle <= (i + valid_share_count++)) ) {
671 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
675 break;
677 case 502:
678 ctr.ctr502 = talloc_zero(ctx, struct srvsvc_NetShareCtr502);
679 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
681 ctr.ctr502->count = alloc_entries;
682 ctr.ctr502->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
683 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
685 for (snum = 0; snum < num_services; snum++) {
686 if (allowed[snum] &&
687 (resume_handle <= (i + valid_share_count++)) ) {
688 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
692 break;
694 case 1004:
695 ctr.ctr1004 = talloc_zero(ctx, struct srvsvc_NetShareCtr1004);
696 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
698 ctr.ctr1004->count = alloc_entries;
699 ctr.ctr1004->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
700 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
702 for (snum = 0; snum < num_services; snum++) {
703 if (allowed[snum] &&
704 (resume_handle <= (i + valid_share_count++)) ) {
705 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
709 break;
711 case 1005:
712 ctr.ctr1005 = talloc_zero(ctx, struct srvsvc_NetShareCtr1005);
713 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
715 ctr.ctr1005->count = alloc_entries;
716 ctr.ctr1005->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
717 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
719 for (snum = 0; snum < num_services; snum++) {
720 if (allowed[snum] &&
721 (resume_handle <= (i + valid_share_count++)) ) {
722 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
726 break;
728 case 1006:
729 ctr.ctr1006 = talloc_zero(ctx, struct srvsvc_NetShareCtr1006);
730 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
732 ctr.ctr1006->count = alloc_entries;
733 ctr.ctr1006->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
734 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
736 for (snum = 0; snum < num_services; snum++) {
737 if (allowed[snum] &&
738 (resume_handle <= (i + valid_share_count++)) ) {
739 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
743 break;
745 case 1007:
746 ctr.ctr1007 = talloc_zero(ctx, struct srvsvc_NetShareCtr1007);
747 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
749 ctr.ctr1007->count = alloc_entries;
750 ctr.ctr1007->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
751 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
753 for (snum = 0; snum < num_services; snum++) {
754 if (allowed[snum] &&
755 (resume_handle <= (i + valid_share_count++)) ) {
756 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
760 break;
762 case 1501:
763 ctr.ctr1501 = talloc_zero(ctx, struct srvsvc_NetShareCtr1501);
764 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
766 ctr.ctr1501->count = alloc_entries;
767 ctr.ctr1501->array = talloc_zero_array(ctx, struct sec_desc_buf, alloc_entries);
768 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
770 for (snum = 0; snum < num_services; snum++) {
771 if (allowed[snum] &&
772 (resume_handle <= (i + valid_share_count++)) ) {
773 struct sec_desc_buf *sd_buf = NULL;
774 init_srv_share_info_1501(p, &sd_buf, snum);
775 ctr.ctr1501->array[i++] = *sd_buf;
779 break;
781 default:
782 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
783 info_ctr->level));
784 return WERR_UNKNOWN_LEVEL;
787 *total_entries = alloc_entries;
788 if (resume_handle_p) {
789 if (all_shares) {
790 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
791 } else {
792 *resume_handle_p = num_entries;
796 info_ctr->ctr = ctr;
798 return WERR_OK;
801 /*******************************************************************
802 fill in a sess info level 0 structure.
803 ********************************************************************/
805 static WERROR init_srv_sess_info_0(struct pipes_struct *p,
806 struct srvsvc_NetSessCtr0 *ctr0,
807 uint32_t *resume_handle_p,
808 uint32_t *total_entries)
810 struct sessionid *session_list;
811 uint32_t num_entries = 0;
812 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
813 *total_entries = list_sessions(p->mem_ctx, &session_list);
815 DEBUG(5,("init_srv_sess_info_0\n"));
817 if (ctr0 == NULL) {
818 if (resume_handle_p) {
819 *resume_handle_p = 0;
821 return WERR_OK;
824 for (; resume_handle < *total_entries; resume_handle++) {
826 ctr0->array = talloc_realloc(p->mem_ctx,
827 ctr0->array,
828 struct srvsvc_NetSessInfo0,
829 num_entries+1);
830 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
832 ctr0->array[num_entries].client =
833 session_list[resume_handle].remote_machine;
835 num_entries++;
838 ctr0->count = num_entries;
840 if (resume_handle_p) {
841 if (*resume_handle_p >= *total_entries) {
842 *resume_handle_p = 0;
843 } else {
844 *resume_handle_p = resume_handle;
848 return WERR_OK;
851 /*******************************************************************
852 ********************************************************************/
854 static void sess_file_fn( const struct share_mode_entry *e,
855 const char *sharepath, const char *fname,
856 void *data )
858 struct sess_file_count *sess = (struct sess_file_count *)data;
860 if (serverid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid)) {
861 sess->count++;
864 return;
867 /*******************************************************************
868 ********************************************************************/
870 static int net_count_files( uid_t uid, struct server_id pid )
872 struct sess_file_count s_file_cnt;
874 s_file_cnt.count = 0;
875 s_file_cnt.uid = uid;
876 s_file_cnt.pid = pid;
878 share_mode_forall( sess_file_fn, &s_file_cnt );
880 return s_file_cnt.count;
883 /*******************************************************************
884 fill in a sess info level 1 structure.
885 ********************************************************************/
887 static WERROR init_srv_sess_info_1(struct pipes_struct *p,
888 struct srvsvc_NetSessCtr1 *ctr1,
889 uint32_t *resume_handle_p,
890 uint32_t *total_entries)
892 struct sessionid *session_list;
893 uint32_t num_entries = 0;
894 time_t now = time(NULL);
895 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
897 ZERO_STRUCTP(ctr1);
899 if (ctr1 == NULL) {
900 if (resume_handle_p) {
901 *resume_handle_p = 0;
903 return WERR_OK;
906 *total_entries = list_sessions(p->mem_ctx, &session_list);
908 for (; resume_handle < *total_entries; resume_handle++) {
909 uint32 num_files;
910 uint32 connect_time;
911 struct passwd *pw = getpwnam(session_list[resume_handle].username);
912 bool guest;
914 if ( !pw ) {
915 DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
916 session_list[resume_handle].username));
917 continue;
920 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
921 num_files = net_count_files(pw->pw_uid, session_list[resume_handle].pid);
922 guest = strequal( session_list[resume_handle].username, lp_guestaccount() );
924 ctr1->array = talloc_realloc(p->mem_ctx,
925 ctr1->array,
926 struct srvsvc_NetSessInfo1,
927 num_entries+1);
928 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
930 ctr1->array[num_entries].client = session_list[resume_handle].remote_machine;
931 ctr1->array[num_entries].user = session_list[resume_handle].username;
932 ctr1->array[num_entries].num_open = num_files;
933 ctr1->array[num_entries].time = connect_time;
934 ctr1->array[num_entries].idle_time = 0;
935 ctr1->array[num_entries].user_flags = guest;
937 num_entries++;
940 ctr1->count = num_entries;
942 if (resume_handle_p) {
943 if (*resume_handle_p >= *total_entries) {
944 *resume_handle_p = 0;
945 } else {
946 *resume_handle_p = resume_handle;
950 return WERR_OK;
953 /*******************************************************************
954 fill in a conn info level 0 structure.
955 ********************************************************************/
957 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
958 uint32_t *resume_handle_p,
959 uint32_t *total_entries)
961 uint32_t num_entries = 0;
962 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
964 DEBUG(5,("init_srv_conn_info_0\n"));
966 if (ctr0 == NULL) {
967 if (resume_handle_p) {
968 *resume_handle_p = 0;
970 return WERR_OK;
973 *total_entries = 1;
975 ZERO_STRUCTP(ctr0);
977 for (; resume_handle < *total_entries; resume_handle++) {
979 ctr0->array = talloc_realloc(talloc_tos(),
980 ctr0->array,
981 struct srvsvc_NetConnInfo0,
982 num_entries+1);
983 if (!ctr0->array) {
984 return WERR_NOMEM;
987 ctr0->array[num_entries].conn_id = *total_entries;
989 /* move on to creating next connection */
990 num_entries++;
993 ctr0->count = num_entries;
994 *total_entries = num_entries;
996 if (resume_handle_p) {
997 if (*resume_handle_p >= *total_entries) {
998 *resume_handle_p = 0;
999 } else {
1000 *resume_handle_p = resume_handle;
1004 return WERR_OK;
1007 /*******************************************************************
1008 fill in a conn info level 1 structure.
1009 ********************************************************************/
1011 static WERROR init_srv_conn_info_1(struct srvsvc_NetConnCtr1 *ctr1,
1012 uint32_t *resume_handle_p,
1013 uint32_t *total_entries)
1015 uint32_t num_entries = 0;
1016 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
1018 DEBUG(5,("init_srv_conn_info_1\n"));
1020 if (ctr1 == NULL) {
1021 if (resume_handle_p) {
1022 *resume_handle_p = 0;
1024 return WERR_OK;
1027 *total_entries = 1;
1029 ZERO_STRUCTP(ctr1);
1031 for (; resume_handle < *total_entries; resume_handle++) {
1033 ctr1->array = talloc_realloc(talloc_tos(),
1034 ctr1->array,
1035 struct srvsvc_NetConnInfo1,
1036 num_entries+1);
1037 if (!ctr1->array) {
1038 return WERR_NOMEM;
1041 ctr1->array[num_entries].conn_id = *total_entries;
1042 ctr1->array[num_entries].conn_type = 0x3;
1043 ctr1->array[num_entries].num_open = 1;
1044 ctr1->array[num_entries].num_users = 1;
1045 ctr1->array[num_entries].conn_time = 3;
1046 ctr1->array[num_entries].user = "dummy_user";
1047 ctr1->array[num_entries].share = "IPC$";
1049 /* move on to creating next connection */
1050 num_entries++;
1053 ctr1->count = num_entries;
1054 *total_entries = num_entries;
1056 if (resume_handle_p) {
1057 if (*resume_handle_p >= *total_entries) {
1058 *resume_handle_p = 0;
1059 } else {
1060 *resume_handle_p = resume_handle;
1064 return WERR_OK;
1067 /*******************************************************************
1068 _srvsvc_NetFileEnum
1069 *******************************************************************/
1071 WERROR _srvsvc_NetFileEnum(struct pipes_struct *p,
1072 struct srvsvc_NetFileEnum *r)
1074 TALLOC_CTX *ctx = NULL;
1075 struct srvsvc_NetFileCtr3 *ctr3;
1076 uint32_t resume_hnd = 0;
1077 WERROR werr;
1079 switch (r->in.info_ctr->level) {
1080 case 3:
1081 break;
1082 default:
1083 return WERR_UNKNOWN_LEVEL;
1086 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1087 p->session_info->security_token)) {
1088 DEBUG(1, ("Enumerating files only allowed for "
1089 "administrators\n"));
1090 return WERR_ACCESS_DENIED;
1093 ctx = talloc_tos();
1094 ctr3 = r->in.info_ctr->ctr.ctr3;
1095 if (!ctr3) {
1096 werr = WERR_INVALID_PARAM;
1097 goto done;
1100 /* TODO -- Windows enumerates
1101 (b) active pipes
1102 (c) open directories and files */
1104 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1105 if (!W_ERROR_IS_OK(werr)) {
1106 goto done;
1109 werr = net_enum_pipes(ctx, r->in.user, &ctr3, resume_hnd);
1110 if (!W_ERROR_IS_OK(werr)) {
1111 goto done;
1114 *r->out.totalentries = ctr3->count;
1115 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1116 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1118 werr = WERR_OK;
1120 done:
1121 return werr;
1124 /*******************************************************************
1125 _srvsvc_NetSrvGetInfo
1126 ********************************************************************/
1128 WERROR _srvsvc_NetSrvGetInfo(struct pipes_struct *p,
1129 struct srvsvc_NetSrvGetInfo *r)
1131 WERROR status = WERR_OK;
1133 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1135 if (!pipe_access_check(p)) {
1136 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1137 return WERR_ACCESS_DENIED;
1140 switch (r->in.level) {
1142 /* Technically level 102 should only be available to
1143 Administrators but there isn't anything super-secret
1144 here, as most of it is made up. */
1146 case 102: {
1147 struct srvsvc_NetSrvInfo102 *info102;
1149 info102 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1150 if (!info102) {
1151 return WERR_NOMEM;
1154 info102->platform_id = PLATFORM_ID_NT;
1155 info102->server_name = lp_netbios_name();
1156 info102->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1157 info102->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1158 info102->server_type = lp_default_server_announce();
1159 info102->comment = string_truncate(lp_serverstring(talloc_tos()),
1160 MAX_SERVER_STRING_LENGTH);
1161 info102->users = 0xffffffff;
1162 info102->disc = 0xf;
1163 info102->hidden = 0;
1164 info102->announce = 240;
1165 info102->anndelta = 3000;
1166 info102->licenses = 100000;
1167 info102->userpath = "C:\\";
1169 r->out.info->info102 = info102;
1170 break;
1172 case 101: {
1173 struct srvsvc_NetSrvInfo101 *info101;
1175 info101 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1176 if (!info101) {
1177 return WERR_NOMEM;
1180 info101->platform_id = PLATFORM_ID_NT;
1181 info101->server_name = lp_netbios_name();
1182 info101->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1183 info101->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1184 info101->server_type = lp_default_server_announce();
1185 info101->comment = string_truncate(lp_serverstring(talloc_tos()),
1186 MAX_SERVER_STRING_LENGTH);
1188 r->out.info->info101 = info101;
1189 break;
1191 case 100: {
1192 struct srvsvc_NetSrvInfo100 *info100;
1194 info100 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1195 if (!info100) {
1196 return WERR_NOMEM;
1199 info100->platform_id = PLATFORM_ID_NT;
1200 info100->server_name = lp_netbios_name();
1202 r->out.info->info100 = info100;
1204 break;
1206 default:
1207 status = WERR_UNKNOWN_LEVEL;
1208 break;
1211 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1213 return status;
1216 /*******************************************************************
1217 _srvsvc_NetSrvSetInfo
1218 ********************************************************************/
1220 WERROR _srvsvc_NetSrvSetInfo(struct pipes_struct *p,
1221 struct srvsvc_NetSrvSetInfo *r)
1223 WERROR status = WERR_OK;
1225 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1227 /* Set up the net server set info structure. */
1229 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1231 return status;
1234 /*******************************************************************
1235 _srvsvc_NetConnEnum
1236 ********************************************************************/
1238 WERROR _srvsvc_NetConnEnum(struct pipes_struct *p,
1239 struct srvsvc_NetConnEnum *r)
1241 WERROR werr;
1243 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1245 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1246 p->session_info->security_token)) {
1247 DEBUG(1, ("Enumerating connections only allowed for "
1248 "administrators\n"));
1249 return WERR_ACCESS_DENIED;
1252 switch (r->in.info_ctr->level) {
1253 case 0:
1254 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1255 r->in.resume_handle,
1256 r->out.totalentries);
1257 break;
1258 case 1:
1259 werr = init_srv_conn_info_1(r->in.info_ctr->ctr.ctr1,
1260 r->in.resume_handle,
1261 r->out.totalentries);
1262 break;
1263 default:
1264 return WERR_UNKNOWN_LEVEL;
1267 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1269 return werr;
1272 /*******************************************************************
1273 _srvsvc_NetSessEnum
1274 ********************************************************************/
1276 WERROR _srvsvc_NetSessEnum(struct pipes_struct *p,
1277 struct srvsvc_NetSessEnum *r)
1279 WERROR werr;
1281 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1283 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1284 p->session_info->security_token)) {
1285 DEBUG(1, ("Enumerating sessions only allowed for "
1286 "administrators\n"));
1287 return WERR_ACCESS_DENIED;
1290 switch (r->in.info_ctr->level) {
1291 case 0:
1292 werr = init_srv_sess_info_0(p,
1293 r->in.info_ctr->ctr.ctr0,
1294 r->in.resume_handle,
1295 r->out.totalentries);
1296 break;
1297 case 1:
1298 werr = init_srv_sess_info_1(p,
1299 r->in.info_ctr->ctr.ctr1,
1300 r->in.resume_handle,
1301 r->out.totalentries);
1302 break;
1303 default:
1304 return WERR_UNKNOWN_LEVEL;
1307 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1309 return werr;
1312 /*******************************************************************
1313 _srvsvc_NetSessDel
1314 ********************************************************************/
1316 WERROR _srvsvc_NetSessDel(struct pipes_struct *p,
1317 struct srvsvc_NetSessDel *r)
1319 struct sessionid *session_list;
1320 int num_sessions, snum;
1321 const char *username;
1322 const char *machine;
1323 bool not_root = False;
1324 WERROR werr;
1326 username = r->in.user;
1327 machine = r->in.client;
1329 /* strip leading backslashes if any */
1330 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1331 machine += 2;
1334 num_sessions = list_sessions(p->mem_ctx, &session_list);
1336 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1338 werr = WERR_ACCESS_DENIED;
1340 /* fail out now if you are not root or not a domain admin */
1342 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1343 ( ! nt_token_check_domain_rid(p->session_info->security_token,
1344 DOMAIN_RID_ADMINS))) {
1346 goto done;
1349 for (snum = 0; snum < num_sessions; snum++) {
1351 if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
1352 strequal(session_list[snum].remote_machine, machine)) {
1354 NTSTATUS ntstat;
1356 if (p->session_info->unix_token->uid != sec_initial_uid()) {
1357 not_root = True;
1358 become_root();
1361 ntstat = messaging_send(p->msg_ctx,
1362 session_list[snum].pid,
1363 MSG_SHUTDOWN, &data_blob_null);
1365 if (NT_STATUS_IS_OK(ntstat))
1366 werr = WERR_OK;
1368 if (not_root)
1369 unbecome_root();
1373 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1375 done:
1377 return werr;
1380 /*******************************************************************
1381 _srvsvc_NetShareEnumAll
1382 ********************************************************************/
1384 WERROR _srvsvc_NetShareEnumAll(struct pipes_struct *p,
1385 struct srvsvc_NetShareEnumAll *r)
1387 WERROR werr;
1389 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1391 if (!pipe_access_check(p)) {
1392 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1393 return WERR_ACCESS_DENIED;
1396 /* Create the list of shares for the response. */
1397 werr = init_srv_share_info_ctr(p,
1398 r->in.info_ctr,
1399 r->in.resume_handle,
1400 r->out.totalentries,
1401 true);
1403 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1405 return werr;
1408 /*******************************************************************
1409 _srvsvc_NetShareEnum
1410 ********************************************************************/
1412 WERROR _srvsvc_NetShareEnum(struct pipes_struct *p,
1413 struct srvsvc_NetShareEnum *r)
1415 WERROR werr;
1417 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1419 if (!pipe_access_check(p)) {
1420 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\n"));
1421 return WERR_ACCESS_DENIED;
1424 /* Create the list of shares for the response. */
1425 werr = init_srv_share_info_ctr(p,
1426 r->in.info_ctr,
1427 r->in.resume_handle,
1428 r->out.totalentries,
1429 false);
1431 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1433 return werr;
1436 /*******************************************************************
1437 _srvsvc_NetShareGetInfo
1438 ********************************************************************/
1440 WERROR _srvsvc_NetShareGetInfo(struct pipes_struct *p,
1441 struct srvsvc_NetShareGetInfo *r)
1443 WERROR status = WERR_OK;
1444 char *share_name = NULL;
1445 int snum;
1446 union srvsvc_NetShareInfo *info = r->out.info;
1448 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1450 if (!r->in.share_name) {
1451 return WERR_INVALID_NAME;
1454 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1455 if (!share_name) {
1456 return WERR_NOMEM;
1458 if (snum < 0) {
1459 return WERR_INVALID_NAME;
1462 switch (r->in.level) {
1463 case 0:
1464 info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1465 W_ERROR_HAVE_NO_MEMORY(info->info0);
1466 init_srv_share_info_0(p, info->info0, snum);
1467 break;
1468 case 1:
1469 info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1470 W_ERROR_HAVE_NO_MEMORY(info->info1);
1471 init_srv_share_info_1(p, info->info1, snum);
1472 break;
1473 case 2:
1474 info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1475 W_ERROR_HAVE_NO_MEMORY(info->info2);
1476 init_srv_share_info_2(p, info->info2, snum);
1477 break;
1478 case 501:
1479 info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1480 W_ERROR_HAVE_NO_MEMORY(info->info501);
1481 init_srv_share_info_501(p, info->info501, snum);
1482 break;
1483 case 502:
1484 info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1485 W_ERROR_HAVE_NO_MEMORY(info->info502);
1486 init_srv_share_info_502(p, info->info502, snum);
1487 break;
1488 case 1004:
1489 info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1490 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1491 init_srv_share_info_1004(p, info->info1004, snum);
1492 break;
1493 case 1005:
1494 info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1495 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1496 init_srv_share_info_1005(p, info->info1005, snum);
1497 break;
1498 case 1006:
1499 info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1500 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1501 init_srv_share_info_1006(p, info->info1006, snum);
1502 break;
1503 case 1007:
1504 info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1505 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1506 init_srv_share_info_1007(p, info->info1007, snum);
1507 break;
1508 case 1501:
1509 init_srv_share_info_1501(p, &info->info1501, snum);
1510 break;
1511 default:
1512 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1513 r->in.level));
1514 status = WERR_UNKNOWN_LEVEL;
1515 break;
1518 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1520 return status;
1523 /*******************************************************************
1524 _srvsvc_NetShareSetInfo. Modify share details.
1525 ********************************************************************/
1527 WERROR _srvsvc_NetShareSetInfo(struct pipes_struct *p,
1528 struct srvsvc_NetShareSetInfo *r)
1530 char *command = NULL;
1531 char *share_name = NULL;
1532 char *comment = NULL;
1533 const char *pathname = NULL;
1534 int type;
1535 int snum;
1536 int ret;
1537 char *path = NULL;
1538 struct security_descriptor *psd = NULL;
1539 bool is_disk_op = False;
1540 int max_connections = 0;
1541 TALLOC_CTX *ctx = p->mem_ctx;
1542 union srvsvc_NetShareInfo *info = r->in.info;
1544 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1546 if (!r->in.share_name) {
1547 return WERR_INVALID_NAME;
1550 if (r->out.parm_error) {
1551 *r->out.parm_error = 0;
1554 if ( strequal(r->in.share_name,"IPC$")
1555 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1556 || strequal(r->in.share_name,"global") )
1558 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s cannot be "
1559 "modified by a remote user.\n",
1560 r->in.share_name ));
1561 return WERR_ACCESS_DENIED;
1564 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1565 if (!share_name) {
1566 return WERR_NOMEM;
1569 /* Does this share exist ? */
1570 if (snum < 0)
1571 return WERR_NET_NAME_NOT_FOUND;
1573 /* No change to printer shares. */
1574 if (lp_print_ok(snum))
1575 return WERR_ACCESS_DENIED;
1577 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1579 /* fail out now if you are not root and not a disk op */
1581 if ( p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op ) {
1582 DEBUG(2,("_srvsvc_NetShareSetInfo: uid %u doesn't have the "
1583 "SeDiskOperatorPrivilege privilege needed to modify "
1584 "share %s\n",
1585 (unsigned int)p->session_info->unix_token->uid,
1586 share_name ));
1587 return WERR_ACCESS_DENIED;
1590 switch (r->in.level) {
1591 case 1:
1592 pathname = lp_pathname(ctx, snum);
1593 comment = talloc_strdup(ctx, info->info1->comment);
1594 type = info->info1->type;
1595 psd = NULL;
1596 break;
1597 case 2:
1598 comment = talloc_strdup(ctx, info->info2->comment);
1599 pathname = info->info2->path;
1600 type = info->info2->type;
1601 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1602 0 : info->info2->max_users;
1603 psd = NULL;
1604 break;
1605 #if 0
1606 /* not supported on set but here for completeness */
1607 case 501:
1608 comment = talloc_strdup(ctx, info->info501->comment);
1609 type = info->info501->type;
1610 psd = NULL;
1611 break;
1612 #endif
1613 case 502:
1614 comment = talloc_strdup(ctx, info->info502->comment);
1615 pathname = info->info502->path;
1616 type = info->info502->type;
1617 psd = info->info502->sd_buf.sd;
1618 map_generic_share_sd_bits(psd);
1619 break;
1620 case 1004:
1621 pathname = lp_pathname(ctx, snum);
1622 comment = talloc_strdup(ctx, info->info1004->comment);
1623 type = STYPE_DISKTREE;
1624 break;
1625 case 1005:
1626 /* XP re-sets the csc policy even if it wasn't changed by the
1627 user, so we must compare it to see if it's what is set in
1628 smb.conf, so that we can contine other ops like setting
1629 ACLs on a share */
1630 if (((info->info1005->dfs_flags &
1631 SHARE_1005_CSC_POLICY_MASK) >>
1632 SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1633 return WERR_OK;
1634 else {
1635 DEBUG(3, ("_srvsvc_NetShareSetInfo: client is trying to change csc policy from the network; must be done with smb.conf\n"));
1636 return WERR_ACCESS_DENIED;
1638 case 1006:
1639 case 1007:
1640 return WERR_ACCESS_DENIED;
1641 case 1501:
1642 pathname = lp_pathname(ctx, snum);
1643 comment = lp_comment(ctx, snum);
1644 psd = info->info1501->sd;
1645 map_generic_share_sd_bits(psd);
1646 type = STYPE_DISKTREE;
1647 break;
1648 default:
1649 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1650 r->in.level));
1651 return WERR_UNKNOWN_LEVEL;
1654 /* We can only modify disk shares. */
1655 if (type != STYPE_DISKTREE) {
1656 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s is not a "
1657 "disk share\n",
1658 share_name ));
1659 return WERR_ACCESS_DENIED;
1662 if (comment == NULL) {
1663 return WERR_NOMEM;
1666 /* Check if the pathname is valid. */
1667 if (!(path = valid_share_pathname(p->mem_ctx, pathname ))) {
1668 DEBUG(5,("_srvsvc_NetShareSetInfo: invalid pathname %s\n",
1669 pathname ));
1670 return WERR_OBJECT_PATH_INVALID;
1673 /* Ensure share name, pathname and comment don't contain '"' characters. */
1674 string_replace(share_name, '"', ' ');
1675 string_replace(path, '"', ' ');
1676 string_replace(comment, '"', ' ');
1678 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1679 lp_change_share_cmd(talloc_tos()) ? lp_change_share_cmd(talloc_tos()) : "NULL" ));
1681 /* Only call modify function if something changed. */
1683 if (strcmp(path, lp_pathname(talloc_tos(), snum)) || strcmp(comment, lp_comment(talloc_tos(), snum))
1684 || (lp_max_connections(snum) != max_connections)) {
1685 if (!lp_change_share_cmd(talloc_tos()) || !*lp_change_share_cmd(talloc_tos())) {
1686 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1687 return WERR_ACCESS_DENIED;
1690 command = talloc_asprintf(p->mem_ctx,
1691 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1692 lp_change_share_cmd(talloc_tos()),
1693 get_dyn_CONFIGFILE(),
1694 share_name,
1695 path,
1696 comment ? comment : "",
1697 max_connections);
1698 if (!command) {
1699 return WERR_NOMEM;
1702 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1704 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1706 if (is_disk_op)
1707 become_root();
1709 if ( (ret = smbrun(command, NULL)) == 0 ) {
1710 /* Tell everyone we updated smb.conf. */
1711 message_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED,
1712 NULL, 0, NULL);
1715 if ( is_disk_op )
1716 unbecome_root();
1718 /********* END SeDiskOperatorPrivilege BLOCK *********/
1720 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1721 command, ret ));
1723 TALLOC_FREE(command);
1725 if ( ret != 0 )
1726 return WERR_ACCESS_DENIED;
1727 } else {
1728 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1729 share_name ));
1732 /* Replace SD if changed. */
1733 if (psd) {
1734 struct security_descriptor *old_sd;
1735 size_t sd_size;
1737 old_sd = get_share_security(p->mem_ctx, lp_servicename(talloc_tos(), snum), &sd_size);
1739 if (old_sd && !security_descriptor_equal(old_sd, psd)) {
1740 if (!set_share_security(share_name, psd))
1741 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1742 share_name ));
1746 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1748 return WERR_OK;
1751 /*******************************************************************
1752 _srvsvc_NetShareAdd.
1753 Call 'add_share_command "sharename" "pathname"
1754 "comment" "max connections = "
1755 ********************************************************************/
1757 WERROR _srvsvc_NetShareAdd(struct pipes_struct *p,
1758 struct srvsvc_NetShareAdd *r)
1760 char *command = NULL;
1761 char *share_name_in = NULL;
1762 char *share_name = NULL;
1763 char *comment = NULL;
1764 char *pathname = NULL;
1765 int type;
1766 int snum;
1767 int ret;
1768 char *path;
1769 struct security_descriptor *psd = NULL;
1770 bool is_disk_op;
1771 int max_connections = 0;
1772 TALLOC_CTX *ctx = p->mem_ctx;
1774 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1776 if (r->out.parm_error) {
1777 *r->out.parm_error = 0;
1780 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1782 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op )
1783 return WERR_ACCESS_DENIED;
1785 if (!lp_add_share_cmd(talloc_tos()) || !*lp_add_share_cmd(talloc_tos())) {
1786 DEBUG(10,("_srvsvc_NetShareAdd: No add share command\n"));
1787 return WERR_ACCESS_DENIED;
1790 switch (r->in.level) {
1791 case 0:
1792 /* No path. Not enough info in a level 0 to do anything. */
1793 return WERR_ACCESS_DENIED;
1794 case 1:
1795 /* Not enough info in a level 1 to do anything. */
1796 return WERR_ACCESS_DENIED;
1797 case 2:
1798 share_name_in = talloc_strdup(ctx, r->in.info->info2->name);
1799 comment = talloc_strdup(ctx, r->in.info->info2->comment);
1800 pathname = talloc_strdup(ctx, r->in.info->info2->path);
1801 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
1802 0 : r->in.info->info2->max_users;
1803 type = r->in.info->info2->type;
1804 break;
1805 case 501:
1806 /* No path. Not enough info in a level 501 to do anything. */
1807 return WERR_ACCESS_DENIED;
1808 case 502:
1809 share_name_in = talloc_strdup(ctx, r->in.info->info502->name);
1810 comment = talloc_strdup(ctx, r->in.info->info502->comment);
1811 pathname = talloc_strdup(ctx, r->in.info->info502->path);
1812 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
1813 0 : r->in.info->info502->max_users;
1814 type = r->in.info->info502->type;
1815 psd = r->in.info->info502->sd_buf.sd;
1816 map_generic_share_sd_bits(psd);
1817 break;
1819 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
1821 case 1004:
1822 case 1005:
1823 case 1006:
1824 case 1007:
1825 return WERR_ACCESS_DENIED;
1826 case 1501:
1827 /* DFS only level. */
1828 return WERR_ACCESS_DENIED;
1829 default:
1830 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
1831 r->in.level));
1832 return WERR_UNKNOWN_LEVEL;
1835 /* check for invalid share names */
1837 if (!share_name_in || !validate_net_name(share_name_in,
1838 INVALID_SHARENAME_CHARS,
1839 strlen(share_name_in))) {
1840 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
1841 share_name_in ? share_name_in : ""));
1842 return WERR_INVALID_NAME;
1845 if (strequal(share_name_in,"IPC$") || strequal(share_name_in,"global")
1846 || (lp_enable_asu_support() &&
1847 strequal(share_name_in,"ADMIN$"))) {
1848 return WERR_ACCESS_DENIED;
1851 snum = find_service(ctx, share_name_in, &share_name);
1852 if (!share_name) {
1853 return WERR_NOMEM;
1856 /* Share already exists. */
1857 if (snum >= 0) {
1858 return WERR_FILE_EXISTS;
1861 /* We can only add disk shares. */
1862 if (type != STYPE_DISKTREE) {
1863 return WERR_ACCESS_DENIED;
1866 /* Check if the pathname is valid. */
1867 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
1868 return WERR_OBJECT_PATH_INVALID;
1871 /* Ensure share name, pathname and comment don't contain '"' characters. */
1872 string_replace(share_name_in, '"', ' ');
1873 string_replace(share_name, '"', ' ');
1874 string_replace(path, '"', ' ');
1875 if (comment) {
1876 string_replace(comment, '"', ' ');
1879 command = talloc_asprintf(ctx,
1880 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1881 lp_add_share_cmd(talloc_tos()),
1882 get_dyn_CONFIGFILE(),
1883 share_name_in,
1884 path,
1885 comment ? comment : "",
1886 max_connections);
1887 if (!command) {
1888 return WERR_NOMEM;
1891 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
1893 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1895 if ( is_disk_op )
1896 become_root();
1898 /* FIXME: use libnetconf here - gd */
1900 if ( (ret = smbrun(command, NULL)) == 0 ) {
1901 /* Tell everyone we updated smb.conf. */
1902 message_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0,
1903 NULL);
1906 if ( is_disk_op )
1907 unbecome_root();
1909 /********* END SeDiskOperatorPrivilege BLOCK *********/
1911 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
1912 command, ret ));
1914 TALLOC_FREE(command);
1916 if ( ret != 0 )
1917 return WERR_ACCESS_DENIED;
1919 if (psd) {
1920 /* Note we use share_name here, not share_name_in as
1921 we need a canonicalized name for setting security. */
1922 if (!set_share_security(share_name, psd)) {
1923 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
1924 share_name ));
1929 * We don't call reload_services() here, the message will
1930 * cause this to be done before the next packet is read
1931 * from the client. JRA.
1934 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1936 return WERR_OK;
1939 /*******************************************************************
1940 _srvsvc_NetShareDel
1941 Call "delete share command" with the share name as
1942 a parameter.
1943 ********************************************************************/
1945 WERROR _srvsvc_NetShareDel(struct pipes_struct *p,
1946 struct srvsvc_NetShareDel *r)
1948 char *command = NULL;
1949 char *share_name = NULL;
1950 int ret;
1951 int snum;
1952 bool is_disk_op;
1953 struct share_params *params;
1954 TALLOC_CTX *ctx = p->mem_ctx;
1956 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
1958 if (!r->in.share_name) {
1959 return WERR_NET_NAME_NOT_FOUND;
1962 if ( strequal(r->in.share_name,"IPC$")
1963 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1964 || strequal(r->in.share_name,"global") )
1966 return WERR_ACCESS_DENIED;
1969 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1970 if (!share_name) {
1971 return WERR_NOMEM;
1974 if (snum < 0) {
1975 return WERR_NO_SUCH_SHARE;
1978 if (!(params = get_share_params(p->mem_ctx, share_name))) {
1979 return WERR_NO_SUCH_SHARE;
1982 /* No change to printer shares. */
1983 if (lp_print_ok(snum))
1984 return WERR_ACCESS_DENIED;
1986 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1988 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op )
1989 return WERR_ACCESS_DENIED;
1991 if (!lp_delete_share_cmd(talloc_tos()) || !*lp_delete_share_cmd(talloc_tos())) {
1992 DEBUG(10,("_srvsvc_NetShareDel: No delete share command\n"));
1993 return WERR_ACCESS_DENIED;
1996 command = talloc_asprintf(ctx,
1997 "%s \"%s\" \"%s\"",
1998 lp_delete_share_cmd(talloc_tos()),
1999 get_dyn_CONFIGFILE(),
2000 lp_servicename(talloc_tos(), snum));
2001 if (!command) {
2002 return WERR_NOMEM;
2005 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
2007 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
2009 if ( is_disk_op )
2010 become_root();
2012 if ( (ret = smbrun(command, NULL)) == 0 ) {
2013 /* Tell everyone we updated smb.conf. */
2014 message_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0,
2015 NULL);
2018 if ( is_disk_op )
2019 unbecome_root();
2021 /********* END SeDiskOperatorPrivilege BLOCK *********/
2023 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
2025 if ( ret != 0 )
2026 return WERR_ACCESS_DENIED;
2028 /* Delete the SD in the database. */
2029 delete_share_security(lp_servicename(talloc_tos(), params->service));
2031 lp_killservice(params->service);
2033 return WERR_OK;
2036 /*******************************************************************
2037 _srvsvc_NetShareDelSticky
2038 ********************************************************************/
2040 WERROR _srvsvc_NetShareDelSticky(struct pipes_struct *p,
2041 struct srvsvc_NetShareDelSticky *r)
2043 struct srvsvc_NetShareDel q;
2045 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
2047 q.in.server_unc = r->in.server_unc;
2048 q.in.share_name = r->in.share_name;
2049 q.in.reserved = r->in.reserved;
2051 return _srvsvc_NetShareDel(p, &q);
2054 /*******************************************************************
2055 _srvsvc_NetRemoteTOD
2056 ********************************************************************/
2058 WERROR _srvsvc_NetRemoteTOD(struct pipes_struct *p,
2059 struct srvsvc_NetRemoteTOD *r)
2061 struct srvsvc_NetRemoteTODInfo *tod;
2062 struct tm *t;
2063 time_t unixdate = time(NULL);
2065 /* We do this call first as if we do it *after* the gmtime call
2066 it overwrites the pointed-to values. JRA */
2068 uint32 zone = get_time_zone(unixdate)/60;
2070 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2072 if ( !(tod = talloc_zero(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
2073 return WERR_NOMEM;
2075 *r->out.info = tod;
2077 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2079 t = gmtime(&unixdate);
2081 /* set up the */
2082 tod->elapsed = unixdate;
2083 tod->msecs = 0;
2084 tod->hours = t->tm_hour;
2085 tod->mins = t->tm_min;
2086 tod->secs = t->tm_sec;
2087 tod->hunds = 0;
2088 tod->timezone = zone;
2089 tod->tinterval = 10000;
2090 tod->day = t->tm_mday;
2091 tod->month = t->tm_mon + 1;
2092 tod->year = 1900+t->tm_year;
2093 tod->weekday = t->tm_wday;
2095 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2097 return WERR_OK;
2100 /***********************************************************************************
2101 _srvsvc_NetGetFileSecurity
2102 Win9x NT tools get security descriptor.
2103 ***********************************************************************************/
2105 WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
2106 struct srvsvc_NetGetFileSecurity *r)
2108 struct smb_filename *smb_fname = NULL;
2109 struct security_descriptor *psd = NULL;
2110 size_t sd_size;
2111 char *servicename = NULL;
2112 SMB_STRUCT_STAT st;
2113 NTSTATUS nt_status;
2114 WERROR werr;
2115 connection_struct *conn = NULL;
2116 struct sec_desc_buf *sd_buf = NULL;
2117 files_struct *fsp = NULL;
2118 int snum;
2119 char *oldcwd = NULL;
2121 ZERO_STRUCT(st);
2123 if (!r->in.share) {
2124 werr = WERR_NET_NAME_NOT_FOUND;
2125 goto error_exit;
2127 snum = find_service(talloc_tos(), r->in.share, &servicename);
2128 if (!servicename) {
2129 werr = WERR_NOMEM;
2130 goto error_exit;
2132 if (snum == -1) {
2133 DEBUG(10, ("Could not find service %s\n", servicename));
2134 werr = WERR_NET_NAME_NOT_FOUND;
2135 goto error_exit;
2138 nt_status = create_conn_struct(talloc_tos(),
2139 server_event_context(),
2140 server_messaging_context(),
2141 &conn,
2142 snum, lp_pathname(talloc_tos(), snum),
2143 p->session_info, &oldcwd);
2144 if (!NT_STATUS_IS_OK(nt_status)) {
2145 DEBUG(10, ("create_conn_struct failed: %s\n",
2146 nt_errstr(nt_status)));
2147 werr = ntstatus_to_werror(nt_status);
2148 goto error_exit;
2151 nt_status = filename_convert(talloc_tos(),
2152 conn,
2153 false,
2154 r->in.file,
2156 NULL,
2157 &smb_fname);
2158 if (!NT_STATUS_IS_OK(nt_status)) {
2159 werr = ntstatus_to_werror(nt_status);
2160 goto error_exit;
2163 nt_status = SMB_VFS_CREATE_FILE(
2164 conn, /* conn */
2165 NULL, /* req */
2166 0, /* root_dir_fid */
2167 smb_fname, /* fname */
2168 FILE_READ_ATTRIBUTES, /* access_mask */
2169 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2170 FILE_OPEN, /* create_disposition*/
2171 0, /* create_options */
2172 0, /* file_attributes */
2173 INTERNAL_OPEN_ONLY, /* oplock_request */
2174 0, /* allocation_size */
2175 0, /* private_flags */
2176 NULL, /* sd */
2177 NULL, /* ea_list */
2178 &fsp, /* result */
2179 NULL); /* pinfo */
2181 if (!NT_STATUS_IS_OK(nt_status)) {
2182 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2183 smb_fname_str_dbg(smb_fname)));
2184 werr = ntstatus_to_werror(nt_status);
2185 goto error_exit;
2188 nt_status = SMB_VFS_FGET_NT_ACL(fsp,
2189 (SECINFO_OWNER
2190 |SECINFO_GROUP
2191 |SECINFO_DACL), &psd);
2193 if (!NT_STATUS_IS_OK(nt_status)) {
2194 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2195 "for file %s\n", smb_fname_str_dbg(smb_fname)));
2196 werr = ntstatus_to_werror(nt_status);
2197 goto error_exit;
2200 if (psd && psd->dacl) {
2201 psd->dacl->revision = NT4_ACL_REVISION;
2204 sd_size = ndr_size_security_descriptor(psd, 0);
2206 sd_buf = talloc_zero(p->mem_ctx, struct sec_desc_buf);
2207 if (!sd_buf) {
2208 werr = WERR_NOMEM;
2209 goto error_exit;
2212 sd_buf->sd_size = sd_size;
2213 sd_buf->sd = psd;
2215 *r->out.sd_buf = sd_buf;
2217 close_file(NULL, fsp, NORMAL_CLOSE);
2218 vfs_ChDir(conn, oldcwd);
2219 SMB_VFS_DISCONNECT(conn);
2220 conn_free(conn);
2221 werr = WERR_OK;
2222 goto done;
2224 error_exit:
2226 if (fsp) {
2227 close_file(NULL, fsp, NORMAL_CLOSE);
2230 if (oldcwd) {
2231 vfs_ChDir(conn, oldcwd);
2234 if (conn) {
2235 SMB_VFS_DISCONNECT(conn);
2236 conn_free(conn);
2239 done:
2240 TALLOC_FREE(smb_fname);
2242 return werr;
2245 /***********************************************************************************
2246 _srvsvc_NetSetFileSecurity
2247 Win9x NT tools set security descriptor.
2248 ***********************************************************************************/
2250 WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
2251 struct srvsvc_NetSetFileSecurity *r)
2253 struct smb_filename *smb_fname = NULL;
2254 char *servicename = NULL;
2255 files_struct *fsp = NULL;
2256 SMB_STRUCT_STAT st;
2257 NTSTATUS nt_status;
2258 WERROR werr;
2259 connection_struct *conn = NULL;
2260 int snum;
2261 char *oldcwd = NULL;
2262 struct security_descriptor *psd = NULL;
2263 uint32_t security_info_sent = 0;
2265 ZERO_STRUCT(st);
2267 if (!r->in.share) {
2268 werr = WERR_NET_NAME_NOT_FOUND;
2269 goto error_exit;
2272 snum = find_service(talloc_tos(), r->in.share, &servicename);
2273 if (!servicename) {
2274 werr = WERR_NOMEM;
2275 goto error_exit;
2278 if (snum == -1) {
2279 DEBUG(10, ("Could not find service %s\n", servicename));
2280 werr = WERR_NET_NAME_NOT_FOUND;
2281 goto error_exit;
2284 nt_status = create_conn_struct(talloc_tos(),
2285 server_event_context(),
2286 server_messaging_context(),
2287 &conn,
2288 snum, lp_pathname(talloc_tos(), snum),
2289 p->session_info, &oldcwd);
2290 if (!NT_STATUS_IS_OK(nt_status)) {
2291 DEBUG(10, ("create_conn_struct failed: %s\n",
2292 nt_errstr(nt_status)));
2293 werr = ntstatus_to_werror(nt_status);
2294 goto error_exit;
2297 nt_status = filename_convert(talloc_tos(),
2298 conn,
2299 false,
2300 r->in.file,
2302 NULL,
2303 &smb_fname);
2304 if (!NT_STATUS_IS_OK(nt_status)) {
2305 werr = ntstatus_to_werror(nt_status);
2306 goto error_exit;
2309 nt_status = SMB_VFS_CREATE_FILE(
2310 conn, /* conn */
2311 NULL, /* req */
2312 0, /* root_dir_fid */
2313 smb_fname, /* fname */
2314 FILE_WRITE_ATTRIBUTES, /* access_mask */
2315 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2316 FILE_OPEN, /* create_disposition*/
2317 0, /* create_options */
2318 0, /* file_attributes */
2319 INTERNAL_OPEN_ONLY, /* oplock_request */
2320 0, /* allocation_size */
2321 0, /* private_flags */
2322 NULL, /* sd */
2323 NULL, /* ea_list */
2324 &fsp, /* result */
2325 NULL); /* pinfo */
2327 if (!NT_STATUS_IS_OK(nt_status)) {
2328 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2329 smb_fname_str_dbg(smb_fname)));
2330 werr = ntstatus_to_werror(nt_status);
2331 goto error_exit;
2334 psd = r->in.sd_buf->sd;
2335 security_info_sent = r->in.securityinformation;
2337 nt_status = set_sd(fsp, psd, security_info_sent);
2339 if (!NT_STATUS_IS_OK(nt_status) ) {
2340 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2341 "on file %s\n", r->in.share));
2342 werr = WERR_ACCESS_DENIED;
2343 goto error_exit;
2346 close_file(NULL, fsp, NORMAL_CLOSE);
2347 vfs_ChDir(conn, oldcwd);
2348 SMB_VFS_DISCONNECT(conn);
2349 conn_free(conn);
2350 werr = WERR_OK;
2351 goto done;
2353 error_exit:
2355 if (fsp) {
2356 close_file(NULL, fsp, NORMAL_CLOSE);
2359 if (oldcwd) {
2360 vfs_ChDir(conn, oldcwd);
2363 if (conn) {
2364 SMB_VFS_DISCONNECT(conn);
2365 conn_free(conn);
2368 done:
2369 TALLOC_FREE(smb_fname);
2371 return werr;
2374 /***********************************************************************************
2375 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2376 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2377 These disks would the disks listed by this function.
2378 Users could then create shares relative to these disks. Watch out for moving these disks around.
2379 "Nigel Williams" <nigel@veritas.com>.
2380 ***********************************************************************************/
2382 static const char *server_disks[] = {"C:"};
2384 static uint32 get_server_disk_count(void)
2386 return sizeof(server_disks)/sizeof(server_disks[0]);
2389 static uint32 init_server_disk_enum(uint32 *resume)
2391 uint32 server_disk_count = get_server_disk_count();
2393 /*resume can be an offset into the list for now*/
2395 if(*resume & 0x80000000)
2396 *resume = 0;
2398 if(*resume > server_disk_count)
2399 *resume = server_disk_count;
2401 return server_disk_count - *resume;
2404 static const char *next_server_disk_enum(uint32 *resume)
2406 const char *disk;
2408 if(init_server_disk_enum(resume) == 0)
2409 return NULL;
2411 disk = server_disks[*resume];
2413 (*resume)++;
2415 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2417 return disk;
2420 /********************************************************************
2421 _srvsvc_NetDiskEnum
2422 ********************************************************************/
2424 WERROR _srvsvc_NetDiskEnum(struct pipes_struct *p,
2425 struct srvsvc_NetDiskEnum *r)
2427 uint32 i;
2428 const char *disk_name;
2429 TALLOC_CTX *ctx = p->mem_ctx;
2430 WERROR werr;
2431 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2433 werr = WERR_OK;
2435 *r->out.totalentries = init_server_disk_enum(&resume);
2437 r->out.info->disks = talloc_zero_array(ctx, struct srvsvc_NetDiskInfo0,
2438 MAX_SERVER_DISK_ENTRIES);
2439 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2441 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2443 r->out.info->count = 0;
2445 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2447 r->out.info->count++;
2449 /*copy disk name into a unicode string*/
2451 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2452 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2455 /* add a terminating null string. Is this there if there is more data to come? */
2457 r->out.info->count++;
2459 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2460 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2462 if (r->out.resume_handle) {
2463 *r->out.resume_handle = resume;
2466 return werr;
2469 /********************************************************************
2470 _srvsvc_NetNameValidate
2471 ********************************************************************/
2473 WERROR _srvsvc_NetNameValidate(struct pipes_struct *p,
2474 struct srvsvc_NetNameValidate *r)
2476 switch (r->in.name_type) {
2477 case 0x9:
2478 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2479 strlen_m(r->in.name)))
2481 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2482 r->in.name));
2483 return WERR_INVALID_NAME;
2485 break;
2487 default:
2488 return WERR_UNKNOWN_LEVEL;
2491 return WERR_OK;
2494 /*******************************************************************
2495 ********************************************************************/
2497 struct enum_file_close_state {
2498 struct srvsvc_NetFileClose *r;
2499 struct messaging_context *msg_ctx;
2502 static void enum_file_close_fn( const struct share_mode_entry *e,
2503 const char *sharepath, const char *fname,
2504 void *private_data )
2506 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2507 struct enum_file_close_state *state =
2508 (struct enum_file_close_state *)private_data;
2509 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2511 if (fid != state->r->in.fid) {
2512 return; /* Not this file. */
2515 if (!process_exists(e->pid) ) {
2516 return;
2519 /* Ok - send the close message. */
2520 DEBUG(10,("enum_file_close_fn: request to close file %s, %s\n",
2521 sharepath,
2522 share_mode_str(talloc_tos(), 0, e) ));
2524 share_mode_entry_to_message(msg, e);
2526 state->r->out.result = ntstatus_to_werror(
2527 messaging_send_buf(state->msg_ctx,
2528 e->pid, MSG_SMB_CLOSE_FILE,
2529 (uint8 *)msg,
2530 MSG_SMB_SHARE_MODE_ENTRY_SIZE));
2533 /********************************************************************
2534 Close a file given a 32-bit file id.
2535 ********************************************************************/
2537 WERROR _srvsvc_NetFileClose(struct pipes_struct *p,
2538 struct srvsvc_NetFileClose *r)
2540 struct enum_file_close_state state;
2541 bool is_disk_op;
2543 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2545 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2547 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op) {
2548 return WERR_ACCESS_DENIED;
2551 /* enum_file_close_fn sends the close message to
2552 * the relevent smbd process. */
2554 r->out.result = WERR_BADFILE;
2555 state.r = r;
2556 state.msg_ctx = p->msg_ctx;
2557 share_mode_forall(enum_file_close_fn, &state);
2558 return r->out.result;
2561 /********************************************************************
2562 ********************************************************************/
2564 WERROR _srvsvc_NetCharDevEnum(struct pipes_struct *p,
2565 struct srvsvc_NetCharDevEnum *r)
2567 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2568 return WERR_NOT_SUPPORTED;
2571 WERROR _srvsvc_NetCharDevGetInfo(struct pipes_struct *p,
2572 struct srvsvc_NetCharDevGetInfo *r)
2574 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2575 return WERR_NOT_SUPPORTED;
2578 WERROR _srvsvc_NetCharDevControl(struct pipes_struct *p,
2579 struct srvsvc_NetCharDevControl *r)
2581 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2582 return WERR_NOT_SUPPORTED;
2585 WERROR _srvsvc_NetCharDevQEnum(struct pipes_struct *p,
2586 struct srvsvc_NetCharDevQEnum *r)
2588 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2589 return WERR_NOT_SUPPORTED;
2592 WERROR _srvsvc_NetCharDevQGetInfo(struct pipes_struct *p,
2593 struct srvsvc_NetCharDevQGetInfo *r)
2595 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2596 return WERR_NOT_SUPPORTED;
2599 WERROR _srvsvc_NetCharDevQSetInfo(struct pipes_struct *p,
2600 struct srvsvc_NetCharDevQSetInfo *r)
2602 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2603 return WERR_NOT_SUPPORTED;
2606 WERROR _srvsvc_NetCharDevQPurge(struct pipes_struct *p,
2607 struct srvsvc_NetCharDevQPurge *r)
2609 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2610 return WERR_NOT_SUPPORTED;
2613 WERROR _srvsvc_NetCharDevQPurgeSelf(struct pipes_struct *p,
2614 struct srvsvc_NetCharDevQPurgeSelf *r)
2616 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2617 return WERR_NOT_SUPPORTED;
2620 WERROR _srvsvc_NetFileGetInfo(struct pipes_struct *p,
2621 struct srvsvc_NetFileGetInfo *r)
2623 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2624 return WERR_NOT_SUPPORTED;
2627 WERROR _srvsvc_NetShareCheck(struct pipes_struct *p,
2628 struct srvsvc_NetShareCheck *r)
2630 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2631 return WERR_NOT_SUPPORTED;
2634 WERROR _srvsvc_NetServerStatisticsGet(struct pipes_struct *p,
2635 struct srvsvc_NetServerStatisticsGet *r)
2637 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2638 return WERR_NOT_SUPPORTED;
2641 WERROR _srvsvc_NetTransportAdd(struct pipes_struct *p,
2642 struct srvsvc_NetTransportAdd *r)
2644 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2645 return WERR_NOT_SUPPORTED;
2648 WERROR _srvsvc_NetTransportEnum(struct pipes_struct *p,
2649 struct srvsvc_NetTransportEnum *r)
2651 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2652 return WERR_NOT_SUPPORTED;
2655 WERROR _srvsvc_NetTransportDel(struct pipes_struct *p,
2656 struct srvsvc_NetTransportDel *r)
2658 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2659 return WERR_NOT_SUPPORTED;
2662 WERROR _srvsvc_NetSetServiceBits(struct pipes_struct *p,
2663 struct srvsvc_NetSetServiceBits *r)
2665 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2666 return WERR_NOT_SUPPORTED;
2669 WERROR _srvsvc_NetPathType(struct pipes_struct *p,
2670 struct srvsvc_NetPathType *r)
2672 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2673 return WERR_NOT_SUPPORTED;
2676 WERROR _srvsvc_NetPathCanonicalize(struct pipes_struct *p,
2677 struct srvsvc_NetPathCanonicalize *r)
2679 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2680 return WERR_NOT_SUPPORTED;
2683 WERROR _srvsvc_NetPathCompare(struct pipes_struct *p,
2684 struct srvsvc_NetPathCompare *r)
2686 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2687 return WERR_NOT_SUPPORTED;
2690 WERROR _srvsvc_NETRPRNAMECANONICALIZE(struct pipes_struct *p,
2691 struct srvsvc_NETRPRNAMECANONICALIZE *r)
2693 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2694 return WERR_NOT_SUPPORTED;
2697 WERROR _srvsvc_NetPRNameCompare(struct pipes_struct *p,
2698 struct srvsvc_NetPRNameCompare *r)
2700 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2701 return WERR_NOT_SUPPORTED;
2704 WERROR _srvsvc_NetShareDelStart(struct pipes_struct *p,
2705 struct srvsvc_NetShareDelStart *r)
2707 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2708 return WERR_NOT_SUPPORTED;
2711 WERROR _srvsvc_NetShareDelCommit(struct pipes_struct *p,
2712 struct srvsvc_NetShareDelCommit *r)
2714 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2715 return WERR_NOT_SUPPORTED;
2718 WERROR _srvsvc_NetServerTransportAddEx(struct pipes_struct *p,
2719 struct srvsvc_NetServerTransportAddEx *r)
2721 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2722 return WERR_NOT_SUPPORTED;
2725 WERROR _srvsvc_NetServerSetServiceBitsEx(struct pipes_struct *p,
2726 struct srvsvc_NetServerSetServiceBitsEx *r)
2728 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2729 return WERR_NOT_SUPPORTED;
2732 WERROR _srvsvc_NETRDFSGETVERSION(struct pipes_struct *p,
2733 struct srvsvc_NETRDFSGETVERSION *r)
2735 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2736 return WERR_NOT_SUPPORTED;
2739 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(struct pipes_struct *p,
2740 struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2742 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2743 return WERR_NOT_SUPPORTED;
2746 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(struct pipes_struct *p,
2747 struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2749 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2750 return WERR_NOT_SUPPORTED;
2753 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(struct pipes_struct *p,
2754 struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
2756 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2757 return WERR_NOT_SUPPORTED;
2760 WERROR _srvsvc_NETRDFSSETSERVERINFO(struct pipes_struct *p,
2761 struct srvsvc_NETRDFSSETSERVERINFO *r)
2763 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2764 return WERR_NOT_SUPPORTED;
2767 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(struct pipes_struct *p,
2768 struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2770 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2771 return WERR_NOT_SUPPORTED;
2774 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(struct pipes_struct *p,
2775 struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2777 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2778 return WERR_NOT_SUPPORTED;
2781 WERROR _srvsvc_NETRDFSMODIFYPREFIX(struct pipes_struct *p,
2782 struct srvsvc_NETRDFSMODIFYPREFIX *r)
2784 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2785 return WERR_NOT_SUPPORTED;
2788 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(struct pipes_struct *p,
2789 struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2791 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2792 return WERR_NOT_SUPPORTED;
2795 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(struct pipes_struct *p,
2796 struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2798 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2799 return WERR_NOT_SUPPORTED;
2802 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(struct pipes_struct *p,
2803 struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2805 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2806 return WERR_NOT_SUPPORTED;