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) Jelmer Vernooij 2006.
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 2 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, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* This is the implementation of the srvsvc pipe. */
29 #define MAX_SERVER_DISK_ENTRIES 15
31 extern struct generic_mapping file_generic_mapping;
32 extern userdom_struct current_user_info;
35 #define DBGC_CLASS DBGC_RPC_SRV
37 /* Use for enumerating connections, pipes, & files */
39 struct file_enum_count {
42 struct srvsvc_NetFileInfo3 *info;
45 struct sess_file_count {
51 /****************************************************************************
52 Count the entries belonging to a service in the connection db.
53 ****************************************************************************/
55 static int pipe_enum_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *p)
57 struct pipe_open_rec prec;
58 struct file_enum_count *fenum = (struct file_enum_count *)p;
60 if (dbuf.dsize != sizeof(struct pipe_open_rec))
63 memcpy(&prec, dbuf.dptr, sizeof(struct pipe_open_rec));
65 if ( process_exists(prec.pid) ) {
66 struct srvsvc_NetFileInfo3 *f;
70 snprintf( fullpath, sizeof(fullpath), "\\PIPE\\%s", prec.name );
72 f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, struct srvsvc_NetFileInfo3, i+1 );
74 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
80 fenum->info[i].fid = (uint32)((procid_to_pid(&prec.pid)<<16) & prec.pnum);
81 fenum->info[i].permissions = (FILE_READ_DATA|FILE_WRITE_DATA);
82 fenum->info[i].num_locks = 0;
83 if (!(fenum->info[i].user = talloc_strdup(
84 fenum->ctx, uidtoname(prec.uid)))) {
85 /* There's not much we can do here. */
86 fenum->info[i].user = "";
88 if (!(fenum->info[i].path = talloc_strdup(
89 fenum->ctx, fullpath))) {
90 /* There's not much we can do here. */
91 fenum->info[i].path = "";
100 /*******************************************************************
101 ********************************************************************/
103 static WERROR net_enum_pipes( TALLOC_CTX *ctx, struct srvsvc_NetFileInfo3 **info,
104 uint32 *count, uint32 *resume )
106 struct file_enum_count fenum;
110 fenum.count = *count;
112 if (connections_traverse(pipe_enum_fn, &fenum) == -1) {
113 DEBUG(0,("net_enum_pipes: traverse of connections.tdb "
119 *count = fenum.count;
124 /*******************************************************************
125 ********************************************************************/
127 /* global needed to make use of the share_mode_forall() callback */
128 static struct file_enum_count f_enum_cnt;
130 static void enum_file_fn( const struct share_mode_entry *e,
131 const char *sharepath, const char *fname,
134 struct file_enum_count *fenum = &f_enum_cnt;
136 /* If the pid was not found delete the entry from connections.tdb */
138 if ( process_exists(e->pid) ) {
139 struct srvsvc_NetFileInfo3 *f;
140 int i = fenum->count;
142 struct byte_range_lock *brl;
147 f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, struct srvsvc_NetFileInfo3, i+1 );
149 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
154 /* need to count the number of locks on a file */
158 fsp.inode = e->inode;
160 if ( (brl = brl_get_locks_readonly(NULL,&fsp)) != NULL ) {
161 num_locks = brl->num_locks;
165 if ( strcmp( fname, "." ) == 0 ) {
166 pstr_sprintf( fullpath, "C:%s", sharepath );
168 pstr_sprintf( fullpath, "C:%s/%s", sharepath, fname );
170 string_replace( fullpath, '/', '\\' );
172 /* mask out create (what ever that is) */
173 permissions = e->share_access & (FILE_READ_DATA|FILE_WRITE_DATA);
175 fenum->info[i].fid = e->share_file_id;
176 fenum->info[i].permissions = permissions;
177 fenum->info[i].num_locks = num_locks;
178 if (!(fenum->info[i].user = talloc_strdup(
179 fenum->ctx, uidtoname(e->uid)))) {
180 /* There's not much we can do here. */
181 fenum->info[i].user = "";
183 if (!(fenum->info[i].path = talloc_strdup(
184 fenum->ctx, fullpath))) {
185 /* There's not much we can do here. */
186 fenum->info[i].path = "";
196 /*******************************************************************
197 ********************************************************************/
199 static WERROR net_enum_files( TALLOC_CTX *ctx, struct srvsvc_NetFileInfo3 **info,
200 uint32 *count, uint32 *resume )
202 f_enum_cnt.ctx = ctx;
203 f_enum_cnt.count = *count;
204 f_enum_cnt.info = *info;
206 share_mode_forall( enum_file_fn, NULL );
208 *info = f_enum_cnt.info;
209 *count = f_enum_cnt.count;
214 /*******************************************************************
215 Utility function to get the 'type' of a share from a share definition.
216 ********************************************************************/
217 static uint32 get_share_type(const struct share_params *params)
219 char *net_name = lp_servicename(params->service);
220 int len_net_name = strlen(net_name);
222 /* work out the share type */
223 uint32 type = STYPE_DISKTREE;
225 if (lp_print_ok(params->service))
227 if (strequal(lp_fstype(params->service), "IPC"))
229 if (net_name[len_net_name-1] == '$')
230 type |= STYPE_HIDDEN;
235 /*******************************************************************
236 Fill in a share info level 0 structure.
237 ********************************************************************/
239 static void init_srv_share_info_0(pipes_struct *p, struct srvsvc_NetShareInfo0 *sh0,
240 const struct share_params *params)
242 sh0->name = lp_servicename(params->service);
245 /*******************************************************************
246 Fill in a share info level 1 structure.
247 ********************************************************************/
249 static void init_srv_share_info_1(pipes_struct *p, struct srvsvc_NetShareInfo1 *sh1,
250 const struct share_params *params)
252 connection_struct *conn = p->conn;
254 sh1->comment = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
255 conn->user, conn->connectpath, conn->gid,
256 get_current_username(),
257 current_user_info.domain,
258 lp_comment(params->service));
260 sh1->name = lp_servicename(params->service);
261 sh1->type = get_share_type(params);
264 /*******************************************************************
265 Fill in a share info level 2 structure.
266 ********************************************************************/
268 static void init_srv_share_info_2(pipes_struct *p, struct srvsvc_NetShareInfo2 *sh2,
269 const struct share_params *params)
271 connection_struct *conn = p->conn;
274 int max_connections = lp_max_connections(params->service);
275 uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
277 char *net_name = lp_servicename(params->service);
279 remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
280 conn->user, conn->connectpath, conn->gid,
281 get_current_username(),
282 current_user_info.domain,
283 lp_comment(params->service));
284 path = talloc_asprintf(p->mem_ctx, "C:%s",
285 lp_pathname(params->service));
288 * Change / to \\ so that win2k will see it as a valid path. This was
289 * added to enable use of browsing in win2k add share dialog.
292 string_replace(path, '/', '\\');
294 count = count_current_connections( net_name, False );
295 sh2->name = net_name;
296 sh2->type = get_share_type(params);
297 sh2->comment = remark;
298 sh2->permissions = 0;
299 sh2->max_users = max_uses;
300 sh2->current_users = count;
305 /*******************************************************************
306 Map any generic bits to file specific bits.
307 ********************************************************************/
309 static void map_generic_share_sd_bits(SEC_DESC *psd)
312 SEC_ACL *ps_dacl = NULL;
321 for (i = 0; i < ps_dacl->num_aces; i++) {
322 SEC_ACE *psa = &ps_dacl->aces[i];
323 uint32 orig_mask = psa->access_mask;
325 se_map_generic(&psa->access_mask, &file_generic_mapping);
326 psa->access_mask |= orig_mask;
330 /*******************************************************************
331 Fill in a share info level 501 structure.
332 ********************************************************************/
334 static void init_srv_share_info_501(pipes_struct *p, struct srvsvc_NetShareInfo501 *sh501,
335 const struct share_params *params)
337 connection_struct *conn = p->conn;
339 const char *net_name = lp_servicename(params->service);
341 remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
342 conn->user, conn->connectpath, conn->gid,
343 get_current_username(),
344 current_user_info.domain,
345 lp_comment(params->service));
348 sh501->name = net_name;
349 sh501->type = get_share_type(params);
350 sh501->comment = remark;
351 sh501->csc_policy = (lp_csc_policy(params->service) << 4);
354 /*******************************************************************
355 Fill in a share info level 502 structure.
356 ********************************************************************/
358 static void init_srv_share_info_502(pipes_struct *p, struct srvsvc_NetShareInfo502 *sh502,
359 const struct share_params *params)
361 int max_connections = lp_max_connections(params->service);
362 uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
363 connection_struct *conn = p->conn;
370 TALLOC_CTX *ctx = p->mem_ctx;
375 net_name = lp_servicename(params->service);
376 count = count_current_connections( net_name, False );
378 remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
379 conn->user, conn->connectpath, conn->gid,
380 get_current_username(),
381 current_user_info.domain,
382 lp_comment(params->service));
384 path = talloc_asprintf(p->mem_ctx, "C:%s",
385 lp_pathname(params->service));
388 * Change / to \\ so that win2k will see it as a valid path. This was
389 * added to enable use of browsing in win2k add share dialog.
392 string_replace(path, '/', '\\');
394 sd = get_share_security(ctx, lp_servicename(params->service),
397 sh502->name = net_name;
398 sh502->type = get_share_type(params);
399 sh502->comment = remark;
401 sh502->password = "";
403 sh502->permissions = 0;
404 sh502->max_users = max_uses;
405 sh502->current_users = count;
409 /***************************************************************************
410 Fill in a share info level 1004 structure.
411 ***************************************************************************/
413 static void init_srv_share_info_1004(pipes_struct *p,
414 struct srvsvc_NetShareInfo1004* sh1004,
415 const struct share_params *params)
417 connection_struct *conn = p->conn;
420 remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
421 conn->user, conn->connectpath, conn->gid,
422 get_current_username(),
423 current_user_info.domain,
424 lp_comment(params->service));
426 ZERO_STRUCTP(sh1004);
428 sh1004->comment = remark;
431 /***************************************************************************
432 Fill in a share info level 1005 structure.
433 ***************************************************************************/
435 static void init_srv_share_info_1005(pipes_struct *p,
436 struct srvsvc_NetShareInfo1005* sh1005,
437 const struct share_params *params)
439 sh1005->dfs_flags = 0;
441 if(lp_host_msdfs() && lp_msdfs_root(params->service))
443 SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
445 lp_csc_policy(params->service) << SHARE_1005_CSC_POLICY_SHIFT;
447 /***************************************************************************
448 Fill in a share info level 1006 structure.
449 ***************************************************************************/
451 static void init_srv_share_info_1006(pipes_struct *p,
452 struct srvsvc_NetShareInfo1006* sh1006,
453 const struct share_params *params)
455 sh1006->max_users = -1;
458 /***************************************************************************
459 Fill in a share info level 1007 structure.
460 ***************************************************************************/
462 static void init_srv_share_info_1007(pipes_struct *p,
463 struct srvsvc_NetShareInfo1007* sh1007,
464 const struct share_params *params)
468 ZERO_STRUCTP(sh1007);
470 sh1007->flags = flags;
471 sh1007->alternate_directory_name = "";
474 /*******************************************************************
475 Fill in a share info level 1501 structure.
476 ********************************************************************/
478 static void init_srv_share_info_1501(pipes_struct *p,
479 struct sec_desc_buf *sh1501,
480 const struct share_params *params)
484 TALLOC_CTX *ctx = p->mem_ctx;
486 ZERO_STRUCTP(sh1501);
488 sd = get_share_security(ctx, lp_servicename(params->service),
494 /*******************************************************************
495 True if it ends in '$'.
496 ********************************************************************/
498 static BOOL is_hidden_share(const struct share_params *params)
500 const char *net_name = lp_servicename(params->service);
502 return (net_name[strlen(net_name) - 1] == '$');
505 /*******************************************************************
506 Fill in a share info structure.
507 ********************************************************************/
509 static WERROR init_srv_share_info_ctr(pipes_struct *p,
510 union srvsvc_NetShareCtr *ctr,
511 uint32 info_level, uint32 *resume_hnd,
512 uint32 *total_entries, BOOL all_shares)
514 TALLOC_CTX *ctx = p->mem_ctx;
515 struct share_iterator *shares;
516 struct share_params *share;
517 WERROR result = WERR_NOMEM;
519 DEBUG(5,("init_srv_share_info_ctr\n"));
527 /* Ensure all the usershares are loaded. */
529 load_usershare_shares();
530 load_registry_shares();
535 if (!(shares = share_list_all(ctx))) {
536 DEBUG(5, ("Could not list shares\n"));
537 return WERR_ACCESS_DENIED;
540 switch (info_level) {
542 if (!(ctr->ctr0 = TALLOC_ZERO_P(
543 p->mem_ctx, struct srvsvc_NetShareCtr0))) {
548 if (!(ctr->ctr1 = TALLOC_ZERO_P(
549 p->mem_ctx, struct srvsvc_NetShareCtr1))) {
554 if (!(ctr->ctr2 = TALLOC_ZERO_P(
555 p->mem_ctx, struct srvsvc_NetShareCtr2))) {
560 if (!(ctr->ctr501 = TALLOC_ZERO_P(
561 p->mem_ctx, struct srvsvc_NetShareCtr501))) {
566 if (!(ctr->ctr502 = TALLOC_ZERO_P(
567 p->mem_ctx, struct srvsvc_NetShareCtr502))) {
572 if (!(ctr->ctr1004 = TALLOC_ZERO_P(
573 p->mem_ctx, struct srvsvc_NetShareCtr1004))) {
578 if (!(ctr->ctr1005 = TALLOC_ZERO_P(
579 p->mem_ctx, struct srvsvc_NetShareCtr1005))) {
584 if (!(ctr->ctr1006 = TALLOC_ZERO_P(
585 p->mem_ctx, struct srvsvc_NetShareCtr1006))) {
590 if (!(ctr->ctr1007 = TALLOC_ZERO_P(
591 p->mem_ctx, struct srvsvc_NetShareCtr1007))) {
596 if (!(ctr->ctr1501 = TALLOC_ZERO_P(
597 p->mem_ctx, struct srvsvc_NetShareCtr1501))) {
602 DEBUG(5,("init_srv_share_info_ctr: unsupported switch "
603 "value %d\n", info_level));
604 return WERR_UNKNOWN_LEVEL;
607 while ((share = next_share(shares)) != NULL) {
608 if (!lp_browseable(share->service)) {
611 if (!all_shares && is_hidden_share(share)) {
615 switch (info_level) {
618 struct srvsvc_NetShareInfo0 i;
619 init_srv_share_info_0(p, &i, share);
620 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo0, i,
621 &ctr->ctr0->array, &ctr->ctr0->count);
622 if (ctr->ctr0->array == NULL) {
625 *total_entries = ctr->ctr0->count;
631 struct srvsvc_NetShareInfo1 i;
632 init_srv_share_info_1(p, &i, share);
633 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1, i,
634 &ctr->ctr1->array, &ctr->ctr1->count);
635 if (ctr->ctr1->array == NULL) {
638 *total_entries = ctr->ctr1->count;
644 struct srvsvc_NetShareInfo2 i;
645 init_srv_share_info_2(p, &i, share);
646 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo2, i,
647 &ctr->ctr2->array, &ctr->ctr2->count);
648 if (ctr->ctr2->array == NULL) {
651 *total_entries = ctr->ctr2->count;
657 struct srvsvc_NetShareInfo501 i;
658 init_srv_share_info_501(p, &i, share);
659 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo501, i,
660 &ctr->ctr501->array, &ctr->ctr501->count);
661 if (ctr->ctr501->array == NULL) {
664 *total_entries = ctr->ctr501->count;
670 struct srvsvc_NetShareInfo502 i;
671 init_srv_share_info_502(p, &i, share);
672 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo502, i,
673 &ctr->ctr502->array, &ctr->ctr502->count);
674 if (ctr->ctr502->array == NULL) {
677 *total_entries = ctr->ctr502->count;
681 /* here for completeness but not currently used with enum
686 struct srvsvc_NetShareInfo1004 i;
687 init_srv_share_info_1004(p, &i, share);
688 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1004, i,
689 &ctr->ctr1004->array, &ctr->ctr1004->count);
690 if (ctr->ctr1004->array == NULL) {
693 *total_entries = ctr->ctr1004->count;
699 struct srvsvc_NetShareInfo1005 i;
700 init_srv_share_info_1005(p, &i, share);
701 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1005, i,
702 &ctr->ctr1005->array, &ctr->ctr1005->count);
703 if (ctr->ctr1005->array == NULL) {
706 *total_entries = ctr->ctr1005->count;
712 struct srvsvc_NetShareInfo1006 i;
713 init_srv_share_info_1006(p, &i, share);
714 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1006, i,
715 &ctr->ctr1006->array, &ctr->ctr1006->count);
716 if (ctr->ctr1006->array == NULL) {
719 *total_entries = ctr->ctr1006->count;
725 struct srvsvc_NetShareInfo1007 i;
726 init_srv_share_info_1007(p, &i, share);
727 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1007, i,
728 &ctr->ctr1007->array, &ctr->ctr1007->count);
729 if (ctr->ctr1007->array == NULL) {
732 *total_entries = ctr->ctr1007->count;
738 struct sec_desc_buf i;
739 init_srv_share_info_1501(p, &i, share);
740 ADD_TO_ARRAY(ctx, struct sec_desc_buf, i,
741 &ctr->ctr1501->array, &ctr->ctr1501->count);
742 if (ctr->ctr1501->array == NULL) {
745 *total_entries = ctr->ctr1501->count;
759 /*******************************************************************
760 fill in a sess info level 0 structure.
761 ********************************************************************/
763 static void init_srv_sess_info_0(pipes_struct *p, struct srvsvc_NetSessCtr0 *ss0, uint32 *snum, uint32 *stot)
765 struct sessionid *session_list;
766 uint32 num_entries = 0;
767 (*stot) = list_sessions(p->mem_ctx, &session_list);
776 DEBUG(5,("init_srv_sess_0_ss0\n"));
778 ss0->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetSessInfo0, *stot);
781 for (; (*snum) < (*stot); (*snum)++) {
782 ss0->array[num_entries].client = session_list[(*snum)].remote_machine;
786 ss0->count = num_entries;
788 if ((*snum) >= (*stot)) {
798 /*******************************************************************
799 ********************************************************************/
801 static void sess_file_fn( const struct share_mode_entry *e,
802 const char *sharepath, const char *fname,
805 struct sess_file_count *sess = (struct sess_file_count *)private_data;
807 if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
814 /*******************************************************************
815 ********************************************************************/
817 static int net_count_files( uid_t uid, struct server_id pid )
819 struct sess_file_count s_file_cnt;
821 s_file_cnt.count = 0;
822 s_file_cnt.uid = uid;
823 s_file_cnt.pid = pid;
825 share_mode_forall( sess_file_fn, (void *)&s_file_cnt );
827 return s_file_cnt.count;
830 /*******************************************************************
831 fill in a sess info level 1 structure.
832 ********************************************************************/
834 static void init_srv_sess_info_1(pipes_struct *p, struct srvsvc_NetSessCtr1 *ss1, uint32 *snum, uint32 *stot)
836 struct sessionid *session_list;
837 uint32 num_entries = 0;
838 time_t now = time(NULL);
855 (*stot) = list_sessions(p->mem_ctx, &session_list);
857 ss1->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetSessInfo1, *stot);
859 for (; (*snum) < (*stot); (*snum)++) {
862 struct passwd *pw = sys_getpwnam(session_list[*snum].username);
866 DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
867 session_list[*snum].username));
871 connect_time = (uint32)(now - session_list[*snum].connect_start);
872 num_files = net_count_files(pw->pw_uid, session_list[*snum].pid);
873 guest = strequal( session_list[*snum].username, lp_guestaccount() );
875 if (!(ss1->array[num_entries].client = talloc_strdup(
876 ss1->array, session_list[*snum].remote_machine))) {
877 ss1->array[num_entries].client = "";
879 if (!(ss1->array[num_entries].user = talloc_strdup(
880 ss1->array, session_list[*snum].username))) {
881 ss1->array[num_entries].user = "";
883 ss1->array[num_entries].num_open = num_files;
884 ss1->array[num_entries].time = connect_time;
885 ss1->array[num_entries].idle_time = 0;
886 ss1->array[num_entries].user_flags = guest;
891 ss1->count = num_entries;
893 if ((*snum) >= (*stot)) {
898 /*******************************************************************
899 makes a SRV_R_NET_SESS_ENUM structure.
900 ********************************************************************/
902 static WERROR init_srv_sess_info_ctr(pipes_struct *p, union srvsvc_NetSessCtr *ctr,
903 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
905 WERROR status = WERR_OK;
906 DEBUG(5,("init_srv_sess_info_ctr: %d\n", __LINE__));
908 switch (switch_value) {
910 ctr->ctr0 = talloc(p->mem_ctx, struct srvsvc_NetSessCtr0);
911 init_srv_sess_info_0(p, ctr->ctr0, resume_hnd, total_entries);
914 ctr->ctr1 = talloc(p->mem_ctx, struct srvsvc_NetSessCtr1);
915 init_srv_sess_info_1(p, ctr->ctr1, resume_hnd, total_entries);
918 DEBUG(5,("init_srv_sess_info_ctr: unsupported switch value %d\n", switch_value));
919 if (resume_hnd != NULL)
921 (*total_entries) = 0;
923 status = WERR_UNKNOWN_LEVEL;
930 /*******************************************************************
931 fill in a conn info level 0 structure.
932 ********************************************************************/
934 static void init_srv_conn_info_0(pipes_struct *p, struct srvsvc_NetConnCtr0 *ss0, uint32 *snum, uint32 *stot)
936 uint32 num_entries = 0;
945 DEBUG(5,("init_srv_conn_0_ss0\n"));
948 ss0->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetConnInfo0, *stot);
949 for (; (*snum) < (*stot); (*snum)++) {
951 ss0->array[num_entries].conn_id = (*stot);
953 /* move on to creating next connection */
954 /* move on to creating next conn */
958 ss0->count = num_entries;
960 if ((*snum) >= (*stot)) {
972 /*******************************************************************
973 fill in a conn info level 1 structure.
974 ********************************************************************/
976 static void init_srv_conn_info_1(pipes_struct *p, struct srvsvc_NetConnCtr1 *ss1, uint32 *snum, uint32 *stot)
978 uint32 num_entries = 0;
987 DEBUG(5,("init_srv_conn_1_ss1\n"));
990 ss1->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetConnInfo1, *stot);
991 for (; (*snum) < (*stot); (*snum)++) {
992 ss1->array[num_entries].conn_id = (*stot);
993 ss1->array[num_entries].conn_type = 0x3;
994 ss1->array[num_entries].num_open = 1;
995 ss1->array[num_entries].num_users = 1;
996 ss1->array[num_entries].conn_time = 3;
997 ss1->array[num_entries].user = "dummy_user";
998 ss1->array[num_entries].share = "IPC$";
1000 /* move on to creating next connection */
1001 /* move on to creating next conn */
1005 ss1->count = num_entries;
1007 if ((*snum) >= (*stot)) {
1019 /*******************************************************************
1020 makes a SRV_R_NET_CONN_ENUM structure.
1021 ********************************************************************/
1023 static WERROR init_srv_conn_info_ctr(pipes_struct *p, union srvsvc_NetConnCtr *ctr,
1024 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
1026 WERROR status = WERR_OK;
1027 DEBUG(5,("init_srv_conn_info_ctr: %d\n", __LINE__));
1029 switch (switch_value) {
1031 init_srv_conn_info_0(p, ctr->ctr0, resume_hnd, total_entries);
1034 init_srv_conn_info_1(p, ctr->ctr1, resume_hnd, total_entries);
1037 DEBUG(5,("init_srv_conn_info_ctr: unsupported switch value %d\n", switch_value));
1040 (*total_entries) = 0;
1041 status = WERR_UNKNOWN_LEVEL;
1048 /*******************************************************************
1049 makes a SRV_R_NET_FILE_ENUM structure.
1050 ********************************************************************/
1052 static WERROR net_file_enum_3(pipes_struct *p, union srvsvc_NetFileCtr *ctr, uint32 *resume_hnd, uint32 *num_entries )
1054 TALLOC_CTX *ctx = get_talloc_ctx();
1057 /* TODO -- Windows enumerates
1059 (c) open directories and files */
1061 ctr->ctr3 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetFileCtr3);
1063 status = net_enum_files( ctx, &ctr->ctr3->array, num_entries, resume_hnd );
1064 if ( !W_ERROR_IS_OK(status))
1067 status = net_enum_pipes( ctx, &ctr->ctr3->array, num_entries, resume_hnd );
1068 if ( !W_ERROR_IS_OK(status))
1071 ctr->ctr3->count = *num_entries;
1076 /*******************************************************************
1077 *******************************************************************/
1079 WERROR _srvsvc_NetFileEnum(pipes_struct *p, struct srvsvc_NetFileEnum *r)
1081 switch ( *r->in.level ) {
1083 return net_file_enum_3(p, r->in.ctr, r->in.resume_handle, r->out.totalentries );
1085 return WERR_UNKNOWN_LEVEL;
1091 /*******************************************************************
1093 ********************************************************************/
1095 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p, struct srvsvc_NetSrvGetInfo *r)
1097 WERROR status = WERR_OK;
1099 ZERO_STRUCTP(r->out.info);
1101 DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1103 if (!pipe_access_check(p)) {
1104 DEBUG(3, ("access denied to srv_net_srv_get_info\n"));
1105 return WERR_ACCESS_DENIED;
1108 switch (r->in.level) {
1110 /* Technically level 102 should only be available to
1111 Administrators but there isn't anything super-secret
1112 here, as most of it is made up. */
1115 r->out.info->info102 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1117 r->out.info->info102->platform_id = 500;
1118 r->out.info->info102->version_major = lp_major_announce_version();
1119 r->out.info->info102->version_minor = lp_minor_announce_version();
1120 r->out.info->info102->server_name = global_myname();
1121 r->out.info->info102->server_type = lp_default_server_announce();
1122 r->out.info->info102->userpath = "C:\\";
1123 r->out.info->info102->licenses = 10000;
1124 r->out.info->info102->anndelta = 3000;
1125 r->out.info->info102->disc = 0xf;
1126 r->out.info->info102->users = 0xffffffff;
1127 r->out.info->info102->hidden = 0;
1128 r->out.info->info102->announce = 240;
1129 r->out.info->info102->comment = lp_serverstring();
1132 r->out.info->info101 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1133 r->out.info->info101->platform_id = 500;
1134 r->out.info->info101->server_name = global_myname();
1135 r->out.info->info101->version_major = lp_major_announce_version();
1136 r->out.info->info101->version_minor = lp_minor_announce_version();
1137 r->out.info->info101->server_type = lp_default_server_announce();
1138 r->out.info->info101->comment = lp_serverstring();
1141 r->out.info->info100 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1142 r->out.info->info100->platform_id = 500;
1143 r->out.info->info100->server_name = global_myname();
1146 return WERR_UNKNOWN_LEVEL;
1150 DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1155 /*******************************************************************
1157 ********************************************************************/
1159 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p, struct srvsvc_NetSrvSetInfo *r)
1161 /* Set up the net server set info structure. */
1162 if (r->out.parm_error) {
1163 *r->out.parm_error = 0;
1168 /*******************************************************************
1170 ********************************************************************/
1172 WERROR _srvsvc_NetConnEnum(pipes_struct *p, struct srvsvc_NetConnEnum *r)
1174 DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
1176 ZERO_STRUCTP(r->out.ctr);
1179 return init_srv_conn_info_ctr(p, r->out.ctr, *r->in.level, r->in.resume_handle, r->out.totalentries);
1182 /*******************************************************************
1184 ********************************************************************/
1186 WERROR _srvsvc_NetSessEnum(pipes_struct *p, struct srvsvc_NetSessEnum *r)
1188 DEBUG(5,("_srv_net_sess_enum: %d\n", __LINE__));
1190 ZERO_STRUCTP(r->out.ctr);
1193 return init_srv_sess_info_ctr(p, r->out.ctr,
1195 r->in.resume_handle,
1196 r->out.totalentries);
1199 /*******************************************************************
1201 ********************************************************************/
1203 WERROR _srvsvc_NetSessDel(pipes_struct *p, struct srvsvc_NetSessDel *r)
1205 struct sessionid *session_list;
1206 int num_sessions, snum;
1209 char *machine = talloc_strdup(p->mem_ctx, r->in.server_unc);
1211 /* strip leading backslashes if any */
1212 while (machine[0] == '\\') {
1213 memmove(machine, &machine[1], strlen(machine));
1216 num_sessions = list_sessions(p->mem_ctx, &session_list);
1218 DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
1220 status = WERR_ACCESS_DENIED;
1222 /* fail out now if you are not root or not a domain admin */
1224 if ((p->pipe_user.ut.uid != sec_initial_uid()) &&
1225 ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
1230 for (snum = 0; snum < num_sessions; snum++) {
1232 if ((strequal(session_list[snum].username, r->in.user) || r->in.user[0] == '\0' ) &&
1233 strequal(session_list[snum].remote_machine, machine)) {
1236 ntstat = messaging_send(smbd_messaging_context(),
1237 session_list[snum].pid,
1238 MSG_SHUTDOWN, &data_blob_null);
1240 if (NT_STATUS_IS_OK(ntstat))
1245 DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
1251 /*******************************************************************
1253 ********************************************************************/
1255 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p, struct srvsvc_NetShareEnumAll *r)
1257 DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1259 if (!pipe_access_check(p)) {
1260 DEBUG(3, ("access denied to srv_net_share_enum_all\n"));
1261 return WERR_ACCESS_DENIED;
1264 /* Create the list of shares for the response. */
1265 return init_srv_share_info_ctr(p, r->out.ctr, *r->in.level,
1266 r->in.resume_handle, r->out.totalentries, True);
1269 /*******************************************************************
1271 ********************************************************************/
1273 WERROR _srvsvc_NetShareEnum(pipes_struct *p, struct srvsvc_NetShareEnum *r)
1275 DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1277 if (!pipe_access_check(p)) {
1278 DEBUG(3, ("access denied to srv_net_share_enum\n"));
1279 return WERR_ACCESS_DENIED;
1282 /* Create the list of shares for the response. */
1283 return init_srv_share_info_ctr(p, r->out.ctr, *r->in.level,
1284 r->in.resume_handle, r->out.totalentries, False);
1287 /*******************************************************************
1289 ********************************************************************/
1291 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p, struct srvsvc_NetShareGetInfo *r)
1293 const struct share_params *params;
1295 params = get_share_params(p->mem_ctx, r->in.share_name);
1297 if (params != NULL) {
1298 switch (r->in.level) {
1300 r->out.info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1301 init_srv_share_info_0(p, r->out.info->info0, params);
1304 r->out.info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1305 init_srv_share_info_1(p, r->out.info->info1, params);
1308 r->out.info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1309 init_srv_share_info_2(p, r->out.info->info2, params);
1312 r->out.info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1313 init_srv_share_info_501(p, r->out.info->info501, params);
1316 r->out.info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1317 init_srv_share_info_502(p, r->out.info->info502, params);
1320 /* here for completeness */
1322 r->out.info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1323 init_srv_share_info_1004(p, r->out.info->info1004, params);
1326 r->out.info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1327 init_srv_share_info_1005(p, r->out.info->info1005, params);
1330 /* here for completeness 1006 - 1501 */
1332 r->out.info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1333 init_srv_share_info_1006(p, r->out.info->info1006,
1337 r->out.info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1338 init_srv_share_info_1007(p, r->out.info->info1007,
1342 r->out.info->info1501 = talloc(p->mem_ctx, struct sec_desc_buf);
1343 init_srv_share_info_1501(p, r->out.info->info1501,
1347 DEBUG(5,("init_srv_net_share_get_info: unsupported "
1348 "switch value %d\n", r->in.level));
1349 return WERR_UNKNOWN_LEVEL;
1353 return WERR_INVALID_NAME;
1359 /*******************************************************************
1360 Check a given DOS pathname is valid for a share.
1361 ********************************************************************/
1363 char *valid_share_pathname(char *dos_pathname)
1367 /* Convert any '\' paths to '/' */
1368 unix_format(dos_pathname);
1369 unix_clean_name(dos_pathname);
1371 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1373 if (strlen(dos_pathname) > 2 && ptr[1] == ':' && ptr[0] != '/')
1376 /* Only absolute paths allowed. */
1383 static void setval_helper(struct registry_key *key, const char *name,
1384 const char *value, WERROR *err)
1386 struct registry_value val;
1388 if (!W_ERROR_IS_OK(*err)) {
1394 val.v.sz.str = CONST_DISCARD(char *, value);
1395 val.v.sz.len = strlen(value)+1;
1397 *err = reg_setvalue(key, name, &val);
1400 static WERROR add_share(const char *share_name, const char *path,
1401 const char *comment, uint32 max_connections,
1402 const struct nt_user_token *token,
1405 if (lp_add_share_cmd() && *lp_add_share_cmd()) {
1409 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1410 lp_add_share_cmd(), dyn_CONFIGFILE, share_name,
1411 path, comment, max_connections) == -1) {
1415 DEBUG(10,("add_share: Running [%s]\n", command ));
1417 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1422 if ( (ret = smbrun(command, NULL)) == 0 ) {
1423 /* Tell everyone we updated smb.conf. */
1424 message_send_all(smbd_messaging_context(),
1425 MSG_SMB_CONF_UPDATED,
1426 NULL, 0, False, NULL);
1432 /********* END SeDiskOperatorPrivilege BLOCK *********/
1434 DEBUG(3,("_srv_net_share_add: Running [%s] returned (%d)\n",
1438 * No fallback to registry shares, the user did define a add
1439 * share command, so fail here.
1443 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1446 if (lp_registry_shares()) {
1448 struct registry_key *key;
1449 enum winreg_CreateAction action;
1451 TALLOC_CTX *mem_ctx;
1453 if (!(keyname = talloc_asprintf(NULL, "%s\\%s", KEY_SMBCONF,
1458 mem_ctx = (TALLOC_CTX *)keyname;
1460 err = reg_create_path(mem_ctx, keyname, REG_KEY_WRITE,
1461 is_disk_op ? get_root_nt_token():token,
1464 if (action != REG_CREATED_NEW_KEY) {
1465 err = WERR_ALREADY_EXISTS;
1468 if (!W_ERROR_IS_OK(err)) {
1469 TALLOC_FREE(mem_ctx);
1473 setval_helper(key, "path", path, &err);
1474 if ((comment != NULL) && (comment[0] != '\0')) {
1475 setval_helper(key, "comment", comment, &err);
1477 if (max_connections != 0) {
1479 snprintf(tmp, sizeof(tmp), "%d", max_connections);
1480 setval_helper(key, "max connections", tmp, &err);
1483 if (!W_ERROR_IS_OK(err)) {
1485 * Hmmmm. We'd need transactions on the registry to
1486 * get this right....
1488 reg_delete_path(is_disk_op ? get_root_nt_token():token,
1491 TALLOC_FREE(mem_ctx);
1495 return WERR_ACCESS_DENIED;
1498 static WERROR delete_share(const char *sharename,
1499 const struct nt_user_token *token,
1502 if (lp_delete_share_cmd() && *lp_delete_share_cmd()) {
1506 if (asprintf(&command, "%s \"%s\" \"%s\"",
1507 lp_delete_share_cmd(), dyn_CONFIGFILE,
1512 DEBUG(10,("delete_share: Running [%s]\n", command ));
1514 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1519 if ( (ret = smbrun(command, NULL)) == 0 ) {
1520 /* Tell everyone we updated smb.conf. */
1521 message_send_all(smbd_messaging_context(),
1522 MSG_SMB_CONF_UPDATED,
1523 NULL, 0, False, NULL);
1529 /********* END SeDiskOperatorPrivilege BLOCK *********/
1533 DEBUG(3,("_srv_net_share_del: Running [%s] returned (%d)\n",
1535 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1538 if (lp_registry_shares()) {
1542 if (asprintf(&keyname, "%s\\%s", KEY_SMBCONF,
1547 err = reg_delete_path(is_disk_op ? get_root_nt_token():token,
1553 return WERR_ACCESS_DENIED;
1556 static WERROR change_share(const char *share_name, const char *path,
1557 const char *comment, uint32 max_connections,
1558 const struct nt_user_token *token,
1561 if (lp_change_share_cmd() && *lp_change_share_cmd()) {
1565 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1566 lp_change_share_cmd(), dyn_CONFIGFILE, share_name,
1567 path, comment, max_connections) == -1) {
1571 DEBUG(10,("_srv_net_share_set_info: Running [%s]\n", command));
1573 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1578 if ( (ret = smbrun(command, NULL)) == 0 ) {
1579 /* Tell everyone we updated smb.conf. */
1580 message_send_all(smbd_messaging_context(),
1581 MSG_SMB_CONF_UPDATED,
1582 NULL, 0, False, NULL);
1588 /********* END SeDiskOperatorPrivilege BLOCK *********/
1590 DEBUG(3,("_srv_net_share_set_info: Running [%s] returned "
1591 "(%d)\n", command, ret ));
1595 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1598 if (lp_registry_shares()) {
1600 struct registry_key *key;
1602 TALLOC_CTX *mem_ctx;
1604 if (!(keyname = talloc_asprintf(NULL, "%s\\%s", KEY_SMBCONF,
1609 mem_ctx = (TALLOC_CTX *)keyname;
1611 err = reg_open_path(mem_ctx, keyname, REG_KEY_WRITE,
1612 is_disk_op ? get_root_nt_token():token,
1614 if (!W_ERROR_IS_OK(err)) {
1615 TALLOC_FREE(mem_ctx);
1619 setval_helper(key, "path", path, &err);
1621 reg_deletevalue(key, "comment");
1622 if ((comment != NULL) && (comment[0] != '\0')) {
1623 setval_helper(key, "comment", comment, &err);
1626 reg_deletevalue(key, "max connections");
1627 if (max_connections != 0) {
1629 snprintf(tmp, sizeof(tmp), "%d", max_connections);
1630 setval_helper(key, "max connections", tmp, &err);
1633 TALLOC_FREE(mem_ctx);
1637 return WERR_ACCESS_DENIED;
1640 /*******************************************************************
1641 Net share set info. Modify share details.
1642 ********************************************************************/
1644 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p, struct srvsvc_NetShareSetInfo *r)
1651 SEC_DESC *psd = NULL;
1652 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1653 BOOL is_disk_op = False;
1654 int max_connections = 0;
1655 fstring tmp_share_name;
1657 DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1659 if (r->out.parm_error) {
1660 *r->out.parm_error = 0;
1663 if ( strequal(r->in.share_name,"IPC$")
1664 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1665 || strequal(r->in.share_name,"global") )
1667 return WERR_ACCESS_DENIED;
1670 fstrcpy(tmp_share_name, r->in.share_name);
1671 snum = find_service(tmp_share_name);
1673 /* Does this share exist ? */
1675 return WERR_NET_NAME_NOT_FOUND;
1677 /* No change to printer shares. */
1678 if (lp_print_ok(snum))
1679 return WERR_ACCESS_DENIED;
1681 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1684 /* fail out now if you are not root and not a disk op */
1686 if ( p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
1687 return WERR_ACCESS_DENIED;
1689 switch (r->in.level) {
1691 pstrcpy(pathname, lp_pathname(snum));
1692 pstrcpy(comment, r->in.info.info1->comment);
1693 type = r->in.info.info1->type;
1697 pstrcpy(comment, r->in.info.info2->comment);
1698 pstrcpy(pathname, r->in.info.info2->path);
1699 type = r->in.info.info2->type;
1700 max_connections = (r->in.info.info2->max_users == 0xffffffff) ?
1701 0 : r->in.info.info2->max_users;
1705 pstrcpy(comment, r->in.info.info502->comment);
1706 pstrcpy(pathname, r->in.info.info502->path);
1707 type = r->in.info.info502->type;
1708 psd = r->in.info.info502->sd;
1709 map_generic_share_sd_bits(psd);
1712 pstrcpy(pathname, lp_pathname(snum));
1713 pstrcpy(comment, r->in.info.info1004->comment);
1714 type = STYPE_DISKTREE;
1717 /* XP re-sets the csc policy even if it wasn't changed by the
1718 user, so we must compare it to see if it's what is set in
1719 smb.conf, so that we can contine other ops like setting
1721 if (((r->in.info.info1005->dfs_flags &
1722 SHARE_1005_CSC_POLICY_MASK) >>
1723 SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1726 DEBUG(3, ("_srv_net_share_set_info: client is trying "
1727 "to change csc policy from the network; "
1728 "must be done with smb.conf\n"));
1729 return WERR_ACCESS_DENIED;
1733 return WERR_ACCESS_DENIED;
1735 pstrcpy(pathname, lp_pathname(snum));
1736 pstrcpy(comment, lp_comment(snum));
1737 psd = r->in.info.info1501->sd;
1738 map_generic_share_sd_bits(psd);
1739 type = STYPE_DISKTREE;
1742 DEBUG(5,("_srv_net_share_set_info: unsupported switch value "
1743 "%d\n", r->in.level));
1744 return WERR_UNKNOWN_LEVEL;
1747 /* We can only modify disk shares. */
1748 if (type != STYPE_DISKTREE)
1749 return WERR_ACCESS_DENIED;
1751 /* Check if the pathname is valid. */
1752 if (!(path = valid_share_pathname( pathname )))
1753 return WERR_OBJECT_PATH_INVALID;
1755 /* Ensure share name, pathname and comment don't contain '"'
1757 string_replace(tmp_share_name, '"', ' ');
1758 string_replace(path, '"', ' ');
1759 string_replace(comment, '"', ' ');
1761 DEBUG(10,("_srv_net_share_set_info: change share command = %s\n",
1762 lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1764 /* Only call modify function if something changed. */
1766 if (strcmp(path, lp_pathname(snum))
1767 || strcmp(comment, lp_comment(snum))
1768 || (lp_max_connections(snum) != max_connections) ) {
1771 err = change_share(tmp_share_name, path, comment,
1772 max_connections, p->pipe_user.nt_user_token,
1775 if (!W_ERROR_IS_OK(err)) {
1780 /* Replace SD if changed. */
1785 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum),
1788 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1789 if (!set_share_security(r->in.share_name, psd)) {
1790 DEBUG(0,("_srv_net_share_set_info: Failed to "
1791 "change security info in share %s.\n",
1792 r->in.share_name ));
1797 DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1803 /*******************************************************************
1804 Net share add. Call 'add_share_command "sharename" "pathname"
1805 "comment" "max connections = "
1806 ********************************************************************/
1808 WERROR _srvsvc_NetShareAdd(pipes_struct *p, struct srvsvc_NetShareAdd *r)
1815 SEC_DESC *psd = NULL;
1816 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1818 uint32 max_connections = 0;
1821 DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1823 if (r->out.parm_error) {
1824 *r->out.parm_error = 0;
1827 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1830 if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
1831 return WERR_ACCESS_DENIED;
1833 switch (r->in.level) {
1835 /* No path. Not enough info in a level 0 to do anything. */
1836 return WERR_ACCESS_DENIED;
1838 /* Not enough info in a level 1 to do anything. */
1839 return WERR_ACCESS_DENIED;
1841 pstrcpy(share_name, r->in.info.info2->name);
1842 pstrcpy(comment, r->in.info.info2->comment);
1843 pstrcpy(pathname, r->in.info.info2->path);
1844 max_connections = (r->in.info.info2->max_users == 0xffffffff) ?
1845 0 : r->in.info.info2->max_users;
1846 type = r->in.info.info2->type;
1849 /* No path. Not enough info in a level 501 to do anything. */
1850 return WERR_ACCESS_DENIED;
1852 pstrcpy(share_name, r->in.info.info502->name);
1853 pstrcpy(comment, r->in.info.info502->comment);
1854 pstrcpy(pathname, r->in.info.info502->path);
1855 type = r->in.info.info502->type;
1856 psd = r->in.info.info502->sd;
1857 map_generic_share_sd_bits(psd);
1860 /* none of the following contain share names. NetShareAdd
1861 * does not have a separate parameter for the share name */
1867 return WERR_ACCESS_DENIED;
1869 /* DFS only level. */
1870 return WERR_ACCESS_DENIED;
1872 DEBUG(5,("_srv_net_share_add: unsupported switch value %d\n",
1874 return WERR_UNKNOWN_LEVEL;
1877 /* check for invalid share names */
1879 if ( !validate_net_name( share_name, INVALID_SHARENAME_CHARS,
1880 sizeof(share_name) ) ) {
1881 DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n",
1883 return WERR_INVALID_NAME;
1886 if ( strequal(share_name,"IPC$") || strequal(share_name,"global")
1887 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") ) )
1889 return WERR_ACCESS_DENIED;
1892 if (get_share_params(p->mem_ctx, share_name) != NULL) {
1893 /* Share already exists. */
1894 return WERR_ALREADY_EXISTS;
1897 /* We can only add disk shares. */
1898 if (type != STYPE_DISKTREE)
1899 return WERR_ACCESS_DENIED;
1901 /* Check if the pathname is valid. */
1902 if (!(path = valid_share_pathname( pathname )))
1903 return WERR_OBJECT_PATH_INVALID;
1905 /* Ensure share name, pathname and comment don't contain '"'
1908 string_replace(share_name, '"', ' ');
1909 string_replace(path, '"', ' ');
1910 string_replace(comment, '"', ' ');
1912 err = add_share(share_name, path, comment, max_connections,
1913 p->pipe_user.nt_user_token, is_disk_op);
1915 if (!W_ERROR_IS_OK(err)) {
1920 if (!set_share_security(share_name, psd)) {
1921 DEBUG(0,("_srv_net_share_add: Failed to add security "
1922 "info to share %s.\n", share_name ));
1927 * We don't call reload_services() here, the message will
1928 * cause this to be done before the next packet is read
1929 * from the client. JRA.
1932 DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1937 /*******************************************************************
1938 Net share delete. Call "delete share command" with the share name as
1940 ********************************************************************/
1942 WERROR _srvsvc_NetShareDel(pipes_struct *p, struct srvsvc_NetShareDel *r)
1944 struct share_params *params;
1945 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1949 DEBUG(5,("_srv_net_share_del: %d\n", __LINE__));
1951 if ( strequal(r->in.share_name, "IPC$")
1952 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1953 || strequal(r->in.share_name, "global") )
1955 return WERR_ACCESS_DENIED;
1958 if (!(params = get_share_params(p->mem_ctx, r->in.share_name))) {
1959 return WERR_NO_SUCH_SHARE;
1962 /* No change to printer shares. */
1963 if (lp_print_ok(params->service))
1964 return WERR_ACCESS_DENIED;
1966 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1969 if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
1970 return WERR_ACCESS_DENIED;
1972 err = delete_share(lp_servicename(params->service),
1973 p->pipe_user.nt_user_token, is_disk_op);
1975 if (!W_ERROR_IS_OK(err)) {
1979 /* Delete the SD in the database. */
1980 delete_share_security(params);
1982 lp_killservice(params->service);
1987 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p, struct srvsvc_NetShareDelSticky *r)
1989 struct srvsvc_NetShareDel s;
1991 DEBUG(5,("_srv_net_share_del_stick: %d\n", __LINE__));
1993 s.in.server_unc = r->in.server_unc;
1994 s.in.share_name = r->in.share_name;
1995 s.in.reserved = r->in.reserved;
1997 return _srvsvc_NetShareDel(p, &s);
2000 /*******************************************************************
2002 ********************************************************************/
2004 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p, struct srvsvc_NetRemoteTOD *r)
2007 time_t unixdate = time(NULL);
2008 WERROR status = WERR_OK;
2010 /* We do this call first as if we do it *after* the gmtime call
2011 it overwrites the pointed-to values. JRA */
2013 uint32 zone = get_time_zone(unixdate)/60;
2015 DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
2017 t = gmtime(&unixdate);
2020 r->out.info->elapsed = unixdate;
2021 r->out.info->msecs = 0;
2022 r->out.info->hours = t->tm_hour;
2023 r->out.info->mins = t->tm_min;
2024 r->out.info->secs = t->tm_sec;
2025 r->out.info->hunds = 0;
2026 r->out.info->timezone = zone;
2027 r->out.info->tinterval = 10000;
2028 r->out.info->day = t->tm_mday;
2029 r->out.info->month = t->tm_mon + 1;
2030 r->out.info->year = 1900+t->tm_year;
2031 r->out.info->weekday = t->tm_wday;
2033 DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
2038 /***********************************************************************************
2039 Win9x NT tools get security descriptor.
2040 ***********************************************************************************/
2042 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecurity *r)
2044 SEC_DESC *psd = NULL;
2047 files_struct *fsp = NULL;
2050 connection_struct *conn = NULL;
2051 BOOL became_user = False;
2052 WERROR status = WERR_OK;
2058 /* Null password is ok - we are already an authenticated user... */
2059 null_pw = data_blob_null;
2062 conn = make_connection(r->in.share, null_pw, "A:", p->pipe_user.vuid, &nt_status);
2066 DEBUG(3,("_srv_net_file_query_secdesc: Unable to connect to %s\n", r->in.share));
2067 status = ntstatus_to_werror(nt_status);
2071 if (!become_user(conn, conn->vuid)) {
2072 DEBUG(0,("_srv_net_file_query_secdesc: Can't become connected user!\n"));
2073 status = WERR_ACCESS_DENIED;
2078 pstrcpy(tmp_file, r->in.file);
2079 nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
2080 if (!NT_STATUS_IS_OK(nt_status)) {
2081 DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", r->in.file));
2082 status = WERR_ACCESS_DENIED;
2086 nt_status = check_name(conn, r->in.file);
2087 if (!NT_STATUS_IS_OK(nt_status)) {
2088 DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", r->in.file));
2089 status = WERR_ACCESS_DENIED;
2093 nt_status = open_file_stat(conn, r->in.file, &st, &fsp);
2094 if (!NT_STATUS_IS_OK(nt_status)) {
2095 /* Perhaps it is a directory */
2096 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2097 nt_status = open_directory(conn, r->in.file, &st,
2098 READ_CONTROL_ACCESS,
2099 FILE_SHARE_READ|FILE_SHARE_WRITE,
2102 FILE_ATTRIBUTE_DIRECTORY,
2105 if (!NT_STATUS_IS_OK(nt_status)) {
2106 DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", r->in.file));
2107 status = WERR_ACCESS_DENIED;
2112 sd_size = SMB_VFS_GET_NT_ACL(fsp, fsp->fsp_name, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
2115 DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", r->in.file));
2116 status = WERR_ACCESS_DENIED;
2120 r->out.sd_buf->sd_size= sd_size;
2121 r->out.sd_buf->sd = psd;
2123 psd->dacl->revision = (uint16) NT4_ACL_REVISION;
2125 close_file(fsp, NORMAL_CLOSE);
2127 close_cnum(conn, p->pipe_user.vuid);
2133 close_file(fsp, NORMAL_CLOSE);
2140 close_cnum(conn, p->pipe_user.vuid);
2145 /***********************************************************************************
2146 Win9x NT tools set security descriptor.
2147 ***********************************************************************************/
2149 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecurity *r)
2153 files_struct *fsp = NULL;
2156 connection_struct *conn = NULL;
2157 BOOL became_user = False;
2158 WERROR status = WERR_OK;
2163 /* Null password is ok - we are already an authenticated user... */
2164 null_pw = data_blob_null;
2167 conn = make_connection(r->in.share, null_pw, "A:", p->pipe_user.vuid, &nt_status);
2171 DEBUG(3,("_srv_net_file_set_secdesc: Unable to connect to %s\n", r->in.share));
2172 status = ntstatus_to_werror(nt_status);
2176 if (!become_user(conn, conn->vuid)) {
2177 DEBUG(0,("_srv_net_file_set_secdesc: Can't become connected user!\n"));
2178 status = WERR_ACCESS_DENIED;
2183 pstrcpy(tmp_file, r->in.file);
2184 nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
2185 if (!NT_STATUS_IS_OK(nt_status)) {
2186 DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", r->in.file));
2187 status = WERR_ACCESS_DENIED;
2191 nt_status = check_name(conn, r->in.file);
2192 if (!NT_STATUS_IS_OK(nt_status)) {
2193 DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", r->in.file));
2194 status = WERR_ACCESS_DENIED;
2199 nt_status = open_file_stat(conn, r->in.file, &st, &fsp);
2201 if (!NT_STATUS_IS_OK(nt_status)) {
2202 /* Perhaps it is a directory */
2203 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2204 nt_status = open_directory(conn, r->in.file, &st,
2205 FILE_READ_ATTRIBUTES,
2206 FILE_SHARE_READ|FILE_SHARE_WRITE,
2209 FILE_ATTRIBUTE_DIRECTORY,
2212 if (!NT_STATUS_IS_OK(nt_status)) {
2213 DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", r->in.file));
2214 status = WERR_ACCESS_DENIED;
2219 ret = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, r->in.securityinformation, r->in.sd_buf.sd);
2222 DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", r->in.file));
2223 status = WERR_ACCESS_DENIED;
2227 close_file(fsp, NORMAL_CLOSE);
2229 close_cnum(conn, p->pipe_user.vuid);
2235 close_file(fsp, NORMAL_CLOSE);
2243 close_cnum(conn, p->pipe_user.vuid);
2249 /***********************************************************************************
2250 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2251 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2252 These disks would the disks listed by this function.
2253 Users could then create shares relative to these disks. Watch out for moving these disks around.
2254 "Nigel Williams" <nigel@veritas.com>.
2255 ***********************************************************************************/
2257 static const char *server_disks[] = {"C:"};
2259 static uint32 get_server_disk_count(void)
2261 return sizeof(server_disks)/sizeof(server_disks[0]);
2264 static uint32 init_server_disk_enum(uint32 *resume)
2266 uint32 server_disk_count = get_server_disk_count();
2268 /*resume can be an offset into the list for now*/
2270 if(*resume & 0x80000000)
2273 if(*resume > server_disk_count)
2274 *resume = server_disk_count;
2276 return server_disk_count - *resume;
2279 static const char *next_server_disk_enum(uint32 *resume)
2283 if(init_server_disk_enum(resume) == 0)
2286 disk = server_disks[*resume];
2290 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2295 WERROR _srvsvc_NetDiskEnum(pipes_struct *p, struct srvsvc_NetDiskEnum *r)
2298 const char *disk_name;
2300 WERROR status = WERR_OK;
2302 *r->out.totalentries = init_server_disk_enum(r->in.resume_handle);
2303 r->out.info->count = 0;
2305 if(!(r->out.info->disks = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetDiskInfo0, MAX_SERVER_DISK_ENTRIES))) {
2309 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2311 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(r->in.resume_handle)); i++) {
2313 r->out.info->count++;
2314 (*r->out.totalentries)++;
2316 /*copy disk name into a unicode string*/
2318 r->out.info->disks[i].disk = disk_name;
2321 /* add a terminating null string. Is this there if there is more data to come? */
2323 r->out.info->count++;
2324 (*r->out.totalentries)++;
2326 r->out.info->disks[i].disk = "";
2331 /********************************************************************
2332 ********************************************************************/
2334 WERROR _srvsvc_NetNameValidate(pipes_struct *p, struct srvsvc_NetNameValidate *r)
2338 if ((r->in.flags != 0x0) && (r->in.flags != 0x80000000)) {
2339 return WERR_INVALID_PARAM;
2342 switch ( r->in.name_type ) {
2344 len = strlen_m(r->in.name);
2346 if ((r->in.flags == 0x0) && (len > 81)) {
2347 DEBUG(5,("_srv_net_name_validate: share name too long (%s > 81 chars)\n", r->in.name));
2348 return WERR_INVALID_NAME;
2350 if ((r->in.flags == 0x80000000) && (len > 13)) {
2351 DEBUG(5,("_srv_net_name_validate: share name too long (%s > 13 chars)\n", r->in.name));
2352 return WERR_INVALID_NAME;
2355 if ( ! validate_net_name( r->in.name, INVALID_SHARENAME_CHARS, sizeof(r->in.name) ) ) {
2356 DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", r->in.name));
2357 return WERR_INVALID_NAME;
2362 return WERR_UNKNOWN_LEVEL;
2369 /********************************************************************
2370 ********************************************************************/
2372 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2374 return WERR_ACCESS_DENIED;
2377 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2379 p->rng_fault_state = True;
2380 return WERR_NOT_SUPPORTED;
2383 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2385 p->rng_fault_state = True;
2386 return WERR_NOT_SUPPORTED;
2389 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2391 p->rng_fault_state = True;
2392 return WERR_NOT_SUPPORTED;
2395 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2397 p->rng_fault_state = True;
2398 return WERR_NOT_SUPPORTED;
2401 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2403 p->rng_fault_state = True;
2404 return WERR_NOT_SUPPORTED;
2407 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2409 p->rng_fault_state = True;
2410 return WERR_NOT_SUPPORTED;
2413 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2415 p->rng_fault_state = True;
2416 return WERR_NOT_SUPPORTED;
2419 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2421 p->rng_fault_state = True;
2422 return WERR_NOT_SUPPORTED;
2425 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2427 p->rng_fault_state = True;
2428 return WERR_NOT_SUPPORTED;
2431 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2433 p->rng_fault_state = True;
2434 return WERR_NOT_SUPPORTED;
2437 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2439 p->rng_fault_state = True;
2440 return WERR_NOT_SUPPORTED;
2443 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2445 p->rng_fault_state = True;
2446 return WERR_NOT_SUPPORTED;
2449 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2451 p->rng_fault_state = True;
2452 return WERR_NOT_SUPPORTED;
2455 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2457 p->rng_fault_state = True;
2458 return WERR_NOT_SUPPORTED;
2461 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2463 p->rng_fault_state = True;
2464 return WERR_NOT_SUPPORTED;
2467 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2469 p->rng_fault_state = True;
2470 return WERR_NOT_SUPPORTED;
2473 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2475 p->rng_fault_state = True;
2476 return WERR_NOT_SUPPORTED;
2479 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2481 p->rng_fault_state = True;
2482 return WERR_NOT_SUPPORTED;
2485 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2487 p->rng_fault_state = True;
2488 return WERR_NOT_SUPPORTED;
2491 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2493 p->rng_fault_state = True;
2494 return WERR_NOT_SUPPORTED;
2497 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2499 p->rng_fault_state = True;
2500 return WERR_NOT_SUPPORTED;
2503 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2505 p->rng_fault_state = True;
2506 return WERR_NOT_SUPPORTED;
2509 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2511 p->rng_fault_state = True;
2512 return WERR_NOT_SUPPORTED;
2515 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2517 p->rng_fault_state = True;
2518 return WERR_NOT_SUPPORTED;
2521 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2523 p->rng_fault_state = True;
2524 return WERR_NOT_SUPPORTED;
2527 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2529 p->rng_fault_state = True;
2530 return WERR_NOT_SUPPORTED;
2533 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2535 p->rng_fault_state = True;
2536 return WERR_NOT_SUPPORTED;
2539 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *R)
2541 p->rng_fault_state = True;
2542 return WERR_NOT_SUPPORTED;
2545 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2547 p->rng_fault_state = True;
2548 return WERR_NOT_SUPPORTED;
2551 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2553 p->rng_fault_state = True;
2554 return WERR_NOT_SUPPORTED;
2557 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2559 p->rng_fault_state = True;
2560 return WERR_NOT_SUPPORTED;
2563 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2565 p->rng_fault_state = True;
2566 return WERR_NOT_SUPPORTED;
2569 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2571 p->rng_fault_state = True;
2572 return WERR_NOT_SUPPORTED;
2575 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2577 p->rng_fault_state = True;
2578 return WERR_NOT_SUPPORTED;
2581 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2583 p->rng_fault_state = True;
2584 return WERR_NOT_SUPPORTED;