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 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. */
28 #define MAX_SERVER_DISK_ENTRIES 15
30 extern struct generic_mapping file_generic_mapping;
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 /* Use for enumerating connections, pipes, & files */
38 struct file_enum_count {
41 struct srvsvc_NetFileInfo3 *info;
44 struct sess_file_count {
50 /****************************************************************************
51 Count the entries belonging to a service in the connection db.
52 ****************************************************************************/
54 static int pipe_enum_fn( struct db_record *rec, void *p)
56 struct pipe_open_rec prec;
57 struct file_enum_count *fenum = (struct file_enum_count *)p;
59 if (rec->value.dsize != sizeof(struct pipe_open_rec))
62 memcpy(&prec, rec->value.dptr, sizeof(struct pipe_open_rec));
64 if ( process_exists(prec.pid) ) {
65 struct srvsvc_NetFileInfo3 *f;
69 snprintf( fullpath, sizeof(fullpath), "\\PIPE\\%s", prec.name );
71 f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, struct srvsvc_NetFileInfo3, i+1 );
73 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
79 fenum->info[i].fid = (uint32)((procid_to_pid(&prec.pid)<<16) & prec.pnum);
80 fenum->info[i].permissions = (FILE_READ_DATA|FILE_WRITE_DATA);
81 fenum->info[i].num_locks = 0;
82 if (!(fenum->info[i].user = talloc_strdup(
83 fenum->ctx, uidtoname(prec.uid)))) {
84 /* There's not much we can do here. */
85 fenum->info[i].user = "";
87 if (!(fenum->info[i].path = talloc_strdup(
88 fenum->ctx, fullpath))) {
89 /* There's not much we can do here. */
90 fenum->info[i].path = "";
99 /*******************************************************************
100 ********************************************************************/
102 static WERROR net_enum_pipes( TALLOC_CTX *ctx, struct srvsvc_NetFileInfo3 **info,
103 uint32 *count, uint32 *resume )
105 struct file_enum_count fenum;
109 fenum.count = *count;
111 if (connections_traverse(pipe_enum_fn, &fenum) == -1) {
112 DEBUG(0,("net_enum_pipes: traverse of connections.tdb "
118 *count = fenum.count;
123 /*******************************************************************
124 ********************************************************************/
126 static void enum_file_fn( const struct share_mode_entry *e,
127 const char *sharepath, const char *fname,
130 struct file_enum_count *fenum =
131 (struct file_enum_count *)&private_data;
133 /* If the pid was not found delete the entry from connections.tdb */
135 if ( process_exists(e->pid) ) {
136 struct srvsvc_NetFileInfo3 *f;
137 int i = fenum->count;
139 struct byte_range_lock *brl;
144 f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, struct srvsvc_NetFileInfo3, i+1 );
146 DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
151 /* need to count the number of locks on a file */
156 if ( (brl = brl_get_locks_readonly(NULL,&fsp)) != NULL ) {
157 num_locks = brl->num_locks;
161 if ( strcmp( fname, "." ) == 0 ) {
162 pstr_sprintf( fullpath, "C:%s", sharepath );
164 pstr_sprintf( fullpath, "C:%s/%s", sharepath, fname );
166 string_replace( fullpath, '/', '\\' );
168 /* mask out create (what ever that is) */
169 permissions = e->share_access & (FILE_READ_DATA|FILE_WRITE_DATA);
171 fenum->info[i].fid = e->share_file_id;
172 fenum->info[i].permissions = permissions;
173 fenum->info[i].num_locks = num_locks;
174 if (!(fenum->info[i].user = talloc_strdup(
175 fenum->ctx, uidtoname(e->uid)))) {
176 /* There's not much we can do here. */
177 fenum->info[i].user = "";
179 if (!(fenum->info[i].path = talloc_strdup(
180 fenum->ctx, fullpath))) {
181 /* There's not much we can do here. */
182 fenum->info[i].path = "";
192 /*******************************************************************
193 ********************************************************************/
195 static WERROR net_enum_files( TALLOC_CTX *ctx, struct srvsvc_NetFileInfo3 **info,
196 uint32 *count, uint32 *resume )
198 struct file_enum_count f_enum_cnt;
200 f_enum_cnt.ctx = ctx;
201 f_enum_cnt.count = *count;
202 f_enum_cnt.info = *info;
204 share_mode_forall( enum_file_fn, (void *)&f_enum_cnt );
206 *info = f_enum_cnt.info;
207 *count = f_enum_cnt.count;
212 /*******************************************************************
213 Utility function to get the 'type' of a share from a share definition.
214 ********************************************************************/
215 static uint32 get_share_type(const struct share_params *params)
217 char *net_name = lp_servicename(params->service);
218 int len_net_name = strlen(net_name);
220 /* work out the share type */
221 uint32 type = STYPE_DISKTREE;
223 if (lp_print_ok(params->service))
225 if (strequal(lp_fstype(params->service), "IPC"))
227 if (net_name[len_net_name-1] == '$')
228 type |= STYPE_HIDDEN;
233 /*******************************************************************
234 Fill in a share info level 0 structure.
235 ********************************************************************/
237 static void init_srv_share_info_0(pipes_struct *p, struct srvsvc_NetShareInfo0 *sh0,
238 const struct share_params *params)
240 sh0->name = lp_servicename(params->service);
243 /*******************************************************************
244 Fill in a share info level 1 structure.
245 ********************************************************************/
247 static void init_srv_share_info_1(pipes_struct *p, struct srvsvc_NetShareInfo1 *sh1,
248 const struct share_params *params)
250 connection_struct *conn = p->conn;
252 sh1->comment = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
253 conn->user, conn->connectpath, conn->gid,
254 get_current_username(),
255 current_user_info.domain,
256 lp_comment(params->service));
258 sh1->name = lp_servicename(params->service);
259 sh1->type = get_share_type(params);
262 /*******************************************************************
263 Fill in a share info level 2 structure.
264 ********************************************************************/
266 static void init_srv_share_info_2(pipes_struct *p, struct srvsvc_NetShareInfo2 *sh2,
267 const struct share_params *params)
269 connection_struct *conn = p->conn;
272 int max_connections = lp_max_connections(params->service);
273 uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
275 char *net_name = lp_servicename(params->service);
277 remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
278 conn->user, conn->connectpath, conn->gid,
279 get_current_username(),
280 current_user_info.domain,
281 lp_comment(params->service));
282 path = talloc_asprintf(p->mem_ctx, "C:%s",
283 lp_pathname(params->service));
286 * Change / to \\ so that win2k will see it as a valid path. This was
287 * added to enable use of browsing in win2k add share dialog.
290 string_replace(path, '/', '\\');
292 count = count_current_connections( net_name, False );
293 sh2->name = net_name;
294 sh2->type = get_share_type(params);
295 sh2->comment = remark;
296 sh2->permissions = 0;
297 sh2->max_users = max_uses;
298 sh2->current_users = count;
303 /*******************************************************************
304 Map any generic bits to file specific bits.
305 ********************************************************************/
307 static void map_generic_share_sd_bits(SEC_DESC *psd)
310 SEC_ACL *ps_dacl = NULL;
319 for (i = 0; i < ps_dacl->num_aces; i++) {
320 SEC_ACE *psa = &ps_dacl->aces[i];
321 uint32 orig_mask = psa->access_mask;
323 se_map_generic(&psa->access_mask, &file_generic_mapping);
324 psa->access_mask |= orig_mask;
328 /*******************************************************************
329 Fill in a share info level 501 structure.
330 ********************************************************************/
332 static void init_srv_share_info_501(pipes_struct *p, struct srvsvc_NetShareInfo501 *sh501,
333 const struct share_params *params)
335 connection_struct *conn = p->conn;
337 const char *net_name = lp_servicename(params->service);
339 remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
340 conn->user, conn->connectpath, conn->gid,
341 get_current_username(),
342 current_user_info.domain,
343 lp_comment(params->service));
346 sh501->name = net_name;
347 sh501->type = get_share_type(params);
348 sh501->comment = remark;
349 sh501->csc_policy = (lp_csc_policy(params->service) << 4);
352 /*******************************************************************
353 Fill in a share info level 502 structure.
354 ********************************************************************/
356 static void init_srv_share_info_502(pipes_struct *p, struct srvsvc_NetShareInfo502 *sh502,
357 const struct share_params *params)
359 int max_connections = lp_max_connections(params->service);
360 uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
361 connection_struct *conn = p->conn;
368 TALLOC_CTX *ctx = p->mem_ctx;
373 net_name = lp_servicename(params->service);
374 count = count_current_connections( net_name, False );
376 remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
377 conn->user, conn->connectpath, conn->gid,
378 get_current_username(),
379 current_user_info.domain,
380 lp_comment(params->service));
382 path = talloc_asprintf(p->mem_ctx, "C:%s",
383 lp_pathname(params->service));
386 * Change / to \\ so that win2k will see it as a valid path. This was
387 * added to enable use of browsing in win2k add share dialog.
390 string_replace(path, '/', '\\');
392 sd = get_share_security(ctx, lp_servicename(params->service),
395 sh502->name = net_name;
396 sh502->type = get_share_type(params);
397 sh502->comment = remark;
399 sh502->password = "";
401 sh502->permissions = 0;
402 sh502->max_users = max_uses;
403 sh502->current_users = count;
407 /***************************************************************************
408 Fill in a share info level 1004 structure.
409 ***************************************************************************/
411 static void init_srv_share_info_1004(pipes_struct *p,
412 struct srvsvc_NetShareInfo1004* sh1004,
413 const struct share_params *params)
415 connection_struct *conn = p->conn;
418 remark = talloc_sub_advanced(p->mem_ctx, lp_servicename(SNUM(conn)),
419 conn->user, conn->connectpath, conn->gid,
420 get_current_username(),
421 current_user_info.domain,
422 lp_comment(params->service));
424 ZERO_STRUCTP(sh1004);
426 sh1004->comment = remark;
429 /***************************************************************************
430 Fill in a share info level 1005 structure.
431 ***************************************************************************/
433 static void init_srv_share_info_1005(pipes_struct *p,
434 struct srvsvc_NetShareInfo1005* sh1005,
435 const struct share_params *params)
437 sh1005->dfs_flags = 0;
439 if(lp_host_msdfs() && lp_msdfs_root(params->service))
441 SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
443 lp_csc_policy(params->service) << SHARE_1005_CSC_POLICY_SHIFT;
445 /***************************************************************************
446 Fill in a share info level 1006 structure.
447 ***************************************************************************/
449 static void init_srv_share_info_1006(pipes_struct *p,
450 struct srvsvc_NetShareInfo1006* sh1006,
451 const struct share_params *params)
453 sh1006->max_users = -1;
456 /***************************************************************************
457 Fill in a share info level 1007 structure.
458 ***************************************************************************/
460 static void init_srv_share_info_1007(pipes_struct *p,
461 struct srvsvc_NetShareInfo1007* sh1007,
462 const struct share_params *params)
466 ZERO_STRUCTP(sh1007);
468 sh1007->flags = flags;
469 sh1007->alternate_directory_name = "";
472 /*******************************************************************
473 Fill in a share info level 1501 structure.
474 ********************************************************************/
476 static void init_srv_share_info_1501(pipes_struct *p,
477 struct sec_desc_buf *sh1501,
478 const struct share_params *params)
482 TALLOC_CTX *ctx = p->mem_ctx;
484 ZERO_STRUCTP(sh1501);
486 sd = get_share_security(ctx, lp_servicename(params->service),
492 /*******************************************************************
493 True if it ends in '$'.
494 ********************************************************************/
496 static BOOL is_hidden_share(const struct share_params *params)
498 const char *net_name = lp_servicename(params->service);
500 return (net_name[strlen(net_name) - 1] == '$');
503 /*******************************************************************
504 Fill in a share info structure.
505 ********************************************************************/
507 static WERROR init_srv_share_info_ctr(pipes_struct *p,
508 union srvsvc_NetShareCtr *ctr,
509 uint32 info_level, uint32 *resume_hnd,
510 uint32 *total_entries, BOOL all_shares)
512 TALLOC_CTX *ctx = p->mem_ctx;
513 struct share_iterator *shares;
514 struct share_params *share;
515 WERROR result = WERR_NOMEM;
517 DEBUG(5,("init_srv_share_info_ctr\n"));
525 /* Ensure all the usershares are loaded. */
527 load_usershare_shares();
528 load_registry_shares();
533 if (!(shares = share_list_all(ctx))) {
534 DEBUG(5, ("Could not list shares\n"));
535 return WERR_ACCESS_DENIED;
538 switch (info_level) {
540 if (!(ctr->ctr0 = TALLOC_ZERO_P(
541 p->mem_ctx, struct srvsvc_NetShareCtr0))) {
546 if (!(ctr->ctr1 = TALLOC_ZERO_P(
547 p->mem_ctx, struct srvsvc_NetShareCtr1))) {
552 if (!(ctr->ctr2 = TALLOC_ZERO_P(
553 p->mem_ctx, struct srvsvc_NetShareCtr2))) {
558 if (!(ctr->ctr501 = TALLOC_ZERO_P(
559 p->mem_ctx, struct srvsvc_NetShareCtr501))) {
564 if (!(ctr->ctr502 = TALLOC_ZERO_P(
565 p->mem_ctx, struct srvsvc_NetShareCtr502))) {
570 if (!(ctr->ctr1004 = TALLOC_ZERO_P(
571 p->mem_ctx, struct srvsvc_NetShareCtr1004))) {
576 if (!(ctr->ctr1005 = TALLOC_ZERO_P(
577 p->mem_ctx, struct srvsvc_NetShareCtr1005))) {
582 if (!(ctr->ctr1006 = TALLOC_ZERO_P(
583 p->mem_ctx, struct srvsvc_NetShareCtr1006))) {
588 if (!(ctr->ctr1007 = TALLOC_ZERO_P(
589 p->mem_ctx, struct srvsvc_NetShareCtr1007))) {
594 if (!(ctr->ctr1501 = TALLOC_ZERO_P(
595 p->mem_ctx, struct srvsvc_NetShareCtr1501))) {
600 DEBUG(5,("init_srv_share_info_ctr: unsupported switch "
601 "value %d\n", info_level));
602 return WERR_UNKNOWN_LEVEL;
605 while ((share = next_share(shares)) != NULL) {
606 if (!lp_browseable(share->service)) {
609 if (!all_shares && is_hidden_share(share)) {
613 switch (info_level) {
616 struct srvsvc_NetShareInfo0 i;
617 init_srv_share_info_0(p, &i, share);
618 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo0, i,
619 &ctr->ctr0->array, &ctr->ctr0->count);
620 if (ctr->ctr0->array == NULL) {
623 *total_entries = ctr->ctr0->count;
629 struct srvsvc_NetShareInfo1 i;
630 init_srv_share_info_1(p, &i, share);
631 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1, i,
632 &ctr->ctr1->array, &ctr->ctr1->count);
633 if (ctr->ctr1->array == NULL) {
636 *total_entries = ctr->ctr1->count;
642 struct srvsvc_NetShareInfo2 i;
643 init_srv_share_info_2(p, &i, share);
644 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo2, i,
645 &ctr->ctr2->array, &ctr->ctr2->count);
646 if (ctr->ctr2->array == NULL) {
649 *total_entries = ctr->ctr2->count;
655 struct srvsvc_NetShareInfo501 i;
656 init_srv_share_info_501(p, &i, share);
657 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo501, i,
658 &ctr->ctr501->array, &ctr->ctr501->count);
659 if (ctr->ctr501->array == NULL) {
662 *total_entries = ctr->ctr501->count;
668 struct srvsvc_NetShareInfo502 i;
669 init_srv_share_info_502(p, &i, share);
670 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo502, i,
671 &ctr->ctr502->array, &ctr->ctr502->count);
672 if (ctr->ctr502->array == NULL) {
675 *total_entries = ctr->ctr502->count;
679 /* here for completeness but not currently used with enum
684 struct srvsvc_NetShareInfo1004 i;
685 init_srv_share_info_1004(p, &i, share);
686 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1004, i,
687 &ctr->ctr1004->array, &ctr->ctr1004->count);
688 if (ctr->ctr1004->array == NULL) {
691 *total_entries = ctr->ctr1004->count;
697 struct srvsvc_NetShareInfo1005 i;
698 init_srv_share_info_1005(p, &i, share);
699 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1005, i,
700 &ctr->ctr1005->array, &ctr->ctr1005->count);
701 if (ctr->ctr1005->array == NULL) {
704 *total_entries = ctr->ctr1005->count;
710 struct srvsvc_NetShareInfo1006 i;
711 init_srv_share_info_1006(p, &i, share);
712 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1006, i,
713 &ctr->ctr1006->array, &ctr->ctr1006->count);
714 if (ctr->ctr1006->array == NULL) {
717 *total_entries = ctr->ctr1006->count;
723 struct srvsvc_NetShareInfo1007 i;
724 init_srv_share_info_1007(p, &i, share);
725 ADD_TO_ARRAY(ctx, struct srvsvc_NetShareInfo1007, i,
726 &ctr->ctr1007->array, &ctr->ctr1007->count);
727 if (ctr->ctr1007->array == NULL) {
730 *total_entries = ctr->ctr1007->count;
736 struct sec_desc_buf i;
737 init_srv_share_info_1501(p, &i, share);
738 ADD_TO_ARRAY(ctx, struct sec_desc_buf, i,
739 &ctr->ctr1501->array, &ctr->ctr1501->count);
740 if (ctr->ctr1501->array == NULL) {
743 *total_entries = ctr->ctr1501->count;
757 /*******************************************************************
758 fill in a sess info level 0 structure.
759 ********************************************************************/
761 static void init_srv_sess_info_0(pipes_struct *p, struct srvsvc_NetSessCtr0 *ss0, uint32 *snum, uint32 *stot)
763 struct sessionid *session_list;
764 uint32 num_entries = 0;
765 (*stot) = list_sessions(p->mem_ctx, &session_list);
774 DEBUG(5,("init_srv_sess_0_ss0\n"));
776 ss0->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetSessInfo0, *stot);
779 for (; (*snum) < (*stot); (*snum)++) {
780 ss0->array[num_entries].client = session_list[(*snum)].remote_machine;
784 ss0->count = num_entries;
786 if ((*snum) >= (*stot)) {
796 /*******************************************************************
797 ********************************************************************/
799 static void sess_file_fn( const struct share_mode_entry *e,
800 const char *sharepath, const char *fname,
803 struct sess_file_count *sess = (struct sess_file_count *)private_data;
805 if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
812 /*******************************************************************
813 ********************************************************************/
815 static int net_count_files( uid_t uid, struct server_id pid )
817 struct sess_file_count s_file_cnt;
819 s_file_cnt.count = 0;
820 s_file_cnt.uid = uid;
821 s_file_cnt.pid = pid;
823 share_mode_forall( sess_file_fn, (void *)&s_file_cnt );
825 return s_file_cnt.count;
828 /*******************************************************************
829 fill in a sess info level 1 structure.
830 ********************************************************************/
832 static void init_srv_sess_info_1(pipes_struct *p, struct srvsvc_NetSessCtr1 *ss1, uint32 *snum, uint32 *stot)
834 struct sessionid *session_list;
835 uint32 num_entries = 0;
836 time_t now = time(NULL);
853 (*stot) = list_sessions(p->mem_ctx, &session_list);
855 ss1->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetSessInfo1, *stot);
857 for (; (*snum) < (*stot); (*snum)++) {
860 struct passwd *pw = sys_getpwnam(session_list[*snum].username);
864 DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
865 session_list[*snum].username));
869 connect_time = (uint32)(now - session_list[*snum].connect_start);
870 num_files = net_count_files(pw->pw_uid, session_list[*snum].pid);
871 guest = strequal( session_list[*snum].username, lp_guestaccount() );
873 if (!(ss1->array[num_entries].client = talloc_strdup(
874 ss1->array, session_list[*snum].remote_machine))) {
875 ss1->array[num_entries].client = "";
877 if (!(ss1->array[num_entries].user = talloc_strdup(
878 ss1->array, session_list[*snum].username))) {
879 ss1->array[num_entries].user = "";
881 ss1->array[num_entries].num_open = num_files;
882 ss1->array[num_entries].time = connect_time;
883 ss1->array[num_entries].idle_time = 0;
884 ss1->array[num_entries].user_flags = guest;
889 ss1->count = num_entries;
891 if ((*snum) >= (*stot)) {
896 /*******************************************************************
897 makes a SRV_R_NET_SESS_ENUM structure.
898 ********************************************************************/
900 static WERROR init_srv_sess_info_ctr(pipes_struct *p, union srvsvc_NetSessCtr *ctr,
901 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
903 WERROR status = WERR_OK;
904 DEBUG(5,("init_srv_sess_info_ctr: %d\n", __LINE__));
906 switch (switch_value) {
908 ctr->ctr0 = talloc(p->mem_ctx, struct srvsvc_NetSessCtr0);
909 init_srv_sess_info_0(p, ctr->ctr0, resume_hnd, total_entries);
912 ctr->ctr1 = talloc(p->mem_ctx, struct srvsvc_NetSessCtr1);
913 init_srv_sess_info_1(p, ctr->ctr1, resume_hnd, total_entries);
916 DEBUG(5,("init_srv_sess_info_ctr: unsupported switch value %d\n", switch_value));
917 if (resume_hnd != NULL)
919 (*total_entries) = 0;
921 status = WERR_UNKNOWN_LEVEL;
928 /*******************************************************************
929 fill in a conn info level 0 structure.
930 ********************************************************************/
932 static void init_srv_conn_info_0(pipes_struct *p, struct srvsvc_NetConnCtr0 *ss0, uint32 *snum, uint32 *stot)
934 uint32 num_entries = 0;
943 DEBUG(5,("init_srv_conn_0_ss0\n"));
946 ss0->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetConnInfo0, *stot);
947 for (; (*snum) < (*stot); (*snum)++) {
949 ss0->array[num_entries].conn_id = (*stot);
951 /* move on to creating next connection */
952 /* move on to creating next conn */
956 ss0->count = num_entries;
958 if ((*snum) >= (*stot)) {
970 /*******************************************************************
971 fill in a conn info level 1 structure.
972 ********************************************************************/
974 static void init_srv_conn_info_1(pipes_struct *p, struct srvsvc_NetConnCtr1 *ss1, uint32 *snum, uint32 *stot)
976 uint32 num_entries = 0;
985 DEBUG(5,("init_srv_conn_1_ss1\n"));
988 ss1->array = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetConnInfo1, *stot);
989 for (; (*snum) < (*stot); (*snum)++) {
990 ss1->array[num_entries].conn_id = (*stot);
991 ss1->array[num_entries].conn_type = 0x3;
992 ss1->array[num_entries].num_open = 1;
993 ss1->array[num_entries].num_users = 1;
994 ss1->array[num_entries].conn_time = 3;
995 ss1->array[num_entries].user = "dummy_user";
996 ss1->array[num_entries].share = "IPC$";
998 /* move on to creating next connection */
999 /* move on to creating next conn */
1003 ss1->count = num_entries;
1005 if ((*snum) >= (*stot)) {
1017 /*******************************************************************
1018 makes a SRV_R_NET_CONN_ENUM structure.
1019 ********************************************************************/
1021 static WERROR init_srv_conn_info_ctr(pipes_struct *p, union srvsvc_NetConnCtr *ctr,
1022 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
1024 WERROR status = WERR_OK;
1025 DEBUG(5,("init_srv_conn_info_ctr: %d\n", __LINE__));
1027 switch (switch_value) {
1029 init_srv_conn_info_0(p, ctr->ctr0, resume_hnd, total_entries);
1032 init_srv_conn_info_1(p, ctr->ctr1, resume_hnd, total_entries);
1035 DEBUG(5,("init_srv_conn_info_ctr: unsupported switch value %d\n", switch_value));
1038 (*total_entries) = 0;
1039 status = WERR_UNKNOWN_LEVEL;
1046 /*******************************************************************
1047 makes a SRV_R_NET_FILE_ENUM structure.
1048 ********************************************************************/
1050 static WERROR net_file_enum_3(pipes_struct *p, union srvsvc_NetFileCtr *ctr, uint32 *resume_hnd, uint32 *num_entries )
1052 TALLOC_CTX *ctx = get_talloc_ctx();
1055 /* TODO -- Windows enumerates
1057 (c) open directories and files */
1059 ctr->ctr3 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetFileCtr3);
1061 status = net_enum_files( ctx, &ctr->ctr3->array, num_entries, resume_hnd );
1062 if ( !W_ERROR_IS_OK(status))
1065 status = net_enum_pipes( ctx, &ctr->ctr3->array, num_entries, resume_hnd );
1066 if ( !W_ERROR_IS_OK(status))
1069 ctr->ctr3->count = *num_entries;
1074 /*******************************************************************
1075 *******************************************************************/
1077 WERROR _srvsvc_NetFileEnum(pipes_struct *p, struct srvsvc_NetFileEnum *r)
1079 switch ( *r->in.level ) {
1081 return net_file_enum_3(p, r->in.ctr, r->in.resume_handle, r->out.totalentries );
1083 return WERR_UNKNOWN_LEVEL;
1089 /*******************************************************************
1091 ********************************************************************/
1093 WERROR _srvsvc_NetSrvGetInfo(pipes_struct *p, struct srvsvc_NetSrvGetInfo *r)
1095 WERROR status = WERR_OK;
1097 ZERO_STRUCTP(r->out.info);
1099 DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1101 if (!pipe_access_check(p)) {
1102 DEBUG(3, ("access denied to srv_net_srv_get_info\n"));
1103 return WERR_ACCESS_DENIED;
1106 switch (r->in.level) {
1108 /* Technically level 102 should only be available to
1109 Administrators but there isn't anything super-secret
1110 here, as most of it is made up. */
1113 r->out.info->info102 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo102);
1115 r->out.info->info102->platform_id = 500;
1116 r->out.info->info102->version_major = lp_major_announce_version();
1117 r->out.info->info102->version_minor = lp_minor_announce_version();
1118 r->out.info->info102->server_name = global_myname();
1119 r->out.info->info102->server_type = lp_default_server_announce();
1120 r->out.info->info102->userpath = "C:\\";
1121 r->out.info->info102->licenses = 10000;
1122 r->out.info->info102->anndelta = 3000;
1123 r->out.info->info102->disc = 0xf;
1124 r->out.info->info102->users = 0xffffffff;
1125 r->out.info->info102->hidden = 0;
1126 r->out.info->info102->announce = 240;
1127 r->out.info->info102->comment = lp_serverstring();
1130 r->out.info->info101 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo101);
1131 r->out.info->info101->platform_id = 500;
1132 r->out.info->info101->server_name = global_myname();
1133 r->out.info->info101->version_major = lp_major_announce_version();
1134 r->out.info->info101->version_minor = lp_minor_announce_version();
1135 r->out.info->info101->server_type = lp_default_server_announce();
1136 r->out.info->info101->comment = lp_serverstring();
1139 r->out.info->info100 = TALLOC_ZERO_P(p->mem_ctx, struct srvsvc_NetSrvInfo100);
1140 r->out.info->info100->platform_id = 500;
1141 r->out.info->info100->server_name = global_myname();
1144 return WERR_UNKNOWN_LEVEL;
1148 DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1153 /*******************************************************************
1155 ********************************************************************/
1157 WERROR _srvsvc_NetSrvSetInfo(pipes_struct *p, struct srvsvc_NetSrvSetInfo *r)
1159 /* Set up the net server set info structure. */
1160 if (r->out.parm_error) {
1161 *r->out.parm_error = 0;
1166 /*******************************************************************
1168 ********************************************************************/
1170 WERROR _srvsvc_NetConnEnum(pipes_struct *p, struct srvsvc_NetConnEnum *r)
1172 DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
1174 ZERO_STRUCTP(r->out.ctr);
1177 return init_srv_conn_info_ctr(p, r->out.ctr, *r->in.level, r->in.resume_handle, r->out.totalentries);
1180 /*******************************************************************
1182 ********************************************************************/
1184 WERROR _srvsvc_NetSessEnum(pipes_struct *p, struct srvsvc_NetSessEnum *r)
1186 DEBUG(5,("_srv_net_sess_enum: %d\n", __LINE__));
1188 ZERO_STRUCTP(r->out.ctr);
1191 return init_srv_sess_info_ctr(p, r->out.ctr,
1193 r->in.resume_handle,
1194 r->out.totalentries);
1197 /*******************************************************************
1199 ********************************************************************/
1201 WERROR _srvsvc_NetSessDel(pipes_struct *p, struct srvsvc_NetSessDel *r)
1203 struct sessionid *session_list;
1204 int num_sessions, snum;
1207 char *machine = talloc_strdup(p->mem_ctx, r->in.server_unc);
1209 /* strip leading backslashes if any */
1210 while (machine[0] == '\\') {
1211 memmove(machine, &machine[1], strlen(machine));
1214 num_sessions = list_sessions(p->mem_ctx, &session_list);
1216 DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
1218 status = WERR_ACCESS_DENIED;
1220 /* fail out now if you are not root or not a domain admin */
1222 if ((p->pipe_user.ut.uid != sec_initial_uid()) &&
1223 ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
1228 for (snum = 0; snum < num_sessions; snum++) {
1230 if ((strequal(session_list[snum].username, r->in.user) || r->in.user[0] == '\0' ) &&
1231 strequal(session_list[snum].remote_machine, machine)) {
1234 ntstat = messaging_send(smbd_messaging_context(),
1235 session_list[snum].pid,
1236 MSG_SHUTDOWN, &data_blob_null);
1238 if (NT_STATUS_IS_OK(ntstat))
1243 DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
1249 /*******************************************************************
1251 ********************************************************************/
1253 WERROR _srvsvc_NetShareEnumAll(pipes_struct *p, struct srvsvc_NetShareEnumAll *r)
1255 DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1257 if (!pipe_access_check(p)) {
1258 DEBUG(3, ("access denied to srv_net_share_enum_all\n"));
1259 return WERR_ACCESS_DENIED;
1262 /* Create the list of shares for the response. */
1263 return init_srv_share_info_ctr(p, r->out.ctr, *r->in.level,
1264 r->in.resume_handle, r->out.totalentries, True);
1267 /*******************************************************************
1269 ********************************************************************/
1271 WERROR _srvsvc_NetShareEnum(pipes_struct *p, struct srvsvc_NetShareEnum *r)
1273 DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1275 if (!pipe_access_check(p)) {
1276 DEBUG(3, ("access denied to srv_net_share_enum\n"));
1277 return WERR_ACCESS_DENIED;
1280 /* Create the list of shares for the response. */
1281 return init_srv_share_info_ctr(p, r->out.ctr, *r->in.level,
1282 r->in.resume_handle, r->out.totalentries, False);
1285 /*******************************************************************
1287 ********************************************************************/
1289 WERROR _srvsvc_NetShareGetInfo(pipes_struct *p, struct srvsvc_NetShareGetInfo *r)
1291 const struct share_params *params;
1293 params = get_share_params(p->mem_ctx, r->in.share_name);
1295 if (params != NULL) {
1296 switch (r->in.level) {
1298 r->out.info->info0 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo0);
1299 init_srv_share_info_0(p, r->out.info->info0, params);
1302 r->out.info->info1 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1);
1303 init_srv_share_info_1(p, r->out.info->info1, params);
1306 r->out.info->info2 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo2);
1307 init_srv_share_info_2(p, r->out.info->info2, params);
1310 r->out.info->info501 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo501);
1311 init_srv_share_info_501(p, r->out.info->info501, params);
1314 r->out.info->info502 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo502);
1315 init_srv_share_info_502(p, r->out.info->info502, params);
1318 /* here for completeness */
1320 r->out.info->info1004 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1004);
1321 init_srv_share_info_1004(p, r->out.info->info1004, params);
1324 r->out.info->info1005 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1005);
1325 init_srv_share_info_1005(p, r->out.info->info1005, params);
1328 /* here for completeness 1006 - 1501 */
1330 r->out.info->info1006 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1006);
1331 init_srv_share_info_1006(p, r->out.info->info1006,
1335 r->out.info->info1007 = talloc(p->mem_ctx, struct srvsvc_NetShareInfo1007);
1336 init_srv_share_info_1007(p, r->out.info->info1007,
1340 r->out.info->info1501 = talloc(p->mem_ctx, struct sec_desc_buf);
1341 init_srv_share_info_1501(p, r->out.info->info1501,
1345 DEBUG(5,("init_srv_net_share_get_info: unsupported "
1346 "switch value %d\n", r->in.level));
1347 return WERR_UNKNOWN_LEVEL;
1351 return WERR_INVALID_NAME;
1357 /*******************************************************************
1358 Check a given DOS pathname is valid for a share.
1359 ********************************************************************/
1361 char *valid_share_pathname(char *dos_pathname)
1365 /* Convert any '\' paths to '/' */
1366 unix_format(dos_pathname);
1367 unix_clean_name(dos_pathname);
1369 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1371 if (strlen(dos_pathname) > 2 && ptr[1] == ':' && ptr[0] != '/')
1374 /* Only absolute paths allowed. */
1381 static void setval_helper(struct registry_key *key, const char *name,
1382 const char *value, WERROR *err)
1384 struct registry_value val;
1386 if (!W_ERROR_IS_OK(*err)) {
1392 val.v.sz.str = CONST_DISCARD(char *, value);
1393 val.v.sz.len = strlen(value)+1;
1395 *err = reg_setvalue(key, name, &val);
1398 static WERROR add_share(const char *share_name, const char *path,
1399 const char *comment, uint32 max_connections,
1400 const struct nt_user_token *token,
1403 if (lp_add_share_cmd() && *lp_add_share_cmd()) {
1407 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1408 lp_add_share_cmd(), dyn_CONFIGFILE, share_name,
1409 path, comment, max_connections) == -1) {
1413 DEBUG(10,("add_share: Running [%s]\n", command ));
1415 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1420 if ( (ret = smbrun(command, NULL)) == 0 ) {
1421 /* Tell everyone we updated smb.conf. */
1422 message_send_all(smbd_messaging_context(),
1423 MSG_SMB_CONF_UPDATED,
1430 /********* END SeDiskOperatorPrivilege BLOCK *********/
1432 DEBUG(3,("_srv_net_share_add: Running [%s] returned (%d)\n",
1436 * No fallback to registry shares, the user did define a add
1437 * share command, so fail here.
1441 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1444 if (lp_registry_shares()) {
1446 struct registry_key *key;
1447 enum winreg_CreateAction action;
1449 TALLOC_CTX *mem_ctx;
1451 if (!(keyname = talloc_asprintf(NULL, "%s\\%s", KEY_SMBCONF,
1456 mem_ctx = (TALLOC_CTX *)keyname;
1458 err = reg_create_path(mem_ctx, keyname, REG_KEY_WRITE,
1459 is_disk_op ? get_root_nt_token():token,
1462 if (action != REG_CREATED_NEW_KEY) {
1463 err = WERR_ALREADY_EXISTS;
1466 if (!W_ERROR_IS_OK(err)) {
1467 TALLOC_FREE(mem_ctx);
1471 setval_helper(key, "path", path, &err);
1472 if ((comment != NULL) && (comment[0] != '\0')) {
1473 setval_helper(key, "comment", comment, &err);
1475 if (max_connections != 0) {
1477 snprintf(tmp, sizeof(tmp), "%d", max_connections);
1478 setval_helper(key, "max connections", tmp, &err);
1481 if (!W_ERROR_IS_OK(err)) {
1483 * Hmmmm. We'd need transactions on the registry to
1484 * get this right....
1486 reg_delete_path(is_disk_op ? get_root_nt_token():token,
1489 TALLOC_FREE(mem_ctx);
1493 return WERR_ACCESS_DENIED;
1496 static WERROR delete_share(const char *sharename,
1497 const struct nt_user_token *token,
1500 if (lp_delete_share_cmd() && *lp_delete_share_cmd()) {
1504 if (asprintf(&command, "%s \"%s\" \"%s\"",
1505 lp_delete_share_cmd(), dyn_CONFIGFILE,
1510 DEBUG(10,("delete_share: Running [%s]\n", command ));
1512 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1517 if ( (ret = smbrun(command, NULL)) == 0 ) {
1518 /* Tell everyone we updated smb.conf. */
1519 message_send_all(smbd_messaging_context(),
1520 MSG_SMB_CONF_UPDATED,
1527 /********* END SeDiskOperatorPrivilege BLOCK *********/
1531 DEBUG(3,("_srv_net_share_del: Running [%s] returned (%d)\n",
1533 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1536 if (lp_registry_shares()) {
1540 if (asprintf(&keyname, "%s\\%s", KEY_SMBCONF,
1545 err = reg_delete_path(is_disk_op ? get_root_nt_token():token,
1551 return WERR_ACCESS_DENIED;
1554 static WERROR change_share(const char *share_name, const char *path,
1555 const char *comment, uint32 max_connections,
1556 const struct nt_user_token *token,
1559 if (lp_change_share_cmd() && *lp_change_share_cmd()) {
1563 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\" %d",
1564 lp_change_share_cmd(), dyn_CONFIGFILE, share_name,
1565 path, comment, max_connections) == -1) {
1569 DEBUG(10,("_srv_net_share_set_info: Running [%s]\n", command));
1571 /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
1576 if ( (ret = smbrun(command, NULL)) == 0 ) {
1577 /* Tell everyone we updated smb.conf. */
1578 message_send_all(smbd_messaging_context(),
1579 MSG_SMB_CONF_UPDATED,
1586 /********* END SeDiskOperatorPrivilege BLOCK *********/
1588 DEBUG(3,("_srv_net_share_set_info: Running [%s] returned "
1589 "(%d)\n", command, ret ));
1593 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
1596 if (lp_registry_shares()) {
1598 struct registry_key *key;
1600 TALLOC_CTX *mem_ctx;
1602 if (!(keyname = talloc_asprintf(NULL, "%s\\%s", KEY_SMBCONF,
1607 mem_ctx = (TALLOC_CTX *)keyname;
1609 err = reg_open_path(mem_ctx, keyname, REG_KEY_WRITE,
1610 is_disk_op ? get_root_nt_token():token,
1612 if (!W_ERROR_IS_OK(err)) {
1613 TALLOC_FREE(mem_ctx);
1617 setval_helper(key, "path", path, &err);
1619 reg_deletevalue(key, "comment");
1620 if ((comment != NULL) && (comment[0] != '\0')) {
1621 setval_helper(key, "comment", comment, &err);
1624 reg_deletevalue(key, "max connections");
1625 if (max_connections != 0) {
1627 snprintf(tmp, sizeof(tmp), "%d", max_connections);
1628 setval_helper(key, "max connections", tmp, &err);
1631 TALLOC_FREE(mem_ctx);
1635 return WERR_ACCESS_DENIED;
1638 /*******************************************************************
1639 Net share set info. Modify share details.
1640 ********************************************************************/
1642 WERROR _srvsvc_NetShareSetInfo(pipes_struct *p, struct srvsvc_NetShareSetInfo *r)
1649 SEC_DESC *psd = NULL;
1650 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1651 BOOL is_disk_op = False;
1652 int max_connections = 0;
1653 fstring tmp_share_name;
1655 DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1657 if (r->out.parm_error) {
1658 *r->out.parm_error = 0;
1661 if ( strequal(r->in.share_name,"IPC$")
1662 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1663 || strequal(r->in.share_name,"global") )
1665 return WERR_ACCESS_DENIED;
1668 fstrcpy(tmp_share_name, r->in.share_name);
1669 snum = find_service(tmp_share_name);
1671 /* Does this share exist ? */
1673 return WERR_NET_NAME_NOT_FOUND;
1675 /* No change to printer shares. */
1676 if (lp_print_ok(snum))
1677 return WERR_ACCESS_DENIED;
1679 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1682 /* fail out now if you are not root and not a disk op */
1684 if ( p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
1685 return WERR_ACCESS_DENIED;
1687 switch (r->in.level) {
1689 pstrcpy(pathname, lp_pathname(snum));
1690 pstrcpy(comment, r->in.info.info1->comment);
1691 type = r->in.info.info1->type;
1695 pstrcpy(comment, r->in.info.info2->comment);
1696 pstrcpy(pathname, r->in.info.info2->path);
1697 type = r->in.info.info2->type;
1698 max_connections = (r->in.info.info2->max_users == 0xffffffff) ?
1699 0 : r->in.info.info2->max_users;
1703 pstrcpy(comment, r->in.info.info502->comment);
1704 pstrcpy(pathname, r->in.info.info502->path);
1705 type = r->in.info.info502->type;
1706 psd = r->in.info.info502->sd;
1707 map_generic_share_sd_bits(psd);
1710 pstrcpy(pathname, lp_pathname(snum));
1711 pstrcpy(comment, r->in.info.info1004->comment);
1712 type = STYPE_DISKTREE;
1715 /* XP re-sets the csc policy even if it wasn't changed by the
1716 user, so we must compare it to see if it's what is set in
1717 smb.conf, so that we can contine other ops like setting
1719 if (((r->in.info.info1005->dfs_flags &
1720 SHARE_1005_CSC_POLICY_MASK) >>
1721 SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
1724 DEBUG(3, ("_srv_net_share_set_info: client is trying "
1725 "to change csc policy from the network; "
1726 "must be done with smb.conf\n"));
1727 return WERR_ACCESS_DENIED;
1731 return WERR_ACCESS_DENIED;
1733 pstrcpy(pathname, lp_pathname(snum));
1734 pstrcpy(comment, lp_comment(snum));
1735 psd = r->in.info.info1501->sd;
1736 map_generic_share_sd_bits(psd);
1737 type = STYPE_DISKTREE;
1740 DEBUG(5,("_srv_net_share_set_info: unsupported switch value "
1741 "%d\n", r->in.level));
1742 return WERR_UNKNOWN_LEVEL;
1745 /* We can only modify disk shares. */
1746 if (type != STYPE_DISKTREE)
1747 return WERR_ACCESS_DENIED;
1749 /* Check if the pathname is valid. */
1750 if (!(path = valid_share_pathname( pathname )))
1751 return WERR_OBJECT_PATH_INVALID;
1753 /* Ensure share name, pathname and comment don't contain '"'
1755 string_replace(tmp_share_name, '"', ' ');
1756 string_replace(path, '"', ' ');
1757 string_replace(comment, '"', ' ');
1759 DEBUG(10,("_srv_net_share_set_info: change share command = %s\n",
1760 lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1762 /* Only call modify function if something changed. */
1764 if (strcmp(path, lp_pathname(snum))
1765 || strcmp(comment, lp_comment(snum))
1766 || (lp_max_connections(snum) != max_connections) ) {
1769 err = change_share(tmp_share_name, path, comment,
1770 max_connections, p->pipe_user.nt_user_token,
1773 if (!W_ERROR_IS_OK(err)) {
1778 /* Replace SD if changed. */
1783 old_sd = get_share_security(p->mem_ctx, lp_servicename(snum),
1786 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1787 if (!set_share_security(r->in.share_name, psd)) {
1788 DEBUG(0,("_srv_net_share_set_info: Failed to "
1789 "change security info in share %s.\n",
1790 r->in.share_name ));
1795 DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1801 /*******************************************************************
1802 Net share add. Call 'add_share_command "sharename" "pathname"
1803 "comment" "max connections = "
1804 ********************************************************************/
1806 WERROR _srvsvc_NetShareAdd(pipes_struct *p, struct srvsvc_NetShareAdd *r)
1813 SEC_DESC *psd = NULL;
1814 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1816 uint32 max_connections = 0;
1819 DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1821 if (r->out.parm_error) {
1822 *r->out.parm_error = 0;
1825 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1828 if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
1829 return WERR_ACCESS_DENIED;
1831 switch (r->in.level) {
1833 /* No path. Not enough info in a level 0 to do anything. */
1834 return WERR_ACCESS_DENIED;
1836 /* Not enough info in a level 1 to do anything. */
1837 return WERR_ACCESS_DENIED;
1839 pstrcpy(share_name, r->in.info.info2->name);
1840 pstrcpy(comment, r->in.info.info2->comment);
1841 pstrcpy(pathname, r->in.info.info2->path);
1842 max_connections = (r->in.info.info2->max_users == 0xffffffff) ?
1843 0 : r->in.info.info2->max_users;
1844 type = r->in.info.info2->type;
1847 /* No path. Not enough info in a level 501 to do anything. */
1848 return WERR_ACCESS_DENIED;
1850 pstrcpy(share_name, r->in.info.info502->name);
1851 pstrcpy(comment, r->in.info.info502->comment);
1852 pstrcpy(pathname, r->in.info.info502->path);
1853 type = r->in.info.info502->type;
1854 psd = r->in.info.info502->sd;
1855 map_generic_share_sd_bits(psd);
1858 /* none of the following contain share names. NetShareAdd
1859 * does not have a separate parameter for the share name */
1865 return WERR_ACCESS_DENIED;
1867 /* DFS only level. */
1868 return WERR_ACCESS_DENIED;
1870 DEBUG(5,("_srv_net_share_add: unsupported switch value %d\n",
1872 return WERR_UNKNOWN_LEVEL;
1875 /* check for invalid share names */
1877 if ( !validate_net_name( share_name, INVALID_SHARENAME_CHARS,
1878 sizeof(share_name) ) ) {
1879 DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n",
1881 return WERR_INVALID_NAME;
1884 if ( strequal(share_name,"IPC$") || strequal(share_name,"global")
1885 || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") ) )
1887 return WERR_ACCESS_DENIED;
1890 if (get_share_params(p->mem_ctx, share_name) != NULL) {
1891 /* Share already exists. */
1892 return WERR_ALREADY_EXISTS;
1895 /* We can only add disk shares. */
1896 if (type != STYPE_DISKTREE)
1897 return WERR_ACCESS_DENIED;
1899 /* Check if the pathname is valid. */
1900 if (!(path = valid_share_pathname( pathname )))
1901 return WERR_OBJECT_PATH_INVALID;
1903 /* Ensure share name, pathname and comment don't contain '"'
1906 string_replace(share_name, '"', ' ');
1907 string_replace(path, '"', ' ');
1908 string_replace(comment, '"', ' ');
1910 err = add_share(share_name, path, comment, max_connections,
1911 p->pipe_user.nt_user_token, is_disk_op);
1913 if (!W_ERROR_IS_OK(err)) {
1918 if (!set_share_security(share_name, psd)) {
1919 DEBUG(0,("_srv_net_share_add: Failed to add security "
1920 "info to share %s.\n", share_name ));
1925 * We don't call reload_services() here, the message will
1926 * cause this to be done before the next packet is read
1927 * from the client. JRA.
1930 DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1935 /*******************************************************************
1936 Net share delete. Call "delete share command" with the share name as
1938 ********************************************************************/
1940 WERROR _srvsvc_NetShareDel(pipes_struct *p, struct srvsvc_NetShareDel *r)
1942 struct share_params *params;
1943 SE_PRIV se_diskop = SE_DISK_OPERATOR;
1947 DEBUG(5,("_srv_net_share_del: %d\n", __LINE__));
1949 if ( strequal(r->in.share_name, "IPC$")
1950 || ( lp_enable_asu_support() && strequal(r->in.share_name,"ADMIN$") )
1951 || strequal(r->in.share_name, "global") )
1953 return WERR_ACCESS_DENIED;
1956 if (!(params = get_share_params(p->mem_ctx, r->in.share_name))) {
1957 return WERR_NO_SUCH_SHARE;
1960 /* No change to printer shares. */
1961 if (lp_print_ok(params->service))
1962 return WERR_ACCESS_DENIED;
1964 is_disk_op = user_has_privileges( p->pipe_user.nt_user_token,
1967 if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op )
1968 return WERR_ACCESS_DENIED;
1970 err = delete_share(lp_servicename(params->service),
1971 p->pipe_user.nt_user_token, is_disk_op);
1973 if (!W_ERROR_IS_OK(err)) {
1977 /* Delete the SD in the database. */
1978 delete_share_security(params);
1980 lp_killservice(params->service);
1985 WERROR _srvsvc_NetShareDelSticky(pipes_struct *p, struct srvsvc_NetShareDelSticky *r)
1987 struct srvsvc_NetShareDel s;
1989 DEBUG(5,("_srv_net_share_del_stick: %d\n", __LINE__));
1991 s.in.server_unc = r->in.server_unc;
1992 s.in.share_name = r->in.share_name;
1993 s.in.reserved = r->in.reserved;
1995 return _srvsvc_NetShareDel(p, &s);
1998 /*******************************************************************
2000 ********************************************************************/
2002 WERROR _srvsvc_NetRemoteTOD(pipes_struct *p, struct srvsvc_NetRemoteTOD *r)
2005 time_t unixdate = time(NULL);
2006 WERROR status = WERR_OK;
2008 /* We do this call first as if we do it *after* the gmtime call
2009 it overwrites the pointed-to values. JRA */
2011 uint32 zone = get_time_zone(unixdate)/60;
2013 DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
2015 t = gmtime(&unixdate);
2018 r->out.info->elapsed = unixdate;
2019 r->out.info->msecs = 0;
2020 r->out.info->hours = t->tm_hour;
2021 r->out.info->mins = t->tm_min;
2022 r->out.info->secs = t->tm_sec;
2023 r->out.info->hunds = 0;
2024 r->out.info->timezone = zone;
2025 r->out.info->tinterval = 10000;
2026 r->out.info->day = t->tm_mday;
2027 r->out.info->month = t->tm_mon + 1;
2028 r->out.info->year = 1900+t->tm_year;
2029 r->out.info->weekday = t->tm_wday;
2031 DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
2036 /***********************************************************************************
2037 Win9x NT tools get security descriptor.
2038 ***********************************************************************************/
2040 WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecurity *r)
2042 SEC_DESC *psd = NULL;
2045 files_struct *fsp = NULL;
2048 connection_struct *conn = NULL;
2049 BOOL became_user = False;
2050 WERROR status = WERR_OK;
2056 /* Null password is ok - we are already an authenticated user... */
2057 null_pw = data_blob_null;
2060 conn = make_connection(r->in.share, null_pw, "A:", p->pipe_user.vuid, &nt_status);
2064 DEBUG(3,("_srv_net_file_query_secdesc: Unable to connect to %s\n", r->in.share));
2065 status = ntstatus_to_werror(nt_status);
2069 if (!become_user(conn, conn->vuid)) {
2070 DEBUG(0,("_srv_net_file_query_secdesc: Can't become connected user!\n"));
2071 status = WERR_ACCESS_DENIED;
2076 pstrcpy(tmp_file, r->in.file);
2077 nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
2078 if (!NT_STATUS_IS_OK(nt_status)) {
2079 DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", r->in.file));
2080 status = WERR_ACCESS_DENIED;
2084 nt_status = check_name(conn, r->in.file);
2085 if (!NT_STATUS_IS_OK(nt_status)) {
2086 DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", r->in.file));
2087 status = WERR_ACCESS_DENIED;
2091 nt_status = open_file_stat(conn, NULL, r->in.file, &st, &fsp);
2092 if (!NT_STATUS_IS_OK(nt_status)) {
2093 /* Perhaps it is a directory */
2094 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2095 nt_status = open_directory(conn, NULL, r->in.file, &st,
2096 READ_CONTROL_ACCESS,
2097 FILE_SHARE_READ|FILE_SHARE_WRITE,
2100 FILE_ATTRIBUTE_DIRECTORY,
2103 if (!NT_STATUS_IS_OK(nt_status)) {
2104 DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", r->in.file));
2105 status = WERR_ACCESS_DENIED;
2110 sd_size = SMB_VFS_GET_NT_ACL(fsp, fsp->fsp_name, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
2113 DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", r->in.file));
2114 status = WERR_ACCESS_DENIED;
2118 r->out.sd_buf->sd_size= sd_size;
2119 r->out.sd_buf->sd = psd;
2121 psd->dacl->revision = (uint16) NT4_ACL_REVISION;
2123 close_file(fsp, NORMAL_CLOSE);
2125 close_cnum(conn, p->pipe_user.vuid);
2131 close_file(fsp, NORMAL_CLOSE);
2138 close_cnum(conn, p->pipe_user.vuid);
2143 /***********************************************************************************
2144 Win9x NT tools set security descriptor.
2145 ***********************************************************************************/
2147 WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecurity *r)
2150 files_struct *fsp = NULL;
2153 connection_struct *conn = NULL;
2154 BOOL became_user = False;
2155 WERROR status = WERR_OK;
2160 /* Null password is ok - we are already an authenticated user... */
2161 null_pw = data_blob_null;
2164 conn = make_connection(r->in.share, null_pw, "A:", p->pipe_user.vuid, &nt_status);
2168 DEBUG(3,("_srv_net_file_set_secdesc: Unable to connect to %s\n", r->in.share));
2169 status = ntstatus_to_werror(nt_status);
2173 if (!become_user(conn, conn->vuid)) {
2174 DEBUG(0,("_srv_net_file_set_secdesc: Can't become connected user!\n"));
2175 status = WERR_ACCESS_DENIED;
2180 pstrcpy(tmp_file, r->in.file);
2181 nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
2182 if (!NT_STATUS_IS_OK(nt_status)) {
2183 DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", r->in.file));
2184 status = WERR_ACCESS_DENIED;
2188 nt_status = check_name(conn, r->in.file);
2189 if (!NT_STATUS_IS_OK(nt_status)) {
2190 DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", r->in.file));
2191 status = WERR_ACCESS_DENIED;
2196 nt_status = open_file_stat(conn, NULL, r->in.file, &st, &fsp);
2198 if (!NT_STATUS_IS_OK(nt_status)) {
2199 /* Perhaps it is a directory */
2200 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
2201 nt_status = open_directory(conn, NULL, r->in.file, &st,
2202 FILE_READ_ATTRIBUTES,
2203 FILE_SHARE_READ|FILE_SHARE_WRITE,
2206 FILE_ATTRIBUTE_DIRECTORY,
2209 if (!NT_STATUS_IS_OK(nt_status)) {
2210 DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", r->in.file));
2211 status = WERR_ACCESS_DENIED;
2216 nt_status = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, r->in.securityinformation, r->in.sd_buf.sd);
2218 if (!NT_STATUS_IS_OK(nt_status)) {
2219 DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", r->in.file));
2220 status = WERR_ACCESS_DENIED;
2224 close_file(fsp, NORMAL_CLOSE);
2226 close_cnum(conn, p->pipe_user.vuid);
2232 close_file(fsp, NORMAL_CLOSE);
2240 close_cnum(conn, p->pipe_user.vuid);
2246 /***********************************************************************************
2247 It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
2248 We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
2249 These disks would the disks listed by this function.
2250 Users could then create shares relative to these disks. Watch out for moving these disks around.
2251 "Nigel Williams" <nigel@veritas.com>.
2252 ***********************************************************************************/
2254 static const char *server_disks[] = {"C:"};
2256 static uint32 get_server_disk_count(void)
2258 return sizeof(server_disks)/sizeof(server_disks[0]);
2261 static uint32 init_server_disk_enum(uint32 *resume)
2263 uint32 server_disk_count = get_server_disk_count();
2265 /*resume can be an offset into the list for now*/
2267 if(*resume & 0x80000000)
2270 if(*resume > server_disk_count)
2271 *resume = server_disk_count;
2273 return server_disk_count - *resume;
2276 static const char *next_server_disk_enum(uint32 *resume)
2280 if(init_server_disk_enum(resume) == 0)
2283 disk = server_disks[*resume];
2287 DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
2292 WERROR _srvsvc_NetDiskEnum(pipes_struct *p, struct srvsvc_NetDiskEnum *r)
2295 const char *disk_name;
2297 WERROR status = WERR_OK;
2299 *r->out.totalentries = init_server_disk_enum(r->in.resume_handle);
2300 r->out.info->count = 0;
2302 if(!(r->out.info->disks = TALLOC_ARRAY(p->mem_ctx, struct srvsvc_NetDiskInfo0, MAX_SERVER_DISK_ENTRIES))) {
2306 /*allow one struct srvsvc_NetDiskInfo0 for null terminator*/
2308 for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(r->in.resume_handle)); i++) {
2310 r->out.info->count++;
2311 (*r->out.totalentries)++;
2313 /*copy disk name into a unicode string*/
2315 r->out.info->disks[i].disk = disk_name;
2318 /* add a terminating null string. Is this there if there is more data to come? */
2320 r->out.info->count++;
2321 (*r->out.totalentries)++;
2323 r->out.info->disks[i].disk = "";
2328 /********************************************************************
2329 ********************************************************************/
2331 WERROR _srvsvc_NetNameValidate(pipes_struct *p, struct srvsvc_NetNameValidate *r)
2335 if ((r->in.flags != 0x0) && (r->in.flags != 0x80000000)) {
2336 return WERR_INVALID_PARAM;
2339 switch ( r->in.name_type ) {
2341 len = strlen_m(r->in.name);
2343 if ((r->in.flags == 0x0) && (len > 81)) {
2344 DEBUG(5,("_srv_net_name_validate: share name too long (%s > 81 chars)\n", r->in.name));
2345 return WERR_INVALID_NAME;
2347 if ((r->in.flags == 0x80000000) && (len > 13)) {
2348 DEBUG(5,("_srv_net_name_validate: share name too long (%s > 13 chars)\n", r->in.name));
2349 return WERR_INVALID_NAME;
2352 if ( ! validate_net_name( r->in.name, INVALID_SHARENAME_CHARS, sizeof(r->in.name) ) ) {
2353 DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", r->in.name));
2354 return WERR_INVALID_NAME;
2359 return WERR_UNKNOWN_LEVEL;
2366 /********************************************************************
2367 ********************************************************************/
2369 WERROR _srvsvc_NetFileClose(pipes_struct *p, struct srvsvc_NetFileClose *r)
2371 return WERR_ACCESS_DENIED;
2374 WERROR _srvsvc_NetCharDevEnum(pipes_struct *p, struct srvsvc_NetCharDevEnum *r)
2376 p->rng_fault_state = True;
2377 return WERR_NOT_SUPPORTED;
2380 WERROR _srvsvc_NetCharDevGetInfo(pipes_struct *p, struct srvsvc_NetCharDevGetInfo *r)
2382 p->rng_fault_state = True;
2383 return WERR_NOT_SUPPORTED;
2386 WERROR _srvsvc_NetCharDevControl(pipes_struct *p, struct srvsvc_NetCharDevControl *r)
2388 p->rng_fault_state = True;
2389 return WERR_NOT_SUPPORTED;
2392 WERROR _srvsvc_NetCharDevQEnum(pipes_struct *p, struct srvsvc_NetCharDevQEnum *r)
2394 p->rng_fault_state = True;
2395 return WERR_NOT_SUPPORTED;
2398 WERROR _srvsvc_NetCharDevQGetInfo(pipes_struct *p, struct srvsvc_NetCharDevQGetInfo *r)
2400 p->rng_fault_state = True;
2401 return WERR_NOT_SUPPORTED;
2404 WERROR _srvsvc_NetCharDevQSetInfo(pipes_struct *p, struct srvsvc_NetCharDevQSetInfo *r)
2406 p->rng_fault_state = True;
2407 return WERR_NOT_SUPPORTED;
2410 WERROR _srvsvc_NetCharDevQPurge(pipes_struct *p, struct srvsvc_NetCharDevQPurge *r)
2412 p->rng_fault_state = True;
2413 return WERR_NOT_SUPPORTED;
2416 WERROR _srvsvc_NetCharDevQPurgeSelf(pipes_struct *p, struct srvsvc_NetCharDevQPurgeSelf *r)
2418 p->rng_fault_state = True;
2419 return WERR_NOT_SUPPORTED;
2422 WERROR _srvsvc_NetFileGetInfo(pipes_struct *p, struct srvsvc_NetFileGetInfo *r)
2424 p->rng_fault_state = True;
2425 return WERR_NOT_SUPPORTED;
2428 WERROR _srvsvc_NetShareCheck(pipes_struct *p, struct srvsvc_NetShareCheck *r)
2430 p->rng_fault_state = True;
2431 return WERR_NOT_SUPPORTED;
2434 WERROR _srvsvc_NetServerStatisticsGet(pipes_struct *p, struct srvsvc_NetServerStatisticsGet *r)
2436 p->rng_fault_state = True;
2437 return WERR_NOT_SUPPORTED;
2440 WERROR _srvsvc_NetTransportAdd(pipes_struct *p, struct srvsvc_NetTransportAdd *r)
2442 p->rng_fault_state = True;
2443 return WERR_NOT_SUPPORTED;
2446 WERROR _srvsvc_NetTransportEnum(pipes_struct *p, struct srvsvc_NetTransportEnum *r)
2448 p->rng_fault_state = True;
2449 return WERR_NOT_SUPPORTED;
2452 WERROR _srvsvc_NetTransportDel(pipes_struct *p, struct srvsvc_NetTransportDel *r)
2454 p->rng_fault_state = True;
2455 return WERR_NOT_SUPPORTED;
2458 WERROR _srvsvc_NetSetServiceBits(pipes_struct *p, struct srvsvc_NetSetServiceBits *r)
2460 p->rng_fault_state = True;
2461 return WERR_NOT_SUPPORTED;
2464 WERROR _srvsvc_NetPathType(pipes_struct *p, struct srvsvc_NetPathType *r)
2466 p->rng_fault_state = True;
2467 return WERR_NOT_SUPPORTED;
2470 WERROR _srvsvc_NetPathCanonicalize(pipes_struct *p, struct srvsvc_NetPathCanonicalize *r)
2472 p->rng_fault_state = True;
2473 return WERR_NOT_SUPPORTED;
2476 WERROR _srvsvc_NetPathCompare(pipes_struct *p, struct srvsvc_NetPathCompare *r)
2478 p->rng_fault_state = True;
2479 return WERR_NOT_SUPPORTED;
2482 WERROR _srvsvc_NETRPRNAMECANONICALIZE(pipes_struct *p, struct srvsvc_NETRPRNAMECANONICALIZE *r)
2484 p->rng_fault_state = True;
2485 return WERR_NOT_SUPPORTED;
2488 WERROR _srvsvc_NetPRNameCompare(pipes_struct *p, struct srvsvc_NetPRNameCompare *r)
2490 p->rng_fault_state = True;
2491 return WERR_NOT_SUPPORTED;
2494 WERROR _srvsvc_NetShareDelStart(pipes_struct *p, struct srvsvc_NetShareDelStart *r)
2496 p->rng_fault_state = True;
2497 return WERR_NOT_SUPPORTED;
2500 WERROR _srvsvc_NetShareDelCommit(pipes_struct *p, struct srvsvc_NetShareDelCommit *r)
2502 p->rng_fault_state = True;
2503 return WERR_NOT_SUPPORTED;
2506 WERROR _srvsvc_NetServerTransportAddEx(pipes_struct *p, struct srvsvc_NetServerTransportAddEx *r)
2508 p->rng_fault_state = True;
2509 return WERR_NOT_SUPPORTED;
2512 WERROR _srvsvc_NetServerSetServiceBitsEx(pipes_struct *p, struct srvsvc_NetServerSetServiceBitsEx *r)
2514 p->rng_fault_state = True;
2515 return WERR_NOT_SUPPORTED;
2518 WERROR _srvsvc_NETRDFSGETVERSION(pipes_struct *p, struct srvsvc_NETRDFSGETVERSION *r)
2520 p->rng_fault_state = True;
2521 return WERR_NOT_SUPPORTED;
2524 WERROR _srvsvc_NETRDFSCREATELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSCREATELOCALPARTITION *r)
2526 p->rng_fault_state = True;
2527 return WERR_NOT_SUPPORTED;
2530 WERROR _srvsvc_NETRDFSDELETELOCALPARTITION(pipes_struct *p, struct srvsvc_NETRDFSDELETELOCALPARTITION *r)
2532 p->rng_fault_state = True;
2533 return WERR_NOT_SUPPORTED;
2536 WERROR _srvsvc_NETRDFSSETLOCALVOLUMESTATE(pipes_struct *p, struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *R)
2538 p->rng_fault_state = True;
2539 return WERR_NOT_SUPPORTED;
2542 WERROR _srvsvc_NETRDFSSETSERVERINFO(pipes_struct *p, struct srvsvc_NETRDFSSETSERVERINFO *r)
2544 p->rng_fault_state = True;
2545 return WERR_NOT_SUPPORTED;
2548 WERROR _srvsvc_NETRDFSCREATEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSCREATEEXITPOINT *r)
2550 p->rng_fault_state = True;
2551 return WERR_NOT_SUPPORTED;
2554 WERROR _srvsvc_NETRDFSDELETEEXITPOINT(pipes_struct *p, struct srvsvc_NETRDFSDELETEEXITPOINT *r)
2556 p->rng_fault_state = True;
2557 return WERR_NOT_SUPPORTED;
2560 WERROR _srvsvc_NETRSERVERTRANSPORTDELEX(pipes_struct *p, struct srvsvc_NETRSERVERTRANSPORTDELEX *r)
2562 p->rng_fault_state = True;
2563 return WERR_NOT_SUPPORTED;
2566 WERROR _srvsvc_NETRDFSMANAGERREPORTSITEINFO(pipes_struct *p, struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r)
2568 p->rng_fault_state = True;
2569 return WERR_NOT_SUPPORTED;
2572 WERROR _srvsvc_NETRDFSMODIFYPREFIX(pipes_struct *p, struct srvsvc_NETRDFSMODIFYPREFIX *r)
2574 p->rng_fault_state = True;
2575 return WERR_NOT_SUPPORTED;
2578 WERROR _srvsvc_NETRDFSFIXLOCALVOLUME(pipes_struct *p, struct srvsvc_NETRDFSFIXLOCALVOLUME *r)
2580 p->rng_fault_state = True;
2581 return WERR_NOT_SUPPORTED;