ctdb-vacuum: rename ctdb_vacuum_db_full --> ctdb_vacuum_traverse_db
[Samba.git] / source3 / rpc_server / srvsvc / srv_srvsvc_nt.c
blob4631691e7ef48a2a2713118e54d89e678d87aab7
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_info {
58 struct srvsvc_NetSessCtr1 *ctr;
59 struct sessionid *session_list;
60 uint32_t resume_handle;
61 uint32_t num_entries;
64 /*******************************************************************
65 ********************************************************************/
67 static void enum_file_fn( const struct share_mode_entry *e,
68 const char *sharepath, const char *fname,
69 void *private_data )
71 struct file_enum_count *fenum =
72 (struct file_enum_count *)private_data;
74 struct srvsvc_NetFileInfo3 *f;
75 int i = fenum->ctr3->count;
76 files_struct fsp;
77 struct byte_range_lock *brl;
78 int num_locks = 0;
79 char *fullpath = NULL;
80 uint32 permissions;
81 const char *username;
83 /* If the pid was not found delete the entry from connections.tdb */
85 if ( !process_exists(e->pid) ) {
86 return;
89 username = uidtoname(e->uid);
91 if ((fenum->username != NULL)
92 && !strequal(username, fenum->username)) {
93 return;
96 f = talloc_realloc(fenum->ctx, fenum->ctr3->array,
97 struct srvsvc_NetFileInfo3, i+1);
98 if ( !f ) {
99 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
100 return;
102 fenum->ctr3->array = f;
104 /* need to count the number of locks on a file */
106 ZERO_STRUCT( fsp );
107 fsp.file_id = e->id;
109 if ( (brl = brl_get_locks(talloc_tos(), &fsp)) != NULL ) {
110 num_locks = brl_num_locks(brl);
111 TALLOC_FREE(brl);
114 if ( strcmp( fname, "." ) == 0 ) {
115 fullpath = talloc_asprintf(fenum->ctx, "C:%s", sharepath );
116 } else {
117 fullpath = talloc_asprintf(fenum->ctx, "C:%s/%s",
118 sharepath, fname );
120 if (!fullpath) {
121 return;
123 string_replace( fullpath, '/', '\\' );
125 /* mask out create (what ever that is) */
126 permissions = e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA);
128 /* now fill in the srvsvc_NetFileInfo3 struct */
130 fenum->ctr3->array[i].fid =
131 (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
132 fenum->ctr3->array[i].permissions = permissions;
133 fenum->ctr3->array[i].num_locks = num_locks;
134 fenum->ctr3->array[i].path = fullpath;
135 fenum->ctr3->array[i].user = username;
137 fenum->ctr3->count++;
140 /*******************************************************************
141 ********************************************************************/
143 static WERROR net_enum_files(TALLOC_CTX *ctx,
144 const char *username,
145 struct srvsvc_NetFileCtr3 **ctr3,
146 uint32_t resume)
148 struct file_enum_count f_enum_cnt;
150 f_enum_cnt.ctx = ctx;
151 f_enum_cnt.username = username;
152 f_enum_cnt.ctr3 = *ctr3;
154 share_mode_forall( enum_file_fn, (void *)&f_enum_cnt );
156 *ctr3 = f_enum_cnt.ctr3;
158 return WERR_OK;
161 /*******************************************************************
162 Utility function to get the 'type' of a share from an snum.
163 ********************************************************************/
164 static enum srvsvc_ShareType get_share_type(int snum)
166 /* work out the share type */
167 enum srvsvc_ShareType type = STYPE_DISKTREE;
169 if (lp_printable(snum)) {
170 type = lp_administrative_share(snum)
171 ? STYPE_PRINTQ_HIDDEN : STYPE_PRINTQ;
173 if (strequal(lp_fstype(snum), "IPC")) {
174 type = lp_administrative_share(snum)
175 ? STYPE_IPC_HIDDEN : STYPE_IPC;
177 return type;
180 /*******************************************************************
181 Fill in a share info level 0 structure.
182 ********************************************************************/
184 static void init_srv_share_info_0(struct pipes_struct *p,
185 struct srvsvc_NetShareInfo0 *r, int snum)
187 r->name = lp_servicename(talloc_tos(), snum);
190 /*******************************************************************
191 Fill in a share info level 1 structure.
192 ********************************************************************/
194 static void init_srv_share_info_1(struct pipes_struct *p,
195 struct srvsvc_NetShareInfo1 *r,
196 int snum)
198 char *net_name = lp_servicename(talloc_tos(), snum);
199 char *remark = lp_comment(p->mem_ctx, snum);
201 if (remark) {
202 remark = talloc_sub_advanced(
203 p->mem_ctx, lp_servicename(talloc_tos(), snum),
204 get_current_username(), lp_path(talloc_tos(), snum),
205 p->session_info->unix_token->uid, get_current_username(),
206 "", remark);
209 r->name = net_name;
210 r->type = get_share_type(snum);
211 r->comment = remark ? remark : "";
214 /*******************************************************************
215 Fill in a share info level 2 structure.
216 ********************************************************************/
218 static void init_srv_share_info_2(struct pipes_struct *p,
219 struct srvsvc_NetShareInfo2 *r,
220 int snum)
222 char *remark = NULL;
223 char *path = NULL;
224 int max_connections = lp_max_connections(snum);
225 uint32_t max_uses = max_connections!=0 ? max_connections : (uint32_t)-1;
226 char *net_name = lp_servicename(talloc_tos(), snum);
228 remark = lp_comment(p->mem_ctx, snum);
229 if (remark) {
230 remark = talloc_sub_advanced(
231 p->mem_ctx, lp_servicename(talloc_tos(), snum),
232 get_current_username(), lp_path(talloc_tos(), snum),
233 p->session_info->unix_token->uid, get_current_username(),
234 "", remark);
236 path = talloc_asprintf(p->mem_ctx,
237 "C:%s", lp_path(talloc_tos(), snum));
239 if (path) {
241 * Change / to \\ so that win2k will see it as a valid path.
242 * This was added to enable use of browsing in win2k add
243 * share dialog.
246 string_replace(path, '/', '\\');
249 r->name = net_name;
250 r->type = get_share_type(snum);
251 r->comment = remark ? remark : "";
252 r->permissions = 0;
253 r->max_users = max_uses;
254 r->current_users = 0; /* computed later */
255 r->path = path ? path : "";
256 r->password = "";
259 /*******************************************************************
260 Map any generic bits to file specific bits.
261 ********************************************************************/
263 static void map_generic_share_sd_bits(struct security_descriptor *psd)
265 int i;
266 struct security_acl *ps_dacl = NULL;
268 if (!psd)
269 return;
271 ps_dacl = psd->dacl;
272 if (!ps_dacl)
273 return;
275 for (i = 0; i < ps_dacl->num_aces; i++) {
276 struct security_ace *psa = &ps_dacl->aces[i];
277 uint32 orig_mask = psa->access_mask;
279 se_map_generic(&psa->access_mask, &file_generic_mapping);
280 psa->access_mask |= orig_mask;
284 /*******************************************************************
285 Fill in a share info level 501 structure.
286 ********************************************************************/
288 static void init_srv_share_info_501(struct pipes_struct *p,
289 struct srvsvc_NetShareInfo501 *r, int snum)
291 const char *net_name = lp_servicename(talloc_tos(), snum);
292 char *remark = lp_comment(p->mem_ctx, snum);
294 if (remark) {
295 remark = talloc_sub_advanced(
296 p->mem_ctx, lp_servicename(talloc_tos(), snum),
297 get_current_username(), lp_path(talloc_tos(), snum),
298 p->session_info->unix_token->uid, get_current_username(),
299 "", remark);
302 r->name = net_name;
303 r->type = get_share_type(snum);
304 r->comment = remark ? remark : "";
307 * According to [MS-SRVS] 2.2.4.25, the flags field is the same as in
308 * level 1005.
310 r->csc_policy = (lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT);
313 /*******************************************************************
314 Fill in a share info level 502 structure.
315 ********************************************************************/
317 static void init_srv_share_info_502(struct pipes_struct *p,
318 struct srvsvc_NetShareInfo502 *r, int snum)
320 const char *net_name = lp_servicename(talloc_tos(), snum);
321 char *path = NULL;
322 struct security_descriptor *sd = NULL;
323 struct sec_desc_buf *sd_buf = NULL;
324 size_t sd_size = 0;
325 TALLOC_CTX *ctx = p->mem_ctx;
326 char *remark = lp_comment(ctx, snum);
328 if (remark) {
329 remark = talloc_sub_advanced(
330 p->mem_ctx, lp_servicename(talloc_tos(), snum),
331 get_current_username(), lp_path(talloc_tos(), snum),
332 p->session_info->unix_token->uid, get_current_username(),
333 "", remark);
335 path = talloc_asprintf(ctx, "C:%s", lp_path(talloc_tos(), snum));
336 if (path) {
338 * Change / to \\ so that win2k will see it as a valid path. This was added to
339 * enable use of browsing in win2k add share dialog.
341 string_replace(path, '/', '\\');
344 sd = get_share_security(ctx, lp_servicename(talloc_tos(), snum), &sd_size);
346 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
348 r->name = net_name;
349 r->type = get_share_type(snum);
350 r->comment = remark ? remark : "";
351 r->permissions = 0;
352 r->max_users = (uint32_t)-1;
353 r->current_users = 1; /* ??? */
354 r->path = path ? path : "";
355 r->password = "";
356 r->sd_buf = *sd_buf;
359 /***************************************************************************
360 Fill in a share info level 1004 structure.
361 ***************************************************************************/
363 static void init_srv_share_info_1004(struct pipes_struct *p,
364 struct srvsvc_NetShareInfo1004 *r,
365 int snum)
367 char *remark = lp_comment(p->mem_ctx, snum);
369 if (remark) {
370 remark = talloc_sub_advanced(
371 p->mem_ctx, lp_servicename(talloc_tos(), snum),
372 get_current_username(), lp_path(talloc_tos(), snum),
373 p->session_info->unix_token->uid, get_current_username(),
374 "", remark);
377 r->comment = remark ? remark : "";
380 /***************************************************************************
381 Fill in a share info level 1005 structure.
382 ***************************************************************************/
384 static void init_srv_share_info_1005(struct pipes_struct *p,
385 struct srvsvc_NetShareInfo1005 *r,
386 int snum)
388 uint32_t dfs_flags = 0;
390 if (lp_host_msdfs() && lp_msdfs_root(snum)) {
391 dfs_flags |= SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
394 dfs_flags |= lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
396 r->dfs_flags = dfs_flags;
399 /***************************************************************************
400 Fill in a share info level 1006 structure.
401 ***************************************************************************/
403 static void init_srv_share_info_1006(struct pipes_struct *p,
404 struct srvsvc_NetShareInfo1006 *r,
405 int snum)
407 r->max_users = (uint32_t)-1;
410 /***************************************************************************
411 Fill in a share info level 1007 structure.
412 ***************************************************************************/
414 static void init_srv_share_info_1007(struct pipes_struct *p,
415 struct srvsvc_NetShareInfo1007 *r,
416 int snum)
418 r->flags = 0;
419 r->alternate_directory_name = "";
422 /*******************************************************************
423 Fill in a share info level 1501 structure.
424 ********************************************************************/
426 static void init_srv_share_info_1501(struct pipes_struct *p,
427 struct sec_desc_buf **r,
428 int snum)
430 struct security_descriptor *sd;
431 struct sec_desc_buf *sd_buf = NULL;
432 size_t sd_size;
433 TALLOC_CTX *ctx = p->mem_ctx;
435 sd = get_share_security(ctx, lp_servicename(talloc_tos(), snum), &sd_size);
436 if (sd) {
437 sd_buf = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
440 *r = sd_buf;
443 /*******************************************************************
444 True if it ends in '$'.
445 ********************************************************************/
447 static bool is_hidden_share(int snum)
449 const char *net_name = lp_servicename(talloc_tos(), snum);
451 return (net_name[strlen(net_name) - 1] == '$') ? True : False;
454 /*******************************************************************
455 Verify user is allowed to view share, access based enumeration
456 ********************************************************************/
457 static bool is_enumeration_allowed(struct pipes_struct *p,
458 int snum)
460 if (!lp_access_based_share_enum(snum))
461 return true;
463 return share_access_check(p->session_info->security_token,
464 lp_servicename(talloc_tos(), snum),
465 FILE_READ_DATA, NULL);
468 /****************************************************************************
469 Count an entry against the respective service.
470 ****************************************************************************/
472 static int count_for_all_fn(struct smbXsrv_tcon_global0 *tcon, void *udp)
474 union srvsvc_NetShareCtr *ctr = NULL;
475 struct srvsvc_NetShareInfo2 *info2 = NULL;
476 int share_entries = 0;
477 int i = 0;
479 ctr = (union srvsvc_NetShareCtr *) udp;
481 /* for level 2 */
482 share_entries = ctr->ctr2->count;
483 info2 = &ctr->ctr2->array[0];
485 for (i = 0; i < share_entries; i++, info2++) {
486 if (strequal(tcon->share_name, info2->name)) {
487 info2->current_users++;
488 break;
492 return 0;
495 /****************************************************************************
496 Count the entries belonging to all services in the connection db.
497 ****************************************************************************/
499 static void count_connections_for_all_shares(union srvsvc_NetShareCtr *ctr)
501 NTSTATUS status;
502 status = smbXsrv_tcon_global_traverse(count_for_all_fn, ctr);
504 if (!NT_STATUS_IS_OK(status)) {
505 DEBUG(0,("count_connections_for_all_shares: traverse of "
506 "smbXsrv_tcon_global.tdb failed - %s\n",
507 nt_errstr(status)));
511 /*******************************************************************
512 Fill in a share info structure.
513 ********************************************************************/
515 static WERROR init_srv_share_info_ctr(struct pipes_struct *p,
516 struct srvsvc_NetShareInfoCtr *info_ctr,
517 uint32_t *resume_handle_p,
518 uint32_t *total_entries,
519 bool all_shares)
521 int num_entries = 0;
522 int alloc_entries = 0;
523 int num_services = 0;
524 int snum;
525 TALLOC_CTX *ctx = p->mem_ctx;
526 int i = 0;
527 int valid_share_count = 0;
528 bool *allowed = 0;
529 union srvsvc_NetShareCtr ctr;
530 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
532 DEBUG(5,("init_srv_share_info_ctr\n"));
534 /* Ensure all the usershares are loaded. */
535 become_root();
536 load_usershare_shares(NULL, connections_snum_used);
537 load_registry_shares();
538 num_services = lp_numservices();
539 unbecome_root();
541 allowed = talloc_zero_array(ctx, bool, num_services);
542 W_ERROR_HAVE_NO_MEMORY(allowed);
544 /* Count the number of entries. */
545 for (snum = 0; snum < num_services; snum++) {
546 if (lp_browseable(snum) && lp_snum_ok(snum) &&
547 is_enumeration_allowed(p, snum) &&
548 (all_shares || !is_hidden_share(snum)) ) {
549 DEBUG(10, ("counting service %s\n",
550 lp_servicename(talloc_tos(), snum) ? lp_servicename(talloc_tos(), snum) : "(null)"));
551 allowed[snum] = true;
552 num_entries++;
553 } else {
554 DEBUG(10, ("NOT counting service %s\n",
555 lp_servicename(talloc_tos(), snum) ? lp_servicename(talloc_tos(), snum) : "(null)"));
559 if (!num_entries || (resume_handle >= num_entries)) {
560 return WERR_OK;
563 /* Calculate alloc entries. */
564 alloc_entries = num_entries - resume_handle;
565 switch (info_ctr->level) {
566 case 0:
567 ctr.ctr0 = talloc_zero(ctx, struct srvsvc_NetShareCtr0);
568 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0);
570 ctr.ctr0->count = alloc_entries;
571 ctr.ctr0->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo0, alloc_entries);
572 W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
574 for (snum = 0; snum < num_services; snum++) {
575 if (allowed[snum] &&
576 (resume_handle <= (i + valid_share_count++)) ) {
577 init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
581 break;
583 case 1:
584 ctr.ctr1 = talloc_zero(ctx, struct srvsvc_NetShareCtr1);
585 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1);
587 ctr.ctr1->count = alloc_entries;
588 ctr.ctr1->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1, alloc_entries);
589 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
591 for (snum = 0; snum < num_services; snum++) {
592 if (allowed[snum] &&
593 (resume_handle <= (i + valid_share_count++)) ) {
594 init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
598 break;
600 case 2:
601 ctr.ctr2 = talloc_zero(ctx, struct srvsvc_NetShareCtr2);
602 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2);
604 ctr.ctr2->count = alloc_entries;
605 ctr.ctr2->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo2, alloc_entries);
606 W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
608 for (snum = 0; snum < num_services; snum++) {
609 if (allowed[snum] &&
610 (resume_handle <= (i + valid_share_count++)) ) {
611 init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
615 count_connections_for_all_shares(&ctr);
616 break;
618 case 501:
619 ctr.ctr501 = talloc_zero(ctx, struct srvsvc_NetShareCtr501);
620 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501);
622 ctr.ctr501->count = alloc_entries;
623 ctr.ctr501->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo501, alloc_entries);
624 W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
626 for (snum = 0; snum < num_services; snum++) {
627 if (allowed[snum] &&
628 (resume_handle <= (i + valid_share_count++)) ) {
629 init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
633 break;
635 case 502:
636 ctr.ctr502 = talloc_zero(ctx, struct srvsvc_NetShareCtr502);
637 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502);
639 ctr.ctr502->count = alloc_entries;
640 ctr.ctr502->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo502, alloc_entries);
641 W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
643 for (snum = 0; snum < num_services; snum++) {
644 if (allowed[snum] &&
645 (resume_handle <= (i + valid_share_count++)) ) {
646 init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
650 break;
652 case 1004:
653 ctr.ctr1004 = talloc_zero(ctx, struct srvsvc_NetShareCtr1004);
654 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004);
656 ctr.ctr1004->count = alloc_entries;
657 ctr.ctr1004->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1004, alloc_entries);
658 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
660 for (snum = 0; snum < num_services; snum++) {
661 if (allowed[snum] &&
662 (resume_handle <= (i + valid_share_count++)) ) {
663 init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
667 break;
669 case 1005:
670 ctr.ctr1005 = talloc_zero(ctx, struct srvsvc_NetShareCtr1005);
671 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005);
673 ctr.ctr1005->count = alloc_entries;
674 ctr.ctr1005->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1005, alloc_entries);
675 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
677 for (snum = 0; snum < num_services; snum++) {
678 if (allowed[snum] &&
679 (resume_handle <= (i + valid_share_count++)) ) {
680 init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
684 break;
686 case 1006:
687 ctr.ctr1006 = talloc_zero(ctx, struct srvsvc_NetShareCtr1006);
688 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006);
690 ctr.ctr1006->count = alloc_entries;
691 ctr.ctr1006->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1006, alloc_entries);
692 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
694 for (snum = 0; snum < num_services; snum++) {
695 if (allowed[snum] &&
696 (resume_handle <= (i + valid_share_count++)) ) {
697 init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
701 break;
703 case 1007:
704 ctr.ctr1007 = talloc_zero(ctx, struct srvsvc_NetShareCtr1007);
705 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007);
707 ctr.ctr1007->count = alloc_entries;
708 ctr.ctr1007->array = talloc_zero_array(ctx, struct srvsvc_NetShareInfo1007, alloc_entries);
709 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
711 for (snum = 0; snum < num_services; snum++) {
712 if (allowed[snum] &&
713 (resume_handle <= (i + valid_share_count++)) ) {
714 init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
718 break;
720 case 1501:
721 ctr.ctr1501 = talloc_zero(ctx, struct srvsvc_NetShareCtr1501);
722 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501);
724 ctr.ctr1501->count = alloc_entries;
725 ctr.ctr1501->array = talloc_zero_array(ctx, struct sec_desc_buf, alloc_entries);
726 W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
728 for (snum = 0; snum < num_services; snum++) {
729 if (allowed[snum] &&
730 (resume_handle <= (i + valid_share_count++)) ) {
731 struct sec_desc_buf *sd_buf = NULL;
732 init_srv_share_info_1501(p, &sd_buf, snum);
733 ctr.ctr1501->array[i++] = *sd_buf;
737 break;
739 default:
740 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n",
741 info_ctr->level));
742 return WERR_UNKNOWN_LEVEL;
745 *total_entries = alloc_entries;
746 if (resume_handle_p) {
747 if (all_shares) {
748 *resume_handle_p = (num_entries == 0) ? *resume_handle_p : 0;
749 } else {
750 *resume_handle_p = num_entries;
754 info_ctr->ctr = ctr;
756 return WERR_OK;
759 /*******************************************************************
760 fill in a sess info level 0 structure.
761 ********************************************************************/
763 static WERROR init_srv_sess_info_0(struct pipes_struct *p,
764 struct srvsvc_NetSessCtr0 *ctr0,
765 uint32_t *resume_handle_p,
766 uint32_t *total_entries)
768 struct sessionid *session_list;
769 uint32_t num_entries = 0;
770 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
771 *total_entries = list_sessions(p->mem_ctx, &session_list);
773 DEBUG(5,("init_srv_sess_info_0\n"));
775 if (ctr0 == NULL) {
776 if (resume_handle_p) {
777 *resume_handle_p = 0;
779 return WERR_OK;
782 for (; resume_handle < *total_entries; resume_handle++) {
784 ctr0->array = talloc_realloc(p->mem_ctx,
785 ctr0->array,
786 struct srvsvc_NetSessInfo0,
787 num_entries+1);
788 W_ERROR_HAVE_NO_MEMORY(ctr0->array);
790 ctr0->array[num_entries].client =
791 session_list[resume_handle].remote_machine;
793 num_entries++;
796 ctr0->count = num_entries;
798 if (resume_handle_p) {
799 if (*resume_handle_p >= *total_entries) {
800 *resume_handle_p = 0;
801 } else {
802 *resume_handle_p = resume_handle;
806 return WERR_OK;
809 /***********************************************************************
810 * find out the session on which this file is open and bump up its count
811 **********************************************************************/
813 static void count_sess_files_fn(const struct share_mode_entry *e,
814 const char *sharepath, const char *fname,
815 void *data)
817 struct sess_file_info *info = data;
818 uint32_t rh = info->resume_handle;
819 int i;
821 for (i=0; i < info->num_entries; i++) {
822 /* rh+info->num_entries is safe, as we've
823 ensured that:
824 *total_entries > resume_handle &&
825 info->num_entries = *total_entries - resume_handle;
826 inside init_srv_sess_info_1() below.
828 struct sessionid *sess = &info->session_list[rh + i];
829 if ((e->uid == sess->uid) &&
830 serverid_equal(&e->pid, &sess->pid)) {
832 info->ctr->array[i].num_open++;
833 return;
838 /*******************************************************************
839 * count the num of open files on all sessions
840 *******************************************************************/
842 static void net_count_files_for_all_sess(struct srvsvc_NetSessCtr1 *ctr1,
843 struct sessionid *session_list,
844 uint32_t resume_handle,
845 uint32_t num_entries)
847 struct sess_file_info s_file_info;
849 s_file_info.ctr = ctr1;
850 s_file_info.session_list = session_list;
851 s_file_info.resume_handle = resume_handle;
852 s_file_info.num_entries = num_entries;
854 share_mode_forall(count_sess_files_fn, &s_file_info);
857 /*******************************************************************
858 fill in a sess info level 1 structure.
859 ********************************************************************/
861 static WERROR init_srv_sess_info_1(struct pipes_struct *p,
862 struct srvsvc_NetSessCtr1 *ctr1,
863 uint32_t *resume_handle_p,
864 uint32_t *total_entries)
866 struct sessionid *session_list;
867 uint32_t num_entries = 0;
868 time_t now = time(NULL);
869 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
871 ZERO_STRUCTP(ctr1);
873 if (ctr1 == NULL) {
874 if (resume_handle_p) {
875 *resume_handle_p = 0;
877 return WERR_OK;
880 *total_entries = list_sessions(p->mem_ctx, &session_list);
882 if (resume_handle >= *total_entries) {
883 if (resume_handle_p) {
884 *resume_handle_p = 0;
886 return WERR_OK;
889 /* We know num_entries must be positive, due to
890 the check resume_handle >= *total_entries above. */
892 num_entries = *total_entries - resume_handle;
894 ctr1->array = talloc_zero_array(p->mem_ctx,
895 struct srvsvc_NetSessInfo1,
896 num_entries);
898 W_ERROR_HAVE_NO_MEMORY(ctr1->array);
900 for (num_entries = 0; resume_handle < *total_entries; num_entries++, resume_handle++) {
901 uint32 connect_time;
902 bool guest;
904 connect_time = (uint32_t)(now - session_list[resume_handle].connect_start);
905 guest = strequal( session_list[resume_handle].username, lp_guest_account() );
907 ctr1->array[num_entries].client = session_list[resume_handle].remote_machine;
908 ctr1->array[num_entries].user = session_list[resume_handle].username;
909 ctr1->array[num_entries].num_open = 0;/* computed later */
910 ctr1->array[num_entries].time = connect_time;
911 ctr1->array[num_entries].idle_time = 0;
912 ctr1->array[num_entries].user_flags = guest;
915 ctr1->count = num_entries;
917 /* count open files on all sessions in single tdb traversal */
918 net_count_files_for_all_sess(ctr1, session_list,
919 resume_handle_p ? *resume_handle_p : 0,
920 num_entries);
922 if (resume_handle_p) {
923 if (*resume_handle_p >= *total_entries) {
924 *resume_handle_p = 0;
925 } else {
926 *resume_handle_p = resume_handle;
930 return WERR_OK;
933 /*******************************************************************
934 fill in a conn info level 0 structure.
935 ********************************************************************/
937 static WERROR init_srv_conn_info_0(struct srvsvc_NetConnCtr0 *ctr0,
938 uint32_t *resume_handle_p,
939 uint32_t *total_entries)
941 uint32_t num_entries = 0;
942 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
944 DEBUG(5,("init_srv_conn_info_0\n"));
946 if (ctr0 == NULL) {
947 if (resume_handle_p) {
948 *resume_handle_p = 0;
950 return WERR_OK;
953 *total_entries = 1;
955 ZERO_STRUCTP(ctr0);
957 for (; resume_handle < *total_entries; resume_handle++) {
959 ctr0->array = talloc_realloc(talloc_tos(),
960 ctr0->array,
961 struct srvsvc_NetConnInfo0,
962 num_entries+1);
963 if (!ctr0->array) {
964 return WERR_NOMEM;
967 ctr0->array[num_entries].conn_id = *total_entries;
969 /* move on to creating next connection */
970 num_entries++;
973 ctr0->count = num_entries;
974 *total_entries = num_entries;
976 if (resume_handle_p) {
977 if (*resume_handle_p >= *total_entries) {
978 *resume_handle_p = 0;
979 } else {
980 *resume_handle_p = resume_handle;
984 return WERR_OK;
987 /*******************************************************************
988 fill in a conn info level 1 structure.
989 ********************************************************************/
991 static WERROR init_srv_conn_info_1(struct srvsvc_NetConnCtr1 *ctr1,
992 uint32_t *resume_handle_p,
993 uint32_t *total_entries)
995 uint32_t num_entries = 0;
996 uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
998 DEBUG(5,("init_srv_conn_info_1\n"));
1000 if (ctr1 == NULL) {
1001 if (resume_handle_p) {
1002 *resume_handle_p = 0;
1004 return WERR_OK;
1007 *total_entries = 1;
1009 ZERO_STRUCTP(ctr1);
1011 for (; resume_handle < *total_entries; resume_handle++) {
1013 ctr1->array = talloc_realloc(talloc_tos(),
1014 ctr1->array,
1015 struct srvsvc_NetConnInfo1,
1016 num_entries+1);
1017 if (!ctr1->array) {
1018 return WERR_NOMEM;
1021 ctr1->array[num_entries].conn_id = *total_entries;
1022 ctr1->array[num_entries].conn_type = 0x3;
1023 ctr1->array[num_entries].num_open = 1;
1024 ctr1->array[num_entries].num_users = 1;
1025 ctr1->array[num_entries].conn_time = 3;
1026 ctr1->array[num_entries].user = "dummy_user";
1027 ctr1->array[num_entries].share = "IPC$";
1029 /* move on to creating next connection */
1030 num_entries++;
1033 ctr1->count = num_entries;
1034 *total_entries = num_entries;
1036 if (resume_handle_p) {
1037 if (*resume_handle_p >= *total_entries) {
1038 *resume_handle_p = 0;
1039 } else {
1040 *resume_handle_p = resume_handle;
1044 return WERR_OK;
1047 /*******************************************************************
1048 _srvsvc_NetFileEnum
1049 *******************************************************************/
1051 WERROR _srvsvc_NetFileEnum(struct pipes_struct *p,
1052 struct srvsvc_NetFileEnum *r)
1054 TALLOC_CTX *ctx = NULL;
1055 struct srvsvc_NetFileCtr3 *ctr3;
1056 uint32_t resume_hnd = 0;
1057 WERROR werr;
1059 switch (r->in.info_ctr->level) {
1060 case 3:
1061 break;
1062 default:
1063 return WERR_UNKNOWN_LEVEL;
1066 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1067 p->session_info->security_token)) {
1068 DEBUG(1, ("Enumerating files only allowed for "
1069 "administrators\n"));
1070 return WERR_ACCESS_DENIED;
1073 ctx = talloc_tos();
1074 ctr3 = r->in.info_ctr->ctr.ctr3;
1075 if (!ctr3) {
1076 werr = WERR_INVALID_PARAM;
1077 goto done;
1080 /* TODO -- Windows enumerates
1081 (b) active pipes
1082 (c) open directories and files */
1084 werr = net_enum_files(ctx, r->in.user, &ctr3, resume_hnd);
1085 if (!W_ERROR_IS_OK(werr)) {
1086 goto done;
1089 *r->out.totalentries = ctr3->count;
1090 r->out.info_ctr->ctr.ctr3->array = ctr3->array;
1091 r->out.info_ctr->ctr.ctr3->count = ctr3->count;
1093 werr = WERR_OK;
1095 done:
1096 return werr;
1099 /*******************************************************************
1100 _srvsvc_NetSrvGetInfo
1101 ********************************************************************/
1103 WERROR _srvsvc_NetSrvGetInfo(struct pipes_struct *p,
1104 struct srvsvc_NetSrvGetInfo *r)
1106 WERROR status = WERR_OK;
1108 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1110 if (!pipe_access_check(p)) {
1111 DEBUG(3, ("access denied to _srvsvc_NetSrvGetInfo\n"));
1112 return WERR_ACCESS_DENIED;
1115 switch (r->in.level) {
1117 /* Technically level 102 should only be available to
1118 Administrators but there isn't anything super-secret
1119 here, as most of it is made up. */
1121 case 102: {
1122 struct srvsvc_NetSrvInfo102 *info102;
1124 info102 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1125 if (!info102) {
1126 return WERR_NOMEM;
1129 info102->platform_id = PLATFORM_ID_NT;
1130 info102->server_name = lp_netbios_name();
1131 info102->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1132 info102->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1133 info102->server_type = lp_default_server_announce();
1134 info102->comment = string_truncate(lp_server_string(talloc_tos()),
1135 MAX_SERVER_STRING_LENGTH);
1136 info102->users = 0xffffffff;
1137 info102->disc = 0xf;
1138 info102->hidden = 0;
1139 info102->announce = 240;
1140 info102->anndelta = 3000;
1141 info102->licenses = 100000;
1142 info102->userpath = "C:\\";
1144 r->out.info->info102 = info102;
1145 break;
1147 case 101: {
1148 struct srvsvc_NetSrvInfo101 *info101;
1150 info101 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1151 if (!info101) {
1152 return WERR_NOMEM;
1155 info101->platform_id = PLATFORM_ID_NT;
1156 info101->server_name = lp_netbios_name();
1157 info101->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
1158 info101->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
1159 info101->server_type = lp_default_server_announce();
1160 info101->comment = string_truncate(lp_server_string(talloc_tos()),
1161 MAX_SERVER_STRING_LENGTH);
1163 r->out.info->info101 = info101;
1164 break;
1166 case 100: {
1167 struct srvsvc_NetSrvInfo100 *info100;
1169 info100 = talloc(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1170 if (!info100) {
1171 return WERR_NOMEM;
1174 info100->platform_id = PLATFORM_ID_NT;
1175 info100->server_name = lp_netbios_name();
1177 r->out.info->info100 = info100;
1179 break;
1181 default:
1182 status = WERR_UNKNOWN_LEVEL;
1183 break;
1186 DEBUG(5,("_srvsvc_NetSrvGetInfo: %d\n", __LINE__));
1188 return status;
1191 /*******************************************************************
1192 _srvsvc_NetSrvSetInfo
1193 ********************************************************************/
1195 WERROR _srvsvc_NetSrvSetInfo(struct pipes_struct *p,
1196 struct srvsvc_NetSrvSetInfo *r)
1198 WERROR status = WERR_OK;
1200 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1202 /* Set up the net server set info structure. */
1204 DEBUG(5,("_srvsvc_NetSrvSetInfo: %d\n", __LINE__));
1206 return status;
1209 /*******************************************************************
1210 _srvsvc_NetConnEnum
1211 ********************************************************************/
1213 WERROR _srvsvc_NetConnEnum(struct pipes_struct *p,
1214 struct srvsvc_NetConnEnum *r)
1216 WERROR werr;
1218 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1220 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1221 p->session_info->security_token)) {
1222 DEBUG(1, ("Enumerating connections only allowed for "
1223 "administrators\n"));
1224 return WERR_ACCESS_DENIED;
1227 switch (r->in.info_ctr->level) {
1228 case 0:
1229 werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0,
1230 r->in.resume_handle,
1231 r->out.totalentries);
1232 break;
1233 case 1:
1234 werr = init_srv_conn_info_1(r->in.info_ctr->ctr.ctr1,
1235 r->in.resume_handle,
1236 r->out.totalentries);
1237 break;
1238 default:
1239 return WERR_UNKNOWN_LEVEL;
1242 DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__));
1244 return werr;
1247 /*******************************************************************
1248 _srvsvc_NetSessEnum
1249 ********************************************************************/
1251 WERROR _srvsvc_NetSessEnum(struct pipes_struct *p,
1252 struct srvsvc_NetSessEnum *r)
1254 WERROR werr;
1256 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1258 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
1259 p->session_info->security_token)) {
1260 DEBUG(1, ("Enumerating sessions only allowed for "
1261 "administrators\n"));
1262 return WERR_ACCESS_DENIED;
1265 switch (r->in.info_ctr->level) {
1266 case 0:
1267 werr = init_srv_sess_info_0(p,
1268 r->in.info_ctr->ctr.ctr0,
1269 r->in.resume_handle,
1270 r->out.totalentries);
1271 break;
1272 case 1:
1273 werr = init_srv_sess_info_1(p,
1274 r->in.info_ctr->ctr.ctr1,
1275 r->in.resume_handle,
1276 r->out.totalentries);
1277 break;
1278 default:
1279 return WERR_UNKNOWN_LEVEL;
1282 DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__));
1284 return werr;
1287 /*******************************************************************
1288 _srvsvc_NetSessDel
1289 ********************************************************************/
1291 WERROR _srvsvc_NetSessDel(struct pipes_struct *p,
1292 struct srvsvc_NetSessDel *r)
1294 struct sessionid *session_list;
1295 int num_sessions, snum;
1296 const char *username;
1297 const char *machine;
1298 bool not_root = False;
1299 WERROR werr;
1301 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1303 werr = WERR_ACCESS_DENIED;
1305 /* fail out now if you are not root or not a domain admin */
1307 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1308 ( ! nt_token_check_domain_rid(p->session_info->security_token,
1309 DOMAIN_RID_ADMINS))) {
1311 goto done;
1314 username = r->in.user;
1315 machine = r->in.client;
1317 /* strip leading backslashes if any */
1318 if (machine && machine[0] == '\\' && machine[1] == '\\') {
1319 machine += 2;
1322 num_sessions = find_sessions(p->mem_ctx, username, machine,
1323 &session_list);
1325 for (snum = 0; snum < num_sessions; snum++) {
1327 NTSTATUS ntstat;
1329 if (p->session_info->unix_token->uid != sec_initial_uid()) {
1330 not_root = True;
1331 become_root();
1334 ntstat = messaging_send(p->msg_ctx,
1335 session_list[snum].pid,
1336 MSG_SHUTDOWN, &data_blob_null);
1338 if (NT_STATUS_IS_OK(ntstat))
1339 werr = WERR_OK;
1341 if (not_root)
1342 unbecome_root();
1345 DEBUG(5,("_srvsvc_NetSessDel: %d\n", __LINE__));
1347 done:
1349 return werr;
1352 /*******************************************************************
1353 _srvsvc_NetShareEnumAll
1354 ********************************************************************/
1356 WERROR _srvsvc_NetShareEnumAll(struct pipes_struct *p,
1357 struct srvsvc_NetShareEnumAll *r)
1359 WERROR werr;
1361 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1363 if (!pipe_access_check(p)) {
1364 DEBUG(3, ("access denied to _srvsvc_NetShareEnumAll\n"));
1365 return WERR_ACCESS_DENIED;
1368 /* Create the list of shares for the response. */
1369 werr = init_srv_share_info_ctr(p,
1370 r->in.info_ctr,
1371 r->in.resume_handle,
1372 r->out.totalentries,
1373 true);
1375 DEBUG(5,("_srvsvc_NetShareEnumAll: %d\n", __LINE__));
1377 return werr;
1380 /*******************************************************************
1381 _srvsvc_NetShareEnum
1382 ********************************************************************/
1384 WERROR _srvsvc_NetShareEnum(struct pipes_struct *p,
1385 struct srvsvc_NetShareEnum *r)
1387 WERROR werr;
1389 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1391 if (!pipe_access_check(p)) {
1392 DEBUG(3, ("access denied to _srvsvc_NetShareEnum\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 false);
1403 DEBUG(5,("_srvsvc_NetShareEnum: %d\n", __LINE__));
1405 return werr;
1408 /*******************************************************************
1409 _srvsvc_NetShareGetInfo
1410 ********************************************************************/
1412 WERROR _srvsvc_NetShareGetInfo(struct pipes_struct *p,
1413 struct srvsvc_NetShareGetInfo *r)
1415 WERROR status = WERR_OK;
1416 char *share_name = NULL;
1417 int snum;
1418 union srvsvc_NetShareInfo *info = r->out.info;
1420 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1422 if (!r->in.share_name) {
1423 return WERR_INVALID_NAME;
1426 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1427 if (!share_name) {
1428 return WERR_NOMEM;
1430 if (snum < 0) {
1431 return WERR_INVALID_NAME;
1434 switch (r->in.level) {
1435 case 0:
1436 info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1437 W_ERROR_HAVE_NO_MEMORY(info->info0);
1438 init_srv_share_info_0(p, info->info0, snum);
1439 break;
1440 case 1:
1441 info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1442 W_ERROR_HAVE_NO_MEMORY(info->info1);
1443 init_srv_share_info_1(p, info->info1, snum);
1444 break;
1445 case 2:
1446 info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1447 W_ERROR_HAVE_NO_MEMORY(info->info2);
1448 init_srv_share_info_2(p, info->info2, snum);
1449 info->info2->current_users =
1450 count_current_connections(info->info2->name, false);
1451 break;
1452 case 501:
1453 info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1454 W_ERROR_HAVE_NO_MEMORY(info->info501);
1455 init_srv_share_info_501(p, info->info501, snum);
1456 break;
1457 case 502:
1458 info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1459 W_ERROR_HAVE_NO_MEMORY(info->info502);
1460 init_srv_share_info_502(p, info->info502, snum);
1461 break;
1462 case 1004:
1463 info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1464 W_ERROR_HAVE_NO_MEMORY(info->info1004);
1465 init_srv_share_info_1004(p, info->info1004, snum);
1466 break;
1467 case 1005:
1468 info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1469 W_ERROR_HAVE_NO_MEMORY(info->info1005);
1470 init_srv_share_info_1005(p, info->info1005, snum);
1471 break;
1472 case 1006:
1473 info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1474 W_ERROR_HAVE_NO_MEMORY(info->info1006);
1475 init_srv_share_info_1006(p, info->info1006, snum);
1476 break;
1477 case 1007:
1478 info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1479 W_ERROR_HAVE_NO_MEMORY(info->info1007);
1480 init_srv_share_info_1007(p, info->info1007, snum);
1481 break;
1482 case 1501:
1483 init_srv_share_info_1501(p, &info->info1501, snum);
1484 break;
1485 default:
1486 DEBUG(5,("_srvsvc_NetShareGetInfo: unsupported switch value %d\n",
1487 r->in.level));
1488 status = WERR_UNKNOWN_LEVEL;
1489 break;
1492 DEBUG(5,("_srvsvc_NetShareGetInfo: %d\n", __LINE__));
1494 return status;
1497 /*******************************************************************
1498 _srvsvc_NetShareSetInfo. Modify share details.
1499 ********************************************************************/
1501 WERROR _srvsvc_NetShareSetInfo(struct pipes_struct *p,
1502 struct srvsvc_NetShareSetInfo *r)
1504 char *command = NULL;
1505 char *share_name = NULL;
1506 char *comment = NULL;
1507 const char *pathname = NULL;
1508 int type;
1509 int snum;
1510 int ret;
1511 char *path = NULL;
1512 struct security_descriptor *psd = NULL;
1513 bool is_disk_op = False;
1514 const char *csc_policy = NULL;
1515 bool csc_policy_changed = false;
1516 const char *csc_policies[] = {"manual", "documents", "programs",
1517 "disable"};
1518 uint32_t client_csc_policy;
1519 int max_connections = 0;
1520 TALLOC_CTX *ctx = p->mem_ctx;
1521 union srvsvc_NetShareInfo *info = r->in.info;
1523 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1525 if (!r->in.share_name) {
1526 return WERR_INVALID_NAME;
1529 if (r->out.parm_error) {
1530 *r->out.parm_error = 0;
1533 if ( strequal(r->in.share_name,"IPC$")
1534 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1535 || strequal(r->in.share_name,"global") )
1537 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s cannot be "
1538 "modified by a remote user.\n",
1539 r->in.share_name ));
1540 return WERR_ACCESS_DENIED;
1543 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1544 if (!share_name) {
1545 return WERR_NOMEM;
1548 /* Does this share exist ? */
1549 if (snum < 0)
1550 return WERR_NET_NAME_NOT_FOUND;
1552 /* No change to printer shares. */
1553 if (lp_printable(snum))
1554 return WERR_ACCESS_DENIED;
1556 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1558 /* fail out now if you are not root and not a disk op */
1560 if ( p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op ) {
1561 DEBUG(2,("_srvsvc_NetShareSetInfo: uid %u doesn't have the "
1562 "SeDiskOperatorPrivilege privilege needed to modify "
1563 "share %s\n",
1564 (unsigned int)p->session_info->unix_token->uid,
1565 share_name ));
1566 return WERR_ACCESS_DENIED;
1569 max_connections = lp_max_connections(snum);
1570 csc_policy = csc_policies[lp_csc_policy(snum)];
1572 switch (r->in.level) {
1573 case 1:
1574 pathname = lp_path(ctx, snum);
1575 comment = talloc_strdup(ctx, info->info1->comment);
1576 type = info->info1->type;
1577 psd = NULL;
1578 break;
1579 case 2:
1580 comment = talloc_strdup(ctx, info->info2->comment);
1581 pathname = info->info2->path;
1582 type = info->info2->type;
1583 max_connections = (info->info2->max_users == (uint32_t)-1) ?
1584 0 : info->info2->max_users;
1585 psd = NULL;
1586 break;
1587 #if 0
1588 /* not supported on set but here for completeness */
1589 case 501:
1590 comment = talloc_strdup(ctx, info->info501->comment);
1591 type = info->info501->type;
1592 psd = NULL;
1593 break;
1594 #endif
1595 case 502:
1596 comment = talloc_strdup(ctx, info->info502->comment);
1597 pathname = info->info502->path;
1598 type = info->info502->type;
1599 psd = info->info502->sd_buf.sd;
1600 map_generic_share_sd_bits(psd);
1601 break;
1602 case 1004:
1603 pathname = lp_path(ctx, snum);
1604 comment = talloc_strdup(ctx, info->info1004->comment);
1605 type = STYPE_DISKTREE;
1606 break;
1607 case 1005:
1608 /* XP re-sets the csc policy even if it wasn't changed by the
1609 user, so we must compare it to see if it's what is set in
1610 smb.conf, so that we can contine other ops like setting
1611 ACLs on a share */
1612 client_csc_policy = (info->info1005->dfs_flags &
1613 SHARE_1005_CSC_POLICY_MASK) >>
1614 SHARE_1005_CSC_POLICY_SHIFT;
1616 if (client_csc_policy == lp_csc_policy(snum))
1617 return WERR_OK;
1618 else {
1619 csc_policy = csc_policies[client_csc_policy];
1620 csc_policy_changed = true;
1623 pathname = lp_path(ctx, snum);
1624 comment = lp_comment(ctx, snum);
1625 type = STYPE_DISKTREE;
1626 break;
1627 case 1006:
1628 case 1007:
1629 return WERR_ACCESS_DENIED;
1630 case 1501:
1631 pathname = lp_path(ctx, snum);
1632 comment = lp_comment(ctx, snum);
1633 psd = info->info1501->sd;
1634 map_generic_share_sd_bits(psd);
1635 type = STYPE_DISKTREE;
1636 break;
1637 default:
1638 DEBUG(5,("_srvsvc_NetShareSetInfo: unsupported switch value %d\n",
1639 r->in.level));
1640 return WERR_UNKNOWN_LEVEL;
1643 /* We can only modify disk shares. */
1644 if (type != STYPE_DISKTREE) {
1645 DEBUG(5,("_srvsvc_NetShareSetInfo: share %s is not a "
1646 "disk share\n",
1647 share_name ));
1648 return WERR_ACCESS_DENIED;
1651 if (comment == NULL) {
1652 return WERR_NOMEM;
1655 /* Check if the pathname is valid. */
1656 if (!(path = valid_share_pathname(p->mem_ctx, pathname ))) {
1657 DEBUG(5,("_srvsvc_NetShareSetInfo: invalid pathname %s\n",
1658 pathname ));
1659 return WERR_OBJECT_PATH_INVALID;
1662 /* Ensure share name, pathname and comment don't contain '"' characters. */
1663 string_replace(share_name, '"', ' ');
1664 string_replace(path, '"', ' ');
1665 string_replace(comment, '"', ' ');
1667 DEBUG(10,("_srvsvc_NetShareSetInfo: change share command = %s\n",
1668 lp_change_share_command(talloc_tos()) ? lp_change_share_command(talloc_tos()) : "NULL" ));
1670 /* Only call modify function if something changed. */
1672 if (strcmp(path, lp_path(talloc_tos(), snum)) || strcmp(comment, lp_comment(talloc_tos(), snum))
1673 || (lp_max_connections(snum) != max_connections)
1674 || csc_policy_changed) {
1676 if (!lp_change_share_command(talloc_tos()) || !*lp_change_share_command(talloc_tos())) {
1677 DEBUG(10,("_srvsvc_NetShareSetInfo: No change share command\n"));
1678 return WERR_ACCESS_DENIED;
1681 command = talloc_asprintf(p->mem_ctx,
1682 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d \"%s\"",
1683 lp_change_share_command(talloc_tos()),
1684 get_dyn_CONFIGFILE(),
1685 share_name,
1686 path,
1687 comment ? comment : "",
1688 max_connections,
1689 csc_policy);
1690 if (!command) {
1691 return WERR_NOMEM;
1694 DEBUG(10,("_srvsvc_NetShareSetInfo: Running [%s]\n", command ));
1696 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1698 if (is_disk_op)
1699 become_root();
1701 if ( (ret = smbrun(command, NULL)) == 0 ) {
1702 /* Tell everyone we updated smb.conf. */
1703 message_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED,
1704 NULL, 0, NULL);
1707 if ( is_disk_op )
1708 unbecome_root();
1710 /********* END SeDiskOperatorPrivilege BLOCK *********/
1712 DEBUG(3,("_srvsvc_NetShareSetInfo: Running [%s] returned (%d)\n",
1713 command, ret ));
1715 TALLOC_FREE(command);
1717 if ( ret != 0 )
1718 return WERR_ACCESS_DENIED;
1719 } else {
1720 DEBUG(10,("_srvsvc_NetShareSetInfo: No change to share name (%s)\n",
1721 share_name ));
1724 /* Replace SD if changed. */
1725 if (psd) {
1726 struct security_descriptor *old_sd;
1727 size_t sd_size;
1729 old_sd = get_share_security(p->mem_ctx, lp_servicename(talloc_tos(), snum), &sd_size);
1731 if (old_sd && !security_descriptor_equal(old_sd, psd)) {
1732 if (!set_share_security(share_name, psd))
1733 DEBUG(0,("_srvsvc_NetShareSetInfo: Failed to change security info in share %s.\n",
1734 share_name ));
1738 DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__));
1740 return WERR_OK;
1743 /*******************************************************************
1744 _srvsvc_NetShareAdd.
1745 Call 'add_share_command "sharename" "pathname"
1746 "comment" "max connections = "
1747 ********************************************************************/
1749 WERROR _srvsvc_NetShareAdd(struct pipes_struct *p,
1750 struct srvsvc_NetShareAdd *r)
1752 char *command = NULL;
1753 char *share_name_in = NULL;
1754 char *share_name = NULL;
1755 char *comment = NULL;
1756 char *pathname = NULL;
1757 int type;
1758 int snum;
1759 int ret;
1760 char *path;
1761 struct security_descriptor *psd = NULL;
1762 bool is_disk_op;
1763 int max_connections = 0;
1764 TALLOC_CTX *ctx = p->mem_ctx;
1766 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1768 if (r->out.parm_error) {
1769 *r->out.parm_error = 0;
1772 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1774 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op )
1775 return WERR_ACCESS_DENIED;
1777 if (!lp_add_share_command(talloc_tos()) || !*lp_add_share_command(talloc_tos())) {
1778 DEBUG(10,("_srvsvc_NetShareAdd: No add share command\n"));
1779 return WERR_ACCESS_DENIED;
1782 switch (r->in.level) {
1783 case 0:
1784 /* No path. Not enough info in a level 0 to do anything. */
1785 return WERR_ACCESS_DENIED;
1786 case 1:
1787 /* Not enough info in a level 1 to do anything. */
1788 return WERR_ACCESS_DENIED;
1789 case 2:
1790 share_name_in = talloc_strdup(ctx, r->in.info->info2->name);
1791 comment = talloc_strdup(ctx, r->in.info->info2->comment);
1792 pathname = talloc_strdup(ctx, r->in.info->info2->path);
1793 max_connections = (r->in.info->info2->max_users == (uint32_t)-1) ?
1794 0 : r->in.info->info2->max_users;
1795 type = r->in.info->info2->type;
1796 break;
1797 case 501:
1798 /* No path. Not enough info in a level 501 to do anything. */
1799 return WERR_ACCESS_DENIED;
1800 case 502:
1801 share_name_in = talloc_strdup(ctx, r->in.info->info502->name);
1802 comment = talloc_strdup(ctx, r->in.info->info502->comment);
1803 pathname = talloc_strdup(ctx, r->in.info->info502->path);
1804 max_connections = (r->in.info->info502->max_users == (uint32_t)-1) ?
1805 0 : r->in.info->info502->max_users;
1806 type = r->in.info->info502->type;
1807 psd = r->in.info->info502->sd_buf.sd;
1808 map_generic_share_sd_bits(psd);
1809 break;
1811 /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
1813 case 1004:
1814 case 1005:
1815 case 1006:
1816 case 1007:
1817 return WERR_ACCESS_DENIED;
1818 case 1501:
1819 /* DFS only level. */
1820 return WERR_ACCESS_DENIED;
1821 default:
1822 DEBUG(5,("_srvsvc_NetShareAdd: unsupported switch value %d\n",
1823 r->in.level));
1824 return WERR_UNKNOWN_LEVEL;
1827 /* check for invalid share names */
1829 if (!share_name_in || !validate_net_name(share_name_in,
1830 INVALID_SHARENAME_CHARS,
1831 strlen(share_name_in))) {
1832 DEBUG(5,("_srvsvc_NetShareAdd: Bad sharename \"%s\"\n",
1833 share_name_in ? share_name_in : ""));
1834 return WERR_INVALID_NAME;
1837 if (strequal(share_name_in,"IPC$") || strequal(share_name_in,"global")
1838 || (lp_enable_asu_support() &&
1839 strequal(share_name_in,"ADMIN$"))) {
1840 return WERR_ACCESS_DENIED;
1843 snum = find_service(ctx, share_name_in, &share_name);
1844 if (!share_name) {
1845 return WERR_NOMEM;
1848 /* Share already exists. */
1849 if (snum >= 0) {
1850 return WERR_FILE_EXISTS;
1853 /* We can only add disk shares. */
1854 if (type != STYPE_DISKTREE) {
1855 return WERR_ACCESS_DENIED;
1858 /* Check if the pathname is valid. */
1859 if (!(path = valid_share_pathname(p->mem_ctx, pathname))) {
1860 return WERR_OBJECT_PATH_INVALID;
1863 /* Ensure share name, pathname and comment don't contain '"' characters. */
1864 string_replace(share_name_in, '"', ' ');
1865 string_replace(share_name, '"', ' ');
1866 string_replace(path, '"', ' ');
1867 if (comment) {
1868 string_replace(comment, '"', ' ');
1871 command = talloc_asprintf(ctx,
1872 "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1873 lp_add_share_command(talloc_tos()),
1874 get_dyn_CONFIGFILE(),
1875 share_name_in,
1876 path,
1877 comment ? comment : "",
1878 max_connections);
1879 if (!command) {
1880 return WERR_NOMEM;
1883 DEBUG(10,("_srvsvc_NetShareAdd: Running [%s]\n", command ));
1885 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1887 if ( is_disk_op )
1888 become_root();
1890 /* FIXME: use libnetconf here - gd */
1892 if ( (ret = smbrun(command, NULL)) == 0 ) {
1893 /* Tell everyone we updated smb.conf. */
1894 message_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0,
1895 NULL);
1898 if ( is_disk_op )
1899 unbecome_root();
1901 /********* END SeDiskOperatorPrivilege BLOCK *********/
1903 DEBUG(3,("_srvsvc_NetShareAdd: Running [%s] returned (%d)\n",
1904 command, ret ));
1906 TALLOC_FREE(command);
1908 if ( ret != 0 )
1909 return WERR_ACCESS_DENIED;
1911 if (psd) {
1912 /* Note we use share_name here, not share_name_in as
1913 we need a canonicalized name for setting security. */
1914 if (!set_share_security(share_name, psd)) {
1915 DEBUG(0,("_srvsvc_NetShareAdd: Failed to add security info to share %s.\n",
1916 share_name ));
1921 * We don't call reload_services() here, the message will
1922 * cause this to be done before the next packet is read
1923 * from the client. JRA.
1926 DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__));
1928 return WERR_OK;
1931 /*******************************************************************
1932 _srvsvc_NetShareDel
1933 Call "delete share command" with the share name as
1934 a parameter.
1935 ********************************************************************/
1937 WERROR _srvsvc_NetShareDel(struct pipes_struct *p,
1938 struct srvsvc_NetShareDel *r)
1940 char *command = NULL;
1941 char *share_name = NULL;
1942 int ret;
1943 int snum;
1944 bool is_disk_op;
1945 struct share_params *params;
1946 TALLOC_CTX *ctx = p->mem_ctx;
1948 DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__));
1950 if (!r->in.share_name) {
1951 return WERR_NET_NAME_NOT_FOUND;
1954 if ( strequal(r->in.share_name,"IPC$")
1955 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1956 || strequal(r->in.share_name,"global") )
1958 return WERR_ACCESS_DENIED;
1961 snum = find_service(talloc_tos(), r->in.share_name, &share_name);
1962 if (!share_name) {
1963 return WERR_NOMEM;
1966 if (snum < 0) {
1967 return WERR_NO_SUCH_SHARE;
1970 if (!(params = get_share_params(p->mem_ctx, share_name))) {
1971 return WERR_NO_SUCH_SHARE;
1974 /* No change to printer shares. */
1975 if (lp_printable(snum))
1976 return WERR_ACCESS_DENIED;
1978 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
1980 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op )
1981 return WERR_ACCESS_DENIED;
1983 if (!lp_delete_share_command(talloc_tos()) || !*lp_delete_share_command(talloc_tos())) {
1984 DEBUG(10,("_srvsvc_NetShareDel: No delete share command\n"));
1985 return WERR_ACCESS_DENIED;
1988 command = talloc_asprintf(ctx,
1989 "%s \"%s\" \"%s\"",
1990 lp_delete_share_command(talloc_tos()),
1991 get_dyn_CONFIGFILE(),
1992 lp_servicename(talloc_tos(), snum));
1993 if (!command) {
1994 return WERR_NOMEM;
1997 DEBUG(10,("_srvsvc_NetShareDel: Running [%s]\n", command ));
1999 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
2001 if ( is_disk_op )
2002 become_root();
2004 if ( (ret = smbrun(command, NULL)) == 0 ) {
2005 /* Tell everyone we updated smb.conf. */
2006 message_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0,
2007 NULL);
2010 if ( is_disk_op )
2011 unbecome_root();
2013 /********* END SeDiskOperatorPrivilege BLOCK *********/
2015 DEBUG(3,("_srvsvc_NetShareDel: Running [%s] returned (%d)\n", command, ret ));
2017 if ( ret != 0 )
2018 return WERR_ACCESS_DENIED;
2020 /* Delete the SD in the database. */
2021 delete_share_security(lp_servicename(talloc_tos(), params->service));
2023 lp_killservice(params->service);
2025 return WERR_OK;
2028 /*******************************************************************
2029 _srvsvc_NetShareDelSticky
2030 ********************************************************************/
2032 WERROR _srvsvc_NetShareDelSticky(struct pipes_struct *p,
2033 struct srvsvc_NetShareDelSticky *r)
2035 struct srvsvc_NetShareDel q;
2037 DEBUG(5,("_srvsvc_NetShareDelSticky: %d\n", __LINE__));
2039 q.in.server_unc = r->in.server_unc;
2040 q.in.share_name = r->in.share_name;
2041 q.in.reserved = r->in.reserved;
2043 return _srvsvc_NetShareDel(p, &q);
2046 /*******************************************************************
2047 _srvsvc_NetRemoteTOD
2048 ********************************************************************/
2050 WERROR _srvsvc_NetRemoteTOD(struct pipes_struct *p,
2051 struct srvsvc_NetRemoteTOD *r)
2053 struct srvsvc_NetRemoteTODInfo *tod;
2054 struct tm *t;
2055 time_t unixdate = time(NULL);
2057 /* We do this call first as if we do it *after* the gmtime call
2058 it overwrites the pointed-to values. JRA */
2060 uint32 zone = get_time_zone(unixdate)/60;
2062 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2064 if ( !(tod = talloc_zero(p->mem_ctx, struct srvsvc_NetRemoteTODInfo)) )
2065 return WERR_NOMEM;
2067 *r->out.info = tod;
2069 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2071 t = gmtime(&unixdate);
2073 /* set up the */
2074 tod->elapsed = unixdate;
2075 tod->msecs = 0;
2076 tod->hours = t->tm_hour;
2077 tod->mins = t->tm_min;
2078 tod->secs = t->tm_sec;
2079 tod->hunds = 0;
2080 tod->timezone = zone;
2081 tod->tinterval = 10000;
2082 tod->day = t->tm_mday;
2083 tod->month = t->tm_mon + 1;
2084 tod->year = 1900+t->tm_year;
2085 tod->weekday = t->tm_wday;
2087 DEBUG(5,("_srvsvc_NetRemoteTOD: %d\n", __LINE__));
2089 return WERR_OK;
2092 /***********************************************************************************
2093 _srvsvc_NetGetFileSecurity
2094 Win9x NT tools get security descriptor.
2095 ***********************************************************************************/
2097 WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
2098 struct srvsvc_NetGetFileSecurity *r)
2100 struct smb_filename *smb_fname = NULL;
2101 size_t sd_size;
2102 char *servicename = NULL;
2103 SMB_STRUCT_STAT st;
2104 NTSTATUS nt_status;
2105 WERROR werr;
2106 connection_struct *conn = NULL;
2107 struct sec_desc_buf *sd_buf = NULL;
2108 files_struct *fsp = NULL;
2109 int snum;
2110 char *oldcwd = NULL;
2112 ZERO_STRUCT(st);
2114 if (!r->in.share) {
2115 werr = WERR_NET_NAME_NOT_FOUND;
2116 goto error_exit;
2118 snum = find_service(talloc_tos(), r->in.share, &servicename);
2119 if (!servicename) {
2120 werr = WERR_NOMEM;
2121 goto error_exit;
2123 if (snum == -1) {
2124 DEBUG(10, ("Could not find service %s\n", servicename));
2125 werr = WERR_NET_NAME_NOT_FOUND;
2126 goto error_exit;
2129 nt_status = create_conn_struct_cwd(talloc_tos(),
2130 server_event_context(),
2131 server_messaging_context(),
2132 &conn,
2133 snum, lp_path(talloc_tos(), snum),
2134 p->session_info, &oldcwd);
2135 if (!NT_STATUS_IS_OK(nt_status)) {
2136 DEBUG(10, ("create_conn_struct failed: %s\n",
2137 nt_errstr(nt_status)));
2138 werr = ntstatus_to_werror(nt_status);
2139 goto error_exit;
2142 nt_status = filename_convert(talloc_tos(),
2143 conn,
2144 false,
2145 r->in.file,
2147 NULL,
2148 &smb_fname);
2149 if (!NT_STATUS_IS_OK(nt_status)) {
2150 werr = ntstatus_to_werror(nt_status);
2151 goto error_exit;
2154 nt_status = SMB_VFS_CREATE_FILE(
2155 conn, /* conn */
2156 NULL, /* req */
2157 0, /* root_dir_fid */
2158 smb_fname, /* fname */
2159 FILE_READ_ATTRIBUTES, /* access_mask */
2160 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2161 FILE_OPEN, /* create_disposition*/
2162 0, /* create_options */
2163 0, /* file_attributes */
2164 INTERNAL_OPEN_ONLY, /* oplock_request */
2165 0, /* allocation_size */
2166 0, /* private_flags */
2167 NULL, /* sd */
2168 NULL, /* ea_list */
2169 &fsp, /* result */
2170 NULL); /* pinfo */
2172 if (!NT_STATUS_IS_OK(nt_status)) {
2173 DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n",
2174 smb_fname_str_dbg(smb_fname)));
2175 werr = ntstatus_to_werror(nt_status);
2176 goto error_exit;
2179 sd_buf = talloc_zero(p->mem_ctx, struct sec_desc_buf);
2180 if (!sd_buf) {
2181 werr = WERR_NOMEM;
2182 goto error_exit;
2185 nt_status = SMB_VFS_FGET_NT_ACL(fsp,
2186 (SECINFO_OWNER
2187 |SECINFO_GROUP
2188 |SECINFO_DACL), sd_buf, &sd_buf->sd);
2190 if (!NT_STATUS_IS_OK(nt_status)) {
2191 DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL "
2192 "for file %s\n", smb_fname_str_dbg(smb_fname)));
2193 werr = ntstatus_to_werror(nt_status);
2194 TALLOC_FREE(sd_buf);
2195 goto error_exit;
2198 if (sd_buf->sd->dacl) {
2199 sd_buf->sd->dacl->revision = NT4_ACL_REVISION;
2202 sd_size = ndr_size_security_descriptor(sd_buf->sd, 0);
2204 sd_buf->sd_size = sd_size;
2206 *r->out.sd_buf = sd_buf;
2208 close_file(NULL, fsp, NORMAL_CLOSE);
2209 vfs_ChDir(conn, oldcwd);
2210 SMB_VFS_DISCONNECT(conn);
2211 conn_free(conn);
2212 werr = WERR_OK;
2213 goto done;
2215 error_exit:
2217 if (fsp) {
2218 close_file(NULL, fsp, NORMAL_CLOSE);
2221 if (oldcwd) {
2222 vfs_ChDir(conn, oldcwd);
2225 if (conn) {
2226 SMB_VFS_DISCONNECT(conn);
2227 conn_free(conn);
2230 done:
2232 TALLOC_FREE(smb_fname);
2234 return werr;
2237 /***********************************************************************************
2238 _srvsvc_NetSetFileSecurity
2239 Win9x NT tools set security descriptor.
2240 ***********************************************************************************/
2242 WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
2243 struct srvsvc_NetSetFileSecurity *r)
2245 struct smb_filename *smb_fname = NULL;
2246 char *servicename = NULL;
2247 files_struct *fsp = NULL;
2248 SMB_STRUCT_STAT st;
2249 NTSTATUS nt_status;
2250 WERROR werr;
2251 connection_struct *conn = NULL;
2252 int snum;
2253 char *oldcwd = NULL;
2254 struct security_descriptor *psd = NULL;
2255 uint32_t security_info_sent = 0;
2257 ZERO_STRUCT(st);
2259 if (!r->in.share) {
2260 werr = WERR_NET_NAME_NOT_FOUND;
2261 goto error_exit;
2264 snum = find_service(talloc_tos(), r->in.share, &servicename);
2265 if (!servicename) {
2266 werr = WERR_NOMEM;
2267 goto error_exit;
2270 if (snum == -1) {
2271 DEBUG(10, ("Could not find service %s\n", servicename));
2272 werr = WERR_NET_NAME_NOT_FOUND;
2273 goto error_exit;
2276 nt_status = create_conn_struct_cwd(talloc_tos(),
2277 server_event_context(),
2278 server_messaging_context(),
2279 &conn,
2280 snum, lp_path(talloc_tos(), snum),
2281 p->session_info, &oldcwd);
2282 if (!NT_STATUS_IS_OK(nt_status)) {
2283 DEBUG(10, ("create_conn_struct failed: %s\n",
2284 nt_errstr(nt_status)));
2285 werr = ntstatus_to_werror(nt_status);
2286 goto error_exit;
2289 nt_status = filename_convert(talloc_tos(),
2290 conn,
2291 false,
2292 r->in.file,
2294 NULL,
2295 &smb_fname);
2296 if (!NT_STATUS_IS_OK(nt_status)) {
2297 werr = ntstatus_to_werror(nt_status);
2298 goto error_exit;
2301 nt_status = SMB_VFS_CREATE_FILE(
2302 conn, /* conn */
2303 NULL, /* req */
2304 0, /* root_dir_fid */
2305 smb_fname, /* fname */
2306 FILE_WRITE_ATTRIBUTES, /* access_mask */
2307 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
2308 FILE_OPEN, /* create_disposition*/
2309 0, /* create_options */
2310 0, /* file_attributes */
2311 INTERNAL_OPEN_ONLY, /* oplock_request */
2312 0, /* allocation_size */
2313 0, /* private_flags */
2314 NULL, /* sd */
2315 NULL, /* ea_list */
2316 &fsp, /* result */
2317 NULL); /* pinfo */
2319 if (!NT_STATUS_IS_OK(nt_status)) {
2320 DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n",
2321 smb_fname_str_dbg(smb_fname)));
2322 werr = ntstatus_to_werror(nt_status);
2323 goto error_exit;
2326 psd = r->in.sd_buf->sd;
2327 security_info_sent = r->in.securityinformation;
2329 nt_status = set_sd(fsp, psd, security_info_sent);
2331 if (!NT_STATUS_IS_OK(nt_status) ) {
2332 DEBUG(3,("_srvsvc_NetSetFileSecurity: Unable to set NT ACL "
2333 "on file %s\n", r->in.share));
2334 werr = WERR_ACCESS_DENIED;
2335 goto error_exit;
2338 close_file(NULL, fsp, NORMAL_CLOSE);
2339 vfs_ChDir(conn, oldcwd);
2340 SMB_VFS_DISCONNECT(conn);
2341 conn_free(conn);
2342 werr = WERR_OK;
2343 goto done;
2345 error_exit:
2347 if (fsp) {
2348 close_file(NULL, fsp, NORMAL_CLOSE);
2351 if (oldcwd) {
2352 vfs_ChDir(conn, oldcwd);
2355 if (conn) {
2356 SMB_VFS_DISCONNECT(conn);
2357 conn_free(conn);
2360 done:
2361 TALLOC_FREE(smb_fname);
2363 return werr;
2366 /***********************************************************************************
2367 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2368 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2369 These disks would the disks listed by this function.
2370 Users could then create shares relative to these disks. Watch out for moving these disks around.
2371 "Nigel Williams" <nigel@veritas.com>.
2372 ***********************************************************************************/
2374 static const char *server_disks[] = {"C:"};
2376 static uint32 get_server_disk_count(void)
2378 return sizeof(server_disks)/sizeof(server_disks[0]);
2381 static uint32 init_server_disk_enum(uint32 *resume)
2383 uint32 server_disk_count = get_server_disk_count();
2385 /*resume can be an offset into the list for now*/
2387 if(*resume & 0x80000000)
2388 *resume = 0;
2390 if(*resume > server_disk_count)
2391 *resume = server_disk_count;
2393 return server_disk_count - *resume;
2396 static const char *next_server_disk_enum(uint32 *resume)
2398 const char *disk;
2400 if(init_server_disk_enum(resume) == 0)
2401 return NULL;
2403 disk = server_disks[*resume];
2405 (*resume)++;
2407 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2409 return disk;
2412 /********************************************************************
2413 _srvsvc_NetDiskEnum
2414 ********************************************************************/
2416 WERROR _srvsvc_NetDiskEnum(struct pipes_struct *p,
2417 struct srvsvc_NetDiskEnum *r)
2419 uint32 i;
2420 const char *disk_name;
2421 TALLOC_CTX *ctx = p->mem_ctx;
2422 WERROR werr;
2423 uint32_t resume = r->in.resume_handle ? *r->in.resume_handle : 0;
2425 werr = WERR_OK;
2427 *r->out.totalentries = init_server_disk_enum(&resume);
2429 r->out.info->disks = talloc_zero_array(ctx, struct srvsvc_NetDiskInfo0,
2430 MAX_SERVER_DISK_ENTRIES);
2431 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks);
2433 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2435 r->out.info->count = 0;
2437 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
2439 r->out.info->count++;
2441 /*copy disk name into a unicode string*/
2443 r->out.info->disks[i].disk = talloc_strdup(ctx, disk_name);
2444 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2447 /* add a terminating null string. Is this there if there is more data to come? */
2449 r->out.info->count++;
2451 r->out.info->disks[i].disk = talloc_strdup(ctx, "");
2452 W_ERROR_HAVE_NO_MEMORY(r->out.info->disks[i].disk);
2454 if (r->out.resume_handle) {
2455 *r->out.resume_handle = resume;
2458 return werr;
2461 /********************************************************************
2462 _srvsvc_NetNameValidate
2463 ********************************************************************/
2465 WERROR _srvsvc_NetNameValidate(struct pipes_struct *p,
2466 struct srvsvc_NetNameValidate *r)
2468 switch (r->in.name_type) {
2469 case 0x9:
2470 if (!validate_net_name(r->in.name, INVALID_SHARENAME_CHARS,
2471 strlen_m(r->in.name)))
2473 DEBUG(5,("_srvsvc_NetNameValidate: Bad sharename \"%s\"\n",
2474 r->in.name));
2475 return WERR_INVALID_NAME;
2477 break;
2479 default:
2480 return WERR_UNKNOWN_LEVEL;
2483 return WERR_OK;
2486 /*******************************************************************
2487 ********************************************************************/
2489 struct enum_file_close_state {
2490 struct srvsvc_NetFileClose *r;
2491 struct messaging_context *msg_ctx;
2494 static void enum_file_close_fn( const struct share_mode_entry *e,
2495 const char *sharepath, const char *fname,
2496 void *private_data )
2498 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
2499 struct enum_file_close_state *state =
2500 (struct enum_file_close_state *)private_data;
2501 uint32_t fid = (((uint32_t)(procid_to_pid(&e->pid))<<16) | e->share_file_id);
2503 if (fid != state->r->in.fid) {
2504 return; /* Not this file. */
2507 if (!process_exists(e->pid) ) {
2508 return;
2511 /* Ok - send the close message. */
2512 DEBUG(10,("enum_file_close_fn: request to close file %s, %s\n",
2513 sharepath,
2514 share_mode_str(talloc_tos(), 0, e) ));
2516 share_mode_entry_to_message(msg, e);
2518 state->r->out.result = ntstatus_to_werror(
2519 messaging_send_buf(state->msg_ctx,
2520 e->pid, MSG_SMB_CLOSE_FILE,
2521 (uint8 *)msg, sizeof(msg)));
2524 /********************************************************************
2525 Close a file given a 32-bit file id.
2526 ********************************************************************/
2528 WERROR _srvsvc_NetFileClose(struct pipes_struct *p,
2529 struct srvsvc_NetFileClose *r)
2531 struct enum_file_close_state state;
2532 bool is_disk_op;
2534 DEBUG(5,("_srvsvc_NetFileClose: %d\n", __LINE__));
2536 is_disk_op = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_DISK_OPERATOR);
2538 if (p->session_info->unix_token->uid != sec_initial_uid() && !is_disk_op) {
2539 return WERR_ACCESS_DENIED;
2542 /* enum_file_close_fn sends the close message to
2543 * the relevant smbd process. */
2545 r->out.result = WERR_BADFILE;
2546 state.r = r;
2547 state.msg_ctx = p->msg_ctx;
2548 share_mode_forall(enum_file_close_fn, &state);
2549 return r->out.result;
2552 /********************************************************************
2553 ********************************************************************/
2555 WERROR _srvsvc_NetCharDevEnum(struct pipes_struct *p,
2556 struct srvsvc_NetCharDevEnum *r)
2558 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2559 return WERR_NOT_SUPPORTED;
2562 WERROR _srvsvc_NetCharDevGetInfo(struct pipes_struct *p,
2563 struct srvsvc_NetCharDevGetInfo *r)
2565 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2566 return WERR_NOT_SUPPORTED;
2569 WERROR _srvsvc_NetCharDevControl(struct pipes_struct *p,
2570 struct srvsvc_NetCharDevControl *r)
2572 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2573 return WERR_NOT_SUPPORTED;
2576 WERROR _srvsvc_NetCharDevQEnum(struct pipes_struct *p,
2577 struct srvsvc_NetCharDevQEnum *r)
2579 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2580 return WERR_NOT_SUPPORTED;
2583 WERROR _srvsvc_NetCharDevQGetInfo(struct pipes_struct *p,
2584 struct srvsvc_NetCharDevQGetInfo *r)
2586 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2587 return WERR_NOT_SUPPORTED;
2590 WERROR _srvsvc_NetCharDevQSetInfo(struct pipes_struct *p,
2591 struct srvsvc_NetCharDevQSetInfo *r)
2593 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2594 return WERR_NOT_SUPPORTED;
2597 WERROR _srvsvc_NetCharDevQPurge(struct pipes_struct *p,
2598 struct srvsvc_NetCharDevQPurge *r)
2600 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2601 return WERR_NOT_SUPPORTED;
2604 WERROR _srvsvc_NetCharDevQPurgeSelf(struct pipes_struct *p,
2605 struct srvsvc_NetCharDevQPurgeSelf *r)
2607 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2608 return WERR_NOT_SUPPORTED;
2611 WERROR _srvsvc_NetFileGetInfo(struct pipes_struct *p,
2612 struct srvsvc_NetFileGetInfo *r)
2614 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2615 return WERR_NOT_SUPPORTED;
2618 WERROR _srvsvc_NetShareCheck(struct pipes_struct *p,
2619 struct srvsvc_NetShareCheck *r)
2621 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2622 return WERR_NOT_SUPPORTED;
2625 WERROR _srvsvc_NetServerStatisticsGet(struct pipes_struct *p,
2626 struct srvsvc_NetServerStatisticsGet *r)
2628 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2629 return WERR_NOT_SUPPORTED;
2632 WERROR _srvsvc_NetTransportAdd(struct pipes_struct *p,
2633 struct srvsvc_NetTransportAdd *r)
2635 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2636 return WERR_NOT_SUPPORTED;
2639 WERROR _srvsvc_NetTransportEnum(struct pipes_struct *p,
2640 struct srvsvc_NetTransportEnum *r)
2642 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2643 return WERR_NOT_SUPPORTED;
2646 WERROR _srvsvc_NetTransportDel(struct pipes_struct *p,
2647 struct srvsvc_NetTransportDel *r)
2649 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2650 return WERR_NOT_SUPPORTED;
2653 WERROR _srvsvc_NetSetServiceBits(struct pipes_struct *p,
2654 struct srvsvc_NetSetServiceBits *r)
2656 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2657 return WERR_NOT_SUPPORTED;
2660 WERROR _srvsvc_NetPathType(struct pipes_struct *p,
2661 struct srvsvc_NetPathType *r)
2663 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2664 return WERR_NOT_SUPPORTED;
2667 WERROR _srvsvc_NetPathCanonicalize(struct pipes_struct *p,
2668 struct srvsvc_NetPathCanonicalize *r)
2670 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2671 return WERR_NOT_SUPPORTED;
2674 WERROR _srvsvc_NetPathCompare(struct pipes_struct *p,
2675 struct srvsvc_NetPathCompare *r)
2677 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2678 return WERR_NOT_SUPPORTED;
2681 WERROR _srvsvc_NETRPRNAMECANONICALIZE(struct pipes_struct *p,
2682 struct srvsvc_NETRPRNAMECANONICALIZE *r)
2684 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2685 return WERR_NOT_SUPPORTED;
2688 WERROR _srvsvc_NetPRNameCompare(struct pipes_struct *p,
2689 struct srvsvc_NetPRNameCompare *r)
2691 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2692 return WERR_NOT_SUPPORTED;
2695 WERROR _srvsvc_NetShareDelStart(struct pipes_struct *p,
2696 struct srvsvc_NetShareDelStart *r)
2698 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2699 return WERR_NOT_SUPPORTED;
2702 WERROR _srvsvc_NetShareDelCommit(struct pipes_struct *p,
2703 struct srvsvc_NetShareDelCommit *r)
2705 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2706 return WERR_NOT_SUPPORTED;
2709 WERROR _srvsvc_NetServerTransportAddEx(struct pipes_struct *p,
2710 struct srvsvc_NetServerTransportAddEx *r)
2712 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2713 return WERR_NOT_SUPPORTED;
2716 WERROR _srvsvc_NetServerSetServiceBitsEx(struct pipes_struct *p,
2717 struct srvsvc_NetServerSetServiceBitsEx *r)
2719 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2720 return WERR_NOT_SUPPORTED;
2723 WERROR _srvsvc_NETRDFSGETVERSION(struct pipes_struct *p,
2724 struct srvsvc_NETRDFSGETVERSION *r)
2726 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2727 return WERR_NOT_SUPPORTED;
2730 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(struct pipes_struct *p,
2731 struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2733 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2734 return WERR_NOT_SUPPORTED;
2737 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(struct pipes_struct *p,
2738 struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2740 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2741 return WERR_NOT_SUPPORTED;
2744 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(struct pipes_struct *p,
2745 struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r)
2747 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2748 return WERR_NOT_SUPPORTED;
2751 WERROR _srvsvc_NETRDFSSETSERVERINFO(struct pipes_struct *p,
2752 struct srvsvc_NETRDFSSETSERVERINFO *r)
2754 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2755 return WERR_NOT_SUPPORTED;
2758 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(struct pipes_struct *p,
2759 struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2761 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2762 return WERR_NOT_SUPPORTED;
2765 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(struct pipes_struct *p,
2766 struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2768 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2769 return WERR_NOT_SUPPORTED;
2772 WERROR _srvsvc_NETRDFSMODIFYPREFIX(struct pipes_struct *p,
2773 struct srvsvc_NETRDFSMODIFYPREFIX *r)
2775 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2776 return WERR_NOT_SUPPORTED;
2779 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(struct pipes_struct *p,
2780 struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2782 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2783 return WERR_NOT_SUPPORTED;
2786 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(struct pipes_struct *p,
2787 struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2789 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2790 return WERR_NOT_SUPPORTED;
2793 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(struct pipes_struct *p,
2794 struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2796 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
2797 return WERR_NOT_SUPPORTED;