xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c (revision 9832:3569b6c7f56c)
18474SJose.Borrego@Sun.COM /*
28474SJose.Borrego@Sun.COM  * CDDL HEADER START
38474SJose.Borrego@Sun.COM  *
48474SJose.Borrego@Sun.COM  * The contents of this file are subject to the terms of the
58474SJose.Borrego@Sun.COM  * Common Development and Distribution License (the "License").
68474SJose.Borrego@Sun.COM  * You may not use this file except in compliance with the License.
78474SJose.Borrego@Sun.COM  *
88474SJose.Borrego@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98474SJose.Borrego@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108474SJose.Borrego@Sun.COM  * See the License for the specific language governing permissions
118474SJose.Borrego@Sun.COM  * and limitations under the License.
128474SJose.Borrego@Sun.COM  *
138474SJose.Borrego@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148474SJose.Borrego@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158474SJose.Borrego@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168474SJose.Borrego@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178474SJose.Borrego@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188474SJose.Borrego@Sun.COM  *
198474SJose.Borrego@Sun.COM  * CDDL HEADER END
208474SJose.Borrego@Sun.COM  */
218474SJose.Borrego@Sun.COM /*
228474SJose.Borrego@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
238474SJose.Borrego@Sun.COM  * Use is subject to license terms.
248474SJose.Borrego@Sun.COM  */
258474SJose.Borrego@Sun.COM 
268474SJose.Borrego@Sun.COM /*
278474SJose.Borrego@Sun.COM  * Server Service RPC (SRVSVC) server-side interface definition.
288474SJose.Borrego@Sun.COM  * The server service provides a remote administration interface.
298474SJose.Borrego@Sun.COM  *
308474SJose.Borrego@Sun.COM  * This service uses NERR/Win32 error codes rather than NT status
318474SJose.Borrego@Sun.COM  * values.
328474SJose.Borrego@Sun.COM  */
338474SJose.Borrego@Sun.COM 
348474SJose.Borrego@Sun.COM #include <sys/errno.h>
358474SJose.Borrego@Sun.COM #include <unistd.h>
368474SJose.Borrego@Sun.COM #include <netdb.h>
378474SJose.Borrego@Sun.COM #include <strings.h>
388474SJose.Borrego@Sun.COM #include <time.h>
398474SJose.Borrego@Sun.COM #include <thread.h>
408474SJose.Borrego@Sun.COM #include <ctype.h>
418474SJose.Borrego@Sun.COM #include <stdlib.h>
428474SJose.Borrego@Sun.COM #include <string.h>
438474SJose.Borrego@Sun.COM #include <sys/types.h>
448474SJose.Borrego@Sun.COM #include <sys/socket.h>
458474SJose.Borrego@Sun.COM #include <netinet/in.h>
468474SJose.Borrego@Sun.COM #include <arpa/inet.h>
478474SJose.Borrego@Sun.COM #include <libshare.h>
488474SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h>
498474SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h>
508474SJose.Borrego@Sun.COM #include <smbsrv/lmerr.h>
518474SJose.Borrego@Sun.COM #include <smbsrv/nterror.h>
528474SJose.Borrego@Sun.COM #include <smbsrv/nmpipes.h>
538474SJose.Borrego@Sun.COM #include <smbsrv/cifs.h>
548474SJose.Borrego@Sun.COM #include <smbsrv/netrauth.h>
558474SJose.Borrego@Sun.COM #include <smbsrv/ndl/srvsvc.ndl>
568474SJose.Borrego@Sun.COM #include <smbsrv/smb_common_door.h>
57*9832Samw@Sun.COM #include "mlsvc.h"
588474SJose.Borrego@Sun.COM 
598474SJose.Borrego@Sun.COM #define	SV_TYPE_SENT_BY_ME (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | SV_TYPE_NT)
608474SJose.Borrego@Sun.COM 
618474SJose.Borrego@Sun.COM /*
628474SJose.Borrego@Sun.COM  * Qualifier types for NetConnectEnum.
638474SJose.Borrego@Sun.COM  */
648474SJose.Borrego@Sun.COM #define	SRVSVC_CONNECT_ENUM_NULL	0
658474SJose.Borrego@Sun.COM #define	SRVSVC_CONNECT_ENUM_SHARE	1
668474SJose.Borrego@Sun.COM #define	SRVSVC_CONNECT_ENUM_WKSTN	2
678474SJose.Borrego@Sun.COM 
688474SJose.Borrego@Sun.COM #define	SMB_SRVSVC_MAXBUFLEN	(8 * 1024 * 1024)
698474SJose.Borrego@Sun.COM #define	SMB_SRVSVC_MAXPREFLEN	((uint32_t)(-1))
708474SJose.Borrego@Sun.COM 
718474SJose.Borrego@Sun.COM /*
728474SJose.Borrego@Sun.COM  * prefmaxlen:    Client specified response buffer limit.
738474SJose.Borrego@Sun.COM  * resume_handle: Cookie used to track enumeration across multiple calls.
748474SJose.Borrego@Sun.COM  * n_total:       Total number of entries.
758474SJose.Borrego@Sun.COM  * n_enum:        Number of entries to enumerate (derived from prefmaxlen).
768474SJose.Borrego@Sun.COM  * n_skip:        Number of entries to skip (from incoming resume handle).
778474SJose.Borrego@Sun.COM  * n_read:        Number of objects returned for current enumeration request.
788474SJose.Borrego@Sun.COM  */
798474SJose.Borrego@Sun.COM typedef struct srvsvc_enum {
808474SJose.Borrego@Sun.COM 	uint32_t se_level;
818474SJose.Borrego@Sun.COM 	uint32_t se_prefmaxlen;
828474SJose.Borrego@Sun.COM 	uint32_t se_resume_handle;
838474SJose.Borrego@Sun.COM 	uint32_t se_n_total;
848474SJose.Borrego@Sun.COM 	uint32_t se_n_enum;
858474SJose.Borrego@Sun.COM 	uint32_t se_n_skip;
868474SJose.Borrego@Sun.COM 	uint32_t se_n_read;
878474SJose.Borrego@Sun.COM } srvsvc_enum_t;
888474SJose.Borrego@Sun.COM 
89*9832Samw@Sun.COM typedef struct srvsvc_sd {
90*9832Samw@Sun.COM 	uint8_t *sd_buf;
91*9832Samw@Sun.COM 	uint32_t sd_size;
92*9832Samw@Sun.COM } srvsvc_sd_t;
93*9832Samw@Sun.COM 
94*9832Samw@Sun.COM typedef struct srvsvc_netshare_setinfo {
95*9832Samw@Sun.COM 	char *nss_netname;
96*9832Samw@Sun.COM 	char *nss_comment;
97*9832Samw@Sun.COM 	char *nss_path;
98*9832Samw@Sun.COM 	uint32_t nss_type;
99*9832Samw@Sun.COM 	srvsvc_sd_t nss_sd;
100*9832Samw@Sun.COM } srvsvc_netshare_setinfo_t;
101*9832Samw@Sun.COM 
102*9832Samw@Sun.COM typedef union srvsvc_netshare_getinfo {
103*9832Samw@Sun.COM 	struct mslm_NetShareInfo_0 nsg_info0;
104*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1 nsg_info1;
105*9832Samw@Sun.COM 	struct mslm_NetShareInfo_2 nsg_info2;
106*9832Samw@Sun.COM 	struct mslm_NetShareInfo_501 nsg_info501;
107*9832Samw@Sun.COM 	struct mslm_NetShareInfo_502 nsg_info502;
108*9832Samw@Sun.COM 	struct mslm_NetShareInfo_503 nsg_info503;
109*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1004 nsg_info1004;
110*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1005 nsg_info1005;
111*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1006 nsg_info1006;
112*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1501 nsg_info1501;
113*9832Samw@Sun.COM } srvsvc_netshare_getinfo_t;
114*9832Samw@Sun.COM 
1158474SJose.Borrego@Sun.COM static DWORD srvsvc_s_NetConnectEnumLevel0(ndr_xa_t *,
1168474SJose.Borrego@Sun.COM     srvsvc_NetConnectInfo0_t *);
1178474SJose.Borrego@Sun.COM static DWORD srvsvc_s_NetConnectEnumLevel1(ndr_xa_t *,
1188474SJose.Borrego@Sun.COM     srvsvc_NetConnectInfo1_t *);
1198474SJose.Borrego@Sun.COM 
1208474SJose.Borrego@Sun.COM static DWORD srvsvc_NetFileEnum2(ndr_xa_t *,
1218474SJose.Borrego@Sun.COM     struct mslm_NetFileEnum *);
1228474SJose.Borrego@Sun.COM static DWORD srvsvc_NetFileEnum3(ndr_xa_t *,
1238474SJose.Borrego@Sun.COM     struct mslm_NetFileEnum *);
1248474SJose.Borrego@Sun.COM 
1258474SJose.Borrego@Sun.COM static DWORD mlsvc_NetSessionEnumLevel0(struct mslm_infonres *, DWORD,
1268474SJose.Borrego@Sun.COM     ndr_xa_t *);
1278474SJose.Borrego@Sun.COM static DWORD mlsvc_NetSessionEnumLevel1(struct mslm_infonres *, DWORD,
1288474SJose.Borrego@Sun.COM     ndr_xa_t *);
129*9832Samw@Sun.COM static DWORD mlsvc_NetSessionEnumLevel2(struct mslm_infonres *, DWORD,
130*9832Samw@Sun.COM     ndr_xa_t *);
131*9832Samw@Sun.COM static DWORD mlsvc_NetSessionEnumLevel10(struct mslm_infonres *, DWORD,
132*9832Samw@Sun.COM     ndr_xa_t *);
133*9832Samw@Sun.COM static DWORD mlsvc_NetSessionEnumLevel502(struct mslm_infonres *, DWORD,
134*9832Samw@Sun.COM     ndr_xa_t *);
1358474SJose.Borrego@Sun.COM 
1368474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel0(ndr_xa_t *,
1378474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1388474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel1(ndr_xa_t *,
1398474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1408474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel2(ndr_xa_t *,
1418474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1428474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel501(ndr_xa_t *,
1438474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1448474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumLevel502(ndr_xa_t *,
1458474SJose.Borrego@Sun.COM     struct mslm_infonres *, srvsvc_enum_t *, int);
1468474SJose.Borrego@Sun.COM static DWORD mlsvc_NetShareEnumCommon(ndr_xa_t *,
1478474SJose.Borrego@Sun.COM     srvsvc_enum_t *, smb_share_t *, void *);
1488474SJose.Borrego@Sun.COM static boolean_t srvsvc_add_autohome(ndr_xa_t *, srvsvc_enum_t *,
1498474SJose.Borrego@Sun.COM     void *);
1508474SJose.Borrego@Sun.COM static char *srvsvc_share_mkpath(ndr_xa_t *, char *);
151*9832Samw@Sun.COM static uint32_t srvsvc_share_getsd(ndr_xa_t *, smb_share_t *, srvsvc_sd_t *);
1528474SJose.Borrego@Sun.COM 
1538474SJose.Borrego@Sun.COM static int srvsvc_netconnect_qualifier(const char *);
1548474SJose.Borrego@Sun.COM static uint32_t srvsvc_estimate_objcnt(uint32_t, uint32_t, uint32_t);
1558474SJose.Borrego@Sun.COM 
156*9832Samw@Sun.COM static uint32_t srvsvc_modify_share(smb_share_t *,
157*9832Samw@Sun.COM     srvsvc_netshare_setinfo_t *);
158*9832Samw@Sun.COM static uint32_t srvsvc_modify_transient_share(smb_share_t *,
159*9832Samw@Sun.COM     srvsvc_netshare_setinfo_t *);
160*9832Samw@Sun.COM static uint32_t srvsvc_update_share_flags(smb_share_t *, uint32_t);
161*9832Samw@Sun.COM 
1628474SJose.Borrego@Sun.COM static uint32_t srvsvc_sa_add(char *, char *, char *);
1638474SJose.Borrego@Sun.COM static uint32_t srvsvc_sa_delete(char *);
164*9832Samw@Sun.COM static uint32_t srvsvc_sa_modify(smb_share_t *, srvsvc_netshare_setinfo_t *);
165*9832Samw@Sun.COM static uint32_t srvsvc_sa_setattr(smb_share_t *);
1668474SJose.Borrego@Sun.COM 
1678474SJose.Borrego@Sun.COM static char empty_string[1];
1688474SJose.Borrego@Sun.COM 
1698474SJose.Borrego@Sun.COM static ndr_stub_table_t srvsvc_stub_table[];
1708474SJose.Borrego@Sun.COM 
1718474SJose.Borrego@Sun.COM static ndr_service_t srvsvc_service = {
1728474SJose.Borrego@Sun.COM 	"SRVSVC",			/* name */
1738474SJose.Borrego@Sun.COM 	"Server services",		/* desc */
1748474SJose.Borrego@Sun.COM 	"\\srvsvc",			/* endpoint */
1758474SJose.Borrego@Sun.COM 	PIPE_NTSVCS,			/* sec_addr_port */
1768474SJose.Borrego@Sun.COM 	"4b324fc8-1670-01d3-1278-5a47bf6ee188", 3,	/* abstract */
1778474SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
1788474SJose.Borrego@Sun.COM 	0,				/* no bind_instance_size */
1798474SJose.Borrego@Sun.COM 	0,				/* no bind_req() */
1808474SJose.Borrego@Sun.COM 	0,				/* no unbind_and_close() */
1818474SJose.Borrego@Sun.COM 	0,				/* use generic_call_stub() */
1828474SJose.Borrego@Sun.COM 	&TYPEINFO(srvsvc_interface),	/* interface ti */
1838474SJose.Borrego@Sun.COM 	srvsvc_stub_table		/* stub_table */
1848474SJose.Borrego@Sun.COM };
1858474SJose.Borrego@Sun.COM 
1868474SJose.Borrego@Sun.COM /*
1878474SJose.Borrego@Sun.COM  * srvsvc_initialize
1888474SJose.Borrego@Sun.COM  *
1898474SJose.Borrego@Sun.COM  * This function registers the SRVSVC RPC interface with the RPC runtime
1908474SJose.Borrego@Sun.COM  * library. It must be called in order to use either the client side
1918474SJose.Borrego@Sun.COM  * or the server side functions.
1928474SJose.Borrego@Sun.COM  */
1938474SJose.Borrego@Sun.COM void
1948474SJose.Borrego@Sun.COM srvsvc_initialize(void)
1958474SJose.Borrego@Sun.COM {
1968474SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&srvsvc_service);
1978474SJose.Borrego@Sun.COM }
1988474SJose.Borrego@Sun.COM 
1998474SJose.Borrego@Sun.COM /*
2008474SJose.Borrego@Sun.COM  * srvsvc_s_NetConnectEnum
2018474SJose.Borrego@Sun.COM  *
2028474SJose.Borrego@Sun.COM  * List tree connections made to a share on this server or all tree
2038474SJose.Borrego@Sun.COM  * connections established from a specific client.  Administrator,
2048474SJose.Borrego@Sun.COM  * Server Operator, Print Operator or Power User group membership
2058474SJose.Borrego@Sun.COM  * is required to use this interface.
2068474SJose.Borrego@Sun.COM  *
2078474SJose.Borrego@Sun.COM  * There are three information levels:  0, 1, and 50.  We don't support
2088474SJose.Borrego@Sun.COM  * level 50, which is only used by Windows 9x clients.
2098474SJose.Borrego@Sun.COM  *
2108474SJose.Borrego@Sun.COM  * It seems Server Manger (srvmgr) only sends workstation as the qualifier
2118474SJose.Borrego@Sun.COM  * and the Computer Management Interface on Windows 2000 doesn't request
2128474SJose.Borrego@Sun.COM  * a list of connections.
2138474SJose.Borrego@Sun.COM  *
2148474SJose.Borrego@Sun.COM  * Return Values:
2158474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Success
2168474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Caller does not have access to this call.
2178474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  One of the parameters is invalid.
2188474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      Unknown information level specified.
2198474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          Partial date returned, more entries available.
2208474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
2218474SJose.Borrego@Sun.COM  * NERR_NetNameNotFound     The share qualifier cannot be found.
2228474SJose.Borrego@Sun.COM  * NERR_BufTooSmall         The supplied buffer is too small.
2238474SJose.Borrego@Sun.COM  */
2248474SJose.Borrego@Sun.COM static int
2258474SJose.Borrego@Sun.COM srvsvc_s_NetConnectEnum(void *arg, ndr_xa_t *mxa)
2268474SJose.Borrego@Sun.COM {
2278474SJose.Borrego@Sun.COM 	struct mslm_NetConnectEnum *param = arg;
2288474SJose.Borrego@Sun.COM 	srvsvc_NetConnectInfo0_t *info0;
2298474SJose.Borrego@Sun.COM 	srvsvc_NetConnectInfo1_t *info1;
2308474SJose.Borrego@Sun.COM 	char *qualifier;
2318474SJose.Borrego@Sun.COM 	int qualtype;
2328474SJose.Borrego@Sun.COM 	DWORD status = ERROR_SUCCESS;
2338474SJose.Borrego@Sun.COM 
2348474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
2358474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetConnectEnum));
2368474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
2378474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
2388474SJose.Borrego@Sun.COM 	}
2398474SJose.Borrego@Sun.COM 
2408474SJose.Borrego@Sun.COM 	qualifier = (char *)param->qualifier;
2418474SJose.Borrego@Sun.COM 	qualtype = srvsvc_netconnect_qualifier(qualifier);
2428474SJose.Borrego@Sun.COM 
2438474SJose.Borrego@Sun.COM 	if (qualtype == SRVSVC_CONNECT_ENUM_NULL) {
2448474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetConnectEnum));
2458474SJose.Borrego@Sun.COM 		param->status = NERR_NetNameNotFound;
2468474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
2478474SJose.Borrego@Sun.COM 	}
2488474SJose.Borrego@Sun.COM 
2498474SJose.Borrego@Sun.COM 	switch (param->info.level) {
2508474SJose.Borrego@Sun.COM 	case 0:
2518474SJose.Borrego@Sun.COM 		info0 = NDR_NEW(mxa, srvsvc_NetConnectInfo0_t);
2528474SJose.Borrego@Sun.COM 		if (info0 == NULL) {
2538474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
2548474SJose.Borrego@Sun.COM 			break;
2558474SJose.Borrego@Sun.COM 		}
2568474SJose.Borrego@Sun.COM 
2578474SJose.Borrego@Sun.COM 		bzero(info0, sizeof (srvsvc_NetConnectInfo0_t));
2588474SJose.Borrego@Sun.COM 		param->info.ru.info0 = info0;
2598474SJose.Borrego@Sun.COM 
2608474SJose.Borrego@Sun.COM 		status = srvsvc_s_NetConnectEnumLevel0(mxa, info0);
2618474SJose.Borrego@Sun.COM 
2628474SJose.Borrego@Sun.COM 		param->total_entries = info0->entries_read;
2638474SJose.Borrego@Sun.COM 		param->resume_handle = NULL;
2648474SJose.Borrego@Sun.COM 		break;
2658474SJose.Borrego@Sun.COM 
2668474SJose.Borrego@Sun.COM 	case 1:
2678474SJose.Borrego@Sun.COM 		info1 = NDR_NEW(mxa, srvsvc_NetConnectInfo1_t);
2688474SJose.Borrego@Sun.COM 		if (info1 == NULL) {
2698474SJose.Borrego@Sun.COM 			status = ERROR_NOT_ENOUGH_MEMORY;
2708474SJose.Borrego@Sun.COM 			break;
2718474SJose.Borrego@Sun.COM 		}
2728474SJose.Borrego@Sun.COM 
2738474SJose.Borrego@Sun.COM 		bzero(info1, sizeof (srvsvc_NetConnectInfo1_t));
2748474SJose.Borrego@Sun.COM 		param->info.ru.info1 = info1;
2758474SJose.Borrego@Sun.COM 
2768474SJose.Borrego@Sun.COM 		status = srvsvc_s_NetConnectEnumLevel1(mxa, info1);
2778474SJose.Borrego@Sun.COM 
2788474SJose.Borrego@Sun.COM 		param->total_entries = info1->entries_read;
2798474SJose.Borrego@Sun.COM 		param->resume_handle = NULL;
2808474SJose.Borrego@Sun.COM 		break;
2818474SJose.Borrego@Sun.COM 
2828474SJose.Borrego@Sun.COM 	case 50:
2838474SJose.Borrego@Sun.COM 		status = ERROR_NOT_SUPPORTED;
2848474SJose.Borrego@Sun.COM 		break;
2858474SJose.Borrego@Sun.COM 
2868474SJose.Borrego@Sun.COM 	default:
2878474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
2888474SJose.Borrego@Sun.COM 		break;
2898474SJose.Borrego@Sun.COM 	}
2908474SJose.Borrego@Sun.COM 
2918474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS)
2928474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetConnectEnum));
2938474SJose.Borrego@Sun.COM 
2948474SJose.Borrego@Sun.COM 	param->status = status;
2958474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
2968474SJose.Borrego@Sun.COM }
2978474SJose.Borrego@Sun.COM 
2988474SJose.Borrego@Sun.COM static DWORD
2998474SJose.Borrego@Sun.COM srvsvc_s_NetConnectEnumLevel0(ndr_xa_t *mxa, srvsvc_NetConnectInfo0_t *info0)
3008474SJose.Borrego@Sun.COM {
3018474SJose.Borrego@Sun.COM 	srvsvc_NetConnectInfoBuf0_t *ci0;
3028474SJose.Borrego@Sun.COM 
3038474SJose.Borrego@Sun.COM 	ci0 = NDR_NEW(mxa, srvsvc_NetConnectInfoBuf0_t);
3048474SJose.Borrego@Sun.COM 	if (ci0 == NULL)
3058474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
3068474SJose.Borrego@Sun.COM 
3078474SJose.Borrego@Sun.COM 	ci0->coni0_id = 0x17;
3088474SJose.Borrego@Sun.COM 
3098474SJose.Borrego@Sun.COM 	info0->ci0 = ci0;
3108474SJose.Borrego@Sun.COM 	info0->entries_read = 1;
3118474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
3128474SJose.Borrego@Sun.COM }
3138474SJose.Borrego@Sun.COM 
3148474SJose.Borrego@Sun.COM static DWORD
3158474SJose.Borrego@Sun.COM srvsvc_s_NetConnectEnumLevel1(ndr_xa_t *mxa, srvsvc_NetConnectInfo1_t *info1)
3168474SJose.Borrego@Sun.COM {
3178474SJose.Borrego@Sun.COM 	srvsvc_NetConnectInfoBuf1_t *ci1;
3188474SJose.Borrego@Sun.COM 
3198474SJose.Borrego@Sun.COM 	ci1 = NDR_NEW(mxa, srvsvc_NetConnectInfoBuf1_t);
3208474SJose.Borrego@Sun.COM 	if (ci1 == NULL)
3218474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
3228474SJose.Borrego@Sun.COM 
3238474SJose.Borrego@Sun.COM 	ci1->coni1_id = 0x17;
3248474SJose.Borrego@Sun.COM 	ci1->coni1_type = STYPE_IPC;
3258474SJose.Borrego@Sun.COM 	ci1->coni1_num_opens = 1;
3268474SJose.Borrego@Sun.COM 	ci1->coni1_num_users = 1;
3278474SJose.Borrego@Sun.COM 	ci1->coni1_time = 16;
3288474SJose.Borrego@Sun.COM 	ci1->coni1_username = (uint8_t *)NDR_STRDUP(mxa, "Administrator");
3298474SJose.Borrego@Sun.COM 	ci1->coni1_netname = (uint8_t *)NDR_STRDUP(mxa, "IPC$");
3308474SJose.Borrego@Sun.COM 
3318474SJose.Borrego@Sun.COM 	info1->ci1 = ci1;
3328474SJose.Borrego@Sun.COM 	info1->entries_read = 1;
3338474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
3348474SJose.Borrego@Sun.COM }
3358474SJose.Borrego@Sun.COM 
3368474SJose.Borrego@Sun.COM /*
3378474SJose.Borrego@Sun.COM  * srvsvc_netconnect_qualifier
3388474SJose.Borrego@Sun.COM  *
3398474SJose.Borrego@Sun.COM  * The qualifier is a string that specifies a share name or computer name
3408474SJose.Borrego@Sun.COM  * for the connections of interest.  If it is a share name then all the
3418474SJose.Borrego@Sun.COM  * connections made to that share name are listed.  If it is a computer
3428474SJose.Borrego@Sun.COM  * name (it starts with two backslash characters), then NetConnectEnum
3438474SJose.Borrego@Sun.COM  * lists all connections made from that computer to the specified server.
3448474SJose.Borrego@Sun.COM  */
3458474SJose.Borrego@Sun.COM static int
3468474SJose.Borrego@Sun.COM srvsvc_netconnect_qualifier(const char *qualifier)
3478474SJose.Borrego@Sun.COM {
3488474SJose.Borrego@Sun.COM 	if (qualifier == NULL || *qualifier == '\0')
3498474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_NULL);
3508474SJose.Borrego@Sun.COM 
3518474SJose.Borrego@Sun.COM 	if (strlen(qualifier) > MAXHOSTNAMELEN)
3528474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_NULL);
3538474SJose.Borrego@Sun.COM 
3548474SJose.Borrego@Sun.COM 	if (qualifier[0] == '\\' && qualifier[1] == '\\') {
3558474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_WKSTN);
3568474SJose.Borrego@Sun.COM 	} else {
3578474SJose.Borrego@Sun.COM 		if (!smb_shr_exists((char *)qualifier))
3588474SJose.Borrego@Sun.COM 			return (SRVSVC_CONNECT_ENUM_NULL);
3598474SJose.Borrego@Sun.COM 
3608474SJose.Borrego@Sun.COM 		return (SRVSVC_CONNECT_ENUM_SHARE);
3618474SJose.Borrego@Sun.COM 	}
3628474SJose.Borrego@Sun.COM }
3638474SJose.Borrego@Sun.COM 
3648474SJose.Borrego@Sun.COM /*
3658474SJose.Borrego@Sun.COM  * srvsvc_s_NetFileEnum
3668474SJose.Borrego@Sun.COM  *
3678474SJose.Borrego@Sun.COM  * Return information on open files or named pipes. Only members of the
3688474SJose.Borrego@Sun.COM  * Administrators or Server Operators local groups are allowed to make
3698474SJose.Borrego@Sun.COM  * this call. Currently, we only support Administrators.
3708474SJose.Borrego@Sun.COM  *
3718474SJose.Borrego@Sun.COM  * If basepath is null, all open resources are enumerated. If basepath
3728474SJose.Borrego@Sun.COM  * is non-null, only resources that have basepath as a prefix should
3738474SJose.Borrego@Sun.COM  * be returned.
3748474SJose.Borrego@Sun.COM  *
3758474SJose.Borrego@Sun.COM  * If username is specified (non-null), only files opened by username
3768474SJose.Borrego@Sun.COM  * should be returned.
3778474SJose.Borrego@Sun.COM  *
3788474SJose.Borrego@Sun.COM  * Notes:
3798474SJose.Borrego@Sun.COM  * 1. We don't validate the servername because we would have to check
3808474SJose.Borrego@Sun.COM  * all primary IPs and the ROI seems unlikely to be worth it.
3818474SJose.Borrego@Sun.COM  * 2. Both basepath and username are currently ignored because both
3828474SJose.Borrego@Sun.COM  * Server Manger (NT 4.0) and CMI (Windows 2000) always set them to null.
3838474SJose.Borrego@Sun.COM  *
3848474SJose.Borrego@Sun.COM  * The level of information requested may be one of:
3858474SJose.Borrego@Sun.COM  *
3868474SJose.Borrego@Sun.COM  *  2   Return the file identification number.
3878474SJose.Borrego@Sun.COM  *      This level is not supported on Windows Me/98/95.
3888474SJose.Borrego@Sun.COM  *
3898474SJose.Borrego@Sun.COM  *  3   Return information about the file.
3908474SJose.Borrego@Sun.COM  *      This level is not supported on Windows Me/98/95.
3918474SJose.Borrego@Sun.COM  *
3928474SJose.Borrego@Sun.COM  *  50  Windows Me/98/95:  Return information about the file.
3938474SJose.Borrego@Sun.COM  *
3948474SJose.Borrego@Sun.COM  * Note:
3958474SJose.Borrego@Sun.COM  * If pref_max_len is unlimited and resume_handle is null, the client
3968474SJose.Borrego@Sun.COM  * expects to receive all data in a single call.
3978474SJose.Borrego@Sun.COM  * If we are unable to do fit all data in a single response, we would
3988474SJose.Borrego@Sun.COM  * normally return ERROR_MORE_DATA with a partial list.
3998474SJose.Borrego@Sun.COM  *
4008474SJose.Borrego@Sun.COM  * Unfortunately, when both of these conditions occur, Server Manager
4018474SJose.Borrego@Sun.COM  * pops up an error box with the message "more data available" and
4028474SJose.Borrego@Sun.COM  * doesn't display any of the returned data. In this case, it is
4038474SJose.Borrego@Sun.COM  * probably better to return ERROR_SUCCESS with the partial list.
4048474SJose.Borrego@Sun.COM  * Windows 2000 doesn't have this problem because it always sends a
4058474SJose.Borrego@Sun.COM  * non-null resume_handle.
4068474SJose.Borrego@Sun.COM  *
4078474SJose.Borrego@Sun.COM  * Return Values:
4088474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Success
4098474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Caller does not have access to this call.
4108474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  One of the parameters is invalid.
4118474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      Unknown information level specified.
4128474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          Partial date returned, more entries available.
4138474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
4148474SJose.Borrego@Sun.COM  * NERR_BufTooSmall         The supplied buffer is too small.
4158474SJose.Borrego@Sun.COM  */
4168474SJose.Borrego@Sun.COM static int
4178474SJose.Borrego@Sun.COM srvsvc_s_NetFileEnum(void *arg, ndr_xa_t *mxa)
4188474SJose.Borrego@Sun.COM {
4198474SJose.Borrego@Sun.COM 	struct mslm_NetFileEnum *param = arg;
4208474SJose.Borrego@Sun.COM 	DWORD status;
4218474SJose.Borrego@Sun.COM 
4228474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa)) {
4238474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileEnum));
4248474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
4258474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4268474SJose.Borrego@Sun.COM 	}
4278474SJose.Borrego@Sun.COM 
4288474SJose.Borrego@Sun.COM 	switch (param->info.switch_value) {
4298474SJose.Borrego@Sun.COM 	case 2:
4308474SJose.Borrego@Sun.COM 		status = srvsvc_NetFileEnum2(mxa, param);
4318474SJose.Borrego@Sun.COM 		break;
4328474SJose.Borrego@Sun.COM 
4338474SJose.Borrego@Sun.COM 	case 3:
4348474SJose.Borrego@Sun.COM 		status = srvsvc_NetFileEnum3(mxa, param);
4358474SJose.Borrego@Sun.COM 		break;
4368474SJose.Borrego@Sun.COM 
4378474SJose.Borrego@Sun.COM 	case 50:
4388474SJose.Borrego@Sun.COM 		status = ERROR_NOT_SUPPORTED;
4398474SJose.Borrego@Sun.COM 		break;
4408474SJose.Borrego@Sun.COM 
4418474SJose.Borrego@Sun.COM 	default:
4428474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
4438474SJose.Borrego@Sun.COM 		break;
4448474SJose.Borrego@Sun.COM 	}
4458474SJose.Borrego@Sun.COM 
4468474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS) {
4478474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileEnum));
4488474SJose.Borrego@Sun.COM 		param->status = status;
4498474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4508474SJose.Borrego@Sun.COM 	}
4518474SJose.Borrego@Sun.COM 
4528474SJose.Borrego@Sun.COM 	if (param->resume_handle)
4538474SJose.Borrego@Sun.COM 		*param->resume_handle = 0;
4548474SJose.Borrego@Sun.COM 
4558474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
4568474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
4578474SJose.Borrego@Sun.COM }
4588474SJose.Borrego@Sun.COM 
4598474SJose.Borrego@Sun.COM /*
4608474SJose.Borrego@Sun.COM  * Build level 2 file information.
4618474SJose.Borrego@Sun.COM  *
4628474SJose.Borrego@Sun.COM  * On success, the caller expects that the info2, fi2 and entries_read
4638474SJose.Borrego@Sun.COM  * fields have been set up.
4648474SJose.Borrego@Sun.COM  */
4658474SJose.Borrego@Sun.COM static DWORD
4668474SJose.Borrego@Sun.COM srvsvc_NetFileEnum2(ndr_xa_t *mxa, struct mslm_NetFileEnum *param)
4678474SJose.Borrego@Sun.COM {
4688474SJose.Borrego@Sun.COM 	struct mslm_NetFileInfoBuf2 *fi2;
4698474SJose.Borrego@Sun.COM 	ndr_pipe_info_t pi;
4708474SJose.Borrego@Sun.COM 	uint32_t entries_read = 0;
4718474SJose.Borrego@Sun.COM 	int i;
4728474SJose.Borrego@Sun.COM 
4738474SJose.Borrego@Sun.COM 	param->info.ru.info2 = NDR_NEW(mxa, struct mslm_NetFileInfo2);
474*9832Samw@Sun.COM 	if (param->info.ru.info2 == NULL)
4758474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
4768474SJose.Borrego@Sun.COM 
4778474SJose.Borrego@Sun.COM 	fi2 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf2, 128);
4788474SJose.Borrego@Sun.COM 	if (fi2 == NULL)
4798474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
4808474SJose.Borrego@Sun.COM 
4818474SJose.Borrego@Sun.COM 	param->info.ru.info2->fi2 = fi2;
4828474SJose.Borrego@Sun.COM 
4838474SJose.Borrego@Sun.COM 	for (i = 0; i < 128; ++i) {
4848474SJose.Borrego@Sun.COM 		if (ndr_pipe_getinfo(i, &pi) == -1)
4858474SJose.Borrego@Sun.COM 			continue;
4868474SJose.Borrego@Sun.COM 
4878474SJose.Borrego@Sun.COM 		fi2->fi2_id = pi.npi_fid;
4888474SJose.Borrego@Sun.COM 
4898474SJose.Borrego@Sun.COM 		++entries_read;
4908474SJose.Borrego@Sun.COM 		++fi2;
4918474SJose.Borrego@Sun.COM 	}
4928474SJose.Borrego@Sun.COM 
4938474SJose.Borrego@Sun.COM 	param->info.ru.info2->entries_read = entries_read;
4948474SJose.Borrego@Sun.COM 	param->total_entries = entries_read;
4958474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
4968474SJose.Borrego@Sun.COM }
4978474SJose.Borrego@Sun.COM 
4988474SJose.Borrego@Sun.COM /*
4998474SJose.Borrego@Sun.COM  * Build level 3 file information.
5008474SJose.Borrego@Sun.COM  *
5018474SJose.Borrego@Sun.COM  * On success, the caller expects that the info3, fi3 and entries_read
5028474SJose.Borrego@Sun.COM  * fields have been set up.
5038474SJose.Borrego@Sun.COM  */
5048474SJose.Borrego@Sun.COM static DWORD
5058474SJose.Borrego@Sun.COM srvsvc_NetFileEnum3(ndr_xa_t *mxa, struct mslm_NetFileEnum *param)
5068474SJose.Borrego@Sun.COM {
5078474SJose.Borrego@Sun.COM 	struct mslm_NetFileInfoBuf3 *fi3;
5088474SJose.Borrego@Sun.COM 	ndr_pipe_info_t pi;
5098474SJose.Borrego@Sun.COM 	uint32_t entries_read = 0;
5108474SJose.Borrego@Sun.COM 	int i;
5118474SJose.Borrego@Sun.COM 
5128474SJose.Borrego@Sun.COM 	param->info.ru.info3 = NDR_NEW(mxa, struct mslm_NetFileInfo3);
5138474SJose.Borrego@Sun.COM 	if (param->info.ru.info3 == NULL)
5148474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
5158474SJose.Borrego@Sun.COM 
5168474SJose.Borrego@Sun.COM 	fi3 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf3, 128);
5178474SJose.Borrego@Sun.COM 	if (fi3 == NULL)
5188474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
5198474SJose.Borrego@Sun.COM 
5208474SJose.Borrego@Sun.COM 	param->info.ru.info3->fi3 = fi3;
5218474SJose.Borrego@Sun.COM 
5228474SJose.Borrego@Sun.COM 	for (i = 0; i < 128; ++i) {
5238474SJose.Borrego@Sun.COM 		if (ndr_pipe_getinfo(i, &pi) == -1)
5248474SJose.Borrego@Sun.COM 			continue;
5258474SJose.Borrego@Sun.COM 
5268474SJose.Borrego@Sun.COM 		fi3->fi3_id = pi.npi_fid;
5278474SJose.Borrego@Sun.COM 		fi3->fi3_permissions = pi.npi_permissions;
5288474SJose.Borrego@Sun.COM 		fi3->fi3_num_locks = pi.npi_num_locks;
5298474SJose.Borrego@Sun.COM 		fi3->fi3_pathname = (uint8_t *)
5308474SJose.Borrego@Sun.COM 		    NDR_STRDUP(mxa, pi.npi_pathname);
5318474SJose.Borrego@Sun.COM 		fi3->fi3_username = (uint8_t *)
5328474SJose.Borrego@Sun.COM 		    NDR_STRDUP(mxa, pi.npi_username);
5338474SJose.Borrego@Sun.COM 
5348474SJose.Borrego@Sun.COM 		++entries_read;
5358474SJose.Borrego@Sun.COM 		++fi3;
5368474SJose.Borrego@Sun.COM 	}
5378474SJose.Borrego@Sun.COM 
5388474SJose.Borrego@Sun.COM 	param->info.ru.info3->entries_read = entries_read;
5398474SJose.Borrego@Sun.COM 	param->total_entries = entries_read;
5408474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
5418474SJose.Borrego@Sun.COM }
5428474SJose.Borrego@Sun.COM 
5438474SJose.Borrego@Sun.COM /*
5448474SJose.Borrego@Sun.COM  * srvsvc_s_NetFileClose
5458474SJose.Borrego@Sun.COM  *
5468474SJose.Borrego@Sun.COM  * NetFileClose forces a file to close. This function can be used when
5478474SJose.Borrego@Sun.COM  * an error prevents closure by any other means.  Use NetFileClose with
5488474SJose.Borrego@Sun.COM  * caution because it does not flush data, cached on a client, to the
5498474SJose.Borrego@Sun.COM  * file before closing the file.
5508474SJose.Borrego@Sun.COM  *
5518474SJose.Borrego@Sun.COM  * Return Values
5528474SJose.Borrego@Sun.COM  * ERROR_SUCCESS            Operation succeeded.
5538474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      Operation denied.
5548474SJose.Borrego@Sun.COM  * NERR_FileIdNotFound      No open file with the specified id.
5558474SJose.Borrego@Sun.COM  *
5568474SJose.Borrego@Sun.COM  * Note: MSDN suggests that the error code should be ERROR_FILE_NOT_FOUND
5578474SJose.Borrego@Sun.COM  * but network captures using NT show NERR_FileIdNotFound.
5588474SJose.Borrego@Sun.COM  * The NetFileClose2 MSDN page has the right error code.
5598474SJose.Borrego@Sun.COM  */
5608474SJose.Borrego@Sun.COM static int
5618474SJose.Borrego@Sun.COM srvsvc_s_NetFileClose(void *arg, ndr_xa_t *mxa)
5628474SJose.Borrego@Sun.COM {
5638474SJose.Borrego@Sun.COM 	struct mslm_NetFileClose *param = arg;
5648474SJose.Borrego@Sun.COM 
5658474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa)) {
5668474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetFileClose));
5678474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
5688474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5698474SJose.Borrego@Sun.COM 	}
5708474SJose.Borrego@Sun.COM 
5718474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct mslm_NetFileClose));
5728474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
5738474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5748474SJose.Borrego@Sun.COM }
5758474SJose.Borrego@Sun.COM 
5768474SJose.Borrego@Sun.COM /*
5778474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareGetInfo
5788474SJose.Borrego@Sun.COM  *
5798474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
5808474SJose.Borrego@Sun.COM  */
5818474SJose.Borrego@Sun.COM static int
5828474SJose.Borrego@Sun.COM srvsvc_s_NetShareGetInfo(void *arg, ndr_xa_t *mxa)
5838474SJose.Borrego@Sun.COM {
5848474SJose.Borrego@Sun.COM 	struct mlsm_NetShareGetInfo *param = arg;
5859343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_0 *info0;
5869343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1 *info1;
5879343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
5889343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_501 *info501;
5899343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
590*9832Samw@Sun.COM 	struct mslm_NetShareInfo_503 *info503;
5919343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1004 *info1004;
5929343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1005 *info1005;
5939343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1006 *info1006;
594*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1501 *info1501;
595*9832Samw@Sun.COM 	srvsvc_netshare_getinfo_t *info;
596*9832Samw@Sun.COM 	uint8_t *netname;
597*9832Samw@Sun.COM 	uint8_t *comment;
5988474SJose.Borrego@Sun.COM 	smb_share_t si;
599*9832Samw@Sun.COM 	srvsvc_sd_t sd;
6008474SJose.Borrego@Sun.COM 	DWORD status;
6018474SJose.Borrego@Sun.COM 
6028474SJose.Borrego@Sun.COM 	status = smb_shr_get((char *)param->netname, &si);
6038474SJose.Borrego@Sun.COM 	if (status != NERR_Success) {
6048474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareGetInfo));
6058474SJose.Borrego@Sun.COM 		param->status = status;
6068474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6078474SJose.Borrego@Sun.COM 	}
6088474SJose.Borrego@Sun.COM 
609*9832Samw@Sun.COM 	netname = (uint8_t *)NDR_STRDUP(mxa, si.shr_name);
610*9832Samw@Sun.COM 	comment = (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt);
611*9832Samw@Sun.COM 	info = NDR_NEW(mxa, srvsvc_netshare_getinfo_t);
612*9832Samw@Sun.COM 
613*9832Samw@Sun.COM 	if (netname == NULL || comment == NULL || info == NULL) {
614*9832Samw@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareGetInfo));
615*9832Samw@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
616*9832Samw@Sun.COM 		return (NDR_DRC_OK);
617*9832Samw@Sun.COM 	}
618*9832Samw@Sun.COM 
6198474SJose.Borrego@Sun.COM 	switch (param->level) {
6208474SJose.Borrego@Sun.COM 	case 0:
621*9832Samw@Sun.COM 		info0 = &info->nsg_info0;
622*9832Samw@Sun.COM 		info0->shi0_netname = netname;
6238474SJose.Borrego@Sun.COM 		param->result.ru.info0 = info0;
6248474SJose.Borrego@Sun.COM 		break;
6258474SJose.Borrego@Sun.COM 
6268474SJose.Borrego@Sun.COM 	case 1:
627*9832Samw@Sun.COM 		info1 = &info->nsg_info1;
628*9832Samw@Sun.COM 		info1->shi1_netname = netname;
629*9832Samw@Sun.COM 		info1->shi1_comment = comment;
6308474SJose.Borrego@Sun.COM 		info1->shi1_type = si.shr_type;
6318474SJose.Borrego@Sun.COM 		param->result.ru.info1 = info1;
6328474SJose.Borrego@Sun.COM 		break;
6338474SJose.Borrego@Sun.COM 
6348474SJose.Borrego@Sun.COM 	case 2:
635*9832Samw@Sun.COM 		info2 = &info->nsg_info2;
636*9832Samw@Sun.COM 		info2->shi2_netname = netname;
637*9832Samw@Sun.COM 		info2->shi2_comment = comment;
6388474SJose.Borrego@Sun.COM 		info2->shi2_path =
6398474SJose.Borrego@Sun.COM 		    (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
6408474SJose.Borrego@Sun.COM 		info2->shi2_passwd = 0;
6418474SJose.Borrego@Sun.COM 		info2->shi2_type = si.shr_type;
6428474SJose.Borrego@Sun.COM 		info2->shi2_permissions = 0;
6438474SJose.Borrego@Sun.COM 		info2->shi2_max_uses = SHI_USES_UNLIMITED;
6448474SJose.Borrego@Sun.COM 		info2->shi2_current_uses = 0;
6458474SJose.Borrego@Sun.COM 		param->result.ru.info2 = info2;
6468474SJose.Borrego@Sun.COM 		break;
6478474SJose.Borrego@Sun.COM 
648*9832Samw@Sun.COM 	case 501:
649*9832Samw@Sun.COM 		info501 = &info->nsg_info501;
650*9832Samw@Sun.COM 		info501->shi501_netname = netname;
651*9832Samw@Sun.COM 		info501->shi501_comment = comment;
652*9832Samw@Sun.COM 		info501->shi501_type = si.shr_type;
653*9832Samw@Sun.COM 		info501->shi501_reserved = 0;
654*9832Samw@Sun.COM 		param->result.ru.info501 = info501;
655*9832Samw@Sun.COM 		break;
656*9832Samw@Sun.COM 
657*9832Samw@Sun.COM 	case 502:
658*9832Samw@Sun.COM 		info502 = &info->nsg_info502;
659*9832Samw@Sun.COM 		info502->shi502_netname = netname;
660*9832Samw@Sun.COM 		info502->shi502_comment = comment;
661*9832Samw@Sun.COM 		info502->shi502_path =
662*9832Samw@Sun.COM 		    (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
663*9832Samw@Sun.COM 		info502->shi502_passwd = 0;
664*9832Samw@Sun.COM 		info502->shi502_type = si.shr_type;
665*9832Samw@Sun.COM 		info502->shi502_permissions = 0;
666*9832Samw@Sun.COM 		info502->shi502_max_uses = SHI_USES_UNLIMITED;
667*9832Samw@Sun.COM 		info502->shi502_current_uses = 0;
668*9832Samw@Sun.COM 
669*9832Samw@Sun.COM 		status = srvsvc_share_getsd(mxa, &si, &sd);
670*9832Samw@Sun.COM 		if (status == ERROR_SUCCESS) {
671*9832Samw@Sun.COM 			info502->shi502_reserved = sd.sd_size;
672*9832Samw@Sun.COM 			info502->shi502_security_descriptor = sd.sd_buf;
673*9832Samw@Sun.COM 		} else {
674*9832Samw@Sun.COM 			info502->shi502_reserved = 0;
675*9832Samw@Sun.COM 			info502->shi502_security_descriptor = NULL;
6768474SJose.Borrego@Sun.COM 		}
6778474SJose.Borrego@Sun.COM 
678*9832Samw@Sun.COM 		param->result.ru.info502 = info502;
679*9832Samw@Sun.COM 		break;
680*9832Samw@Sun.COM 
681*9832Samw@Sun.COM 	case 503:
682*9832Samw@Sun.COM 		info503 = &info->nsg_info503;
683*9832Samw@Sun.COM 		info503->shi503_netname = netname;
684*9832Samw@Sun.COM 		info503->shi503_comment = comment;
685*9832Samw@Sun.COM 		info503->shi503_path =
686*9832Samw@Sun.COM 		    (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
687*9832Samw@Sun.COM 		info503->shi503_passwd = NULL;
688*9832Samw@Sun.COM 		info503->shi503_type = si.shr_type;
689*9832Samw@Sun.COM 		info503->shi503_permissions = 0;
690*9832Samw@Sun.COM 		info503->shi503_max_uses = SHI_USES_UNLIMITED;
691*9832Samw@Sun.COM 		info503->shi503_current_uses = 0;
692*9832Samw@Sun.COM 		info503->shi503_servername = NULL;
693*9832Samw@Sun.COM 
694*9832Samw@Sun.COM 		status = srvsvc_share_getsd(mxa, &si, &sd);
695*9832Samw@Sun.COM 		if (status == ERROR_SUCCESS) {
696*9832Samw@Sun.COM 			info503->shi503_reserved = sd.sd_size;
697*9832Samw@Sun.COM 			info503->shi503_security_descriptor = sd.sd_buf;
698*9832Samw@Sun.COM 		} else {
699*9832Samw@Sun.COM 			info503->shi503_reserved = 0;
700*9832Samw@Sun.COM 			info503->shi503_security_descriptor = NULL;
701*9832Samw@Sun.COM 		}
702*9832Samw@Sun.COM 
703*9832Samw@Sun.COM 		param->result.ru.info503 = info503;
704*9832Samw@Sun.COM 		break;
705*9832Samw@Sun.COM 
706*9832Samw@Sun.COM 	case 1004:
707*9832Samw@Sun.COM 		info1004 = &info->nsg_info1004;
708*9832Samw@Sun.COM 		info1004->shi1004_comment = comment;
709*9832Samw@Sun.COM 		param->result.ru.info1004 = info1004;
7108474SJose.Borrego@Sun.COM 		break;
7118474SJose.Borrego@Sun.COM 
7128474SJose.Borrego@Sun.COM 	case 1005:
713*9832Samw@Sun.COM 		info1005 = &info->nsg_info1005;
7148474SJose.Borrego@Sun.COM 		info1005->shi1005_flags = 0;
7158474SJose.Borrego@Sun.COM 
7168474SJose.Borrego@Sun.COM 		switch (si.shr_flags & SMB_SHRF_CSC_MASK) {
7178474SJose.Borrego@Sun.COM 		case SMB_SHRF_CSC_DISABLED:
7188474SJose.Borrego@Sun.COM 			info1005->shi1005_flags |= CSC_CACHE_NONE;
7198474SJose.Borrego@Sun.COM 			break;
7208474SJose.Borrego@Sun.COM 		case SMB_SHRF_CSC_AUTO:
7218474SJose.Borrego@Sun.COM 			info1005->shi1005_flags |= CSC_CACHE_AUTO_REINT;
7228474SJose.Borrego@Sun.COM 			break;
7238474SJose.Borrego@Sun.COM 		case SMB_SHRF_CSC_VDO:
7248474SJose.Borrego@Sun.COM 			info1005->shi1005_flags |= CSC_CACHE_VDO;
7258474SJose.Borrego@Sun.COM 			break;
7268474SJose.Borrego@Sun.COM 		case SMB_SHRF_CSC_MANUAL:
7278474SJose.Borrego@Sun.COM 		default:
7288474SJose.Borrego@Sun.COM 			/*
7298474SJose.Borrego@Sun.COM 			 * Default to CSC_CACHE_MANUAL_REINT.
7308474SJose.Borrego@Sun.COM 			 */
7318474SJose.Borrego@Sun.COM 			break;
7328474SJose.Borrego@Sun.COM 		}
7338474SJose.Borrego@Sun.COM 
7348474SJose.Borrego@Sun.COM 		param->result.ru.info1005 = info1005;
7358474SJose.Borrego@Sun.COM 		break;
7368474SJose.Borrego@Sun.COM 
7378474SJose.Borrego@Sun.COM 	case 1006:
738*9832Samw@Sun.COM 		info1006 = &info->nsg_info1006;
7398474SJose.Borrego@Sun.COM 		info1006->shi1006_max_uses = SHI_USES_UNLIMITED;
7408474SJose.Borrego@Sun.COM 		param->result.ru.info1006 = info1006;
7418474SJose.Borrego@Sun.COM 		break;
7428474SJose.Borrego@Sun.COM 
743*9832Samw@Sun.COM 	case 1501:
744*9832Samw@Sun.COM 		info1501 = &info->nsg_info1501;
745*9832Samw@Sun.COM 
746*9832Samw@Sun.COM 		status = srvsvc_share_getsd(mxa, &si, &sd);
747*9832Samw@Sun.COM 		if (status == ERROR_SUCCESS) {
748*9832Samw@Sun.COM 			info503->shi503_reserved = sd.sd_size;
749*9832Samw@Sun.COM 			info503->shi503_security_descriptor = sd.sd_buf;
750*9832Samw@Sun.COM 		} else {
751*9832Samw@Sun.COM 			info503->shi503_reserved = 0;
752*9832Samw@Sun.COM 			info503->shi503_security_descriptor = NULL;
7538474SJose.Borrego@Sun.COM 		}
7548474SJose.Borrego@Sun.COM 
755*9832Samw@Sun.COM 		param->result.ru.info1501 = info1501;
7568474SJose.Borrego@Sun.COM 		break;
7578474SJose.Borrego@Sun.COM 
7588474SJose.Borrego@Sun.COM 	default:
7598474SJose.Borrego@Sun.COM 		status = ERROR_ACCESS_DENIED;
7608474SJose.Borrego@Sun.COM 		break;
7618474SJose.Borrego@Sun.COM 	}
7628474SJose.Borrego@Sun.COM 
7638474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS)
7648474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareGetInfo));
7658474SJose.Borrego@Sun.COM 	else
7668474SJose.Borrego@Sun.COM 		param->result.switch_value = param->level;
7678474SJose.Borrego@Sun.COM 
7688474SJose.Borrego@Sun.COM 	param->status = status;
7698474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7708474SJose.Borrego@Sun.COM }
7718474SJose.Borrego@Sun.COM 
772*9832Samw@Sun.COM static uint32_t
773*9832Samw@Sun.COM srvsvc_share_getsd(ndr_xa_t *mxa, smb_share_t *si, srvsvc_sd_t *sd)
774*9832Samw@Sun.COM {
775*9832Samw@Sun.COM 	uint32_t status;
776*9832Samw@Sun.COM 
777*9832Samw@Sun.COM 	status = srvsvc_sd_get(si, NULL, &sd->sd_size);
778*9832Samw@Sun.COM 	if (status != ERROR_SUCCESS) {
779*9832Samw@Sun.COM 		if (status == ERROR_PATH_NOT_FOUND) {
780*9832Samw@Sun.COM 			bzero(sd, sizeof (srvsvc_sd_t));
781*9832Samw@Sun.COM 			status = ERROR_SUCCESS;
782*9832Samw@Sun.COM 		}
783*9832Samw@Sun.COM 
784*9832Samw@Sun.COM 		return (status);
785*9832Samw@Sun.COM 	}
786*9832Samw@Sun.COM 
787*9832Samw@Sun.COM 	if ((sd->sd_buf = NDR_MALLOC(mxa, sd->sd_size)) == NULL)
788*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
789*9832Samw@Sun.COM 
790*9832Samw@Sun.COM 	status = srvsvc_sd_get(si, sd->sd_buf, NULL);
791*9832Samw@Sun.COM 	if (status == ERROR_PATH_NOT_FOUND) {
792*9832Samw@Sun.COM 		bzero(sd, sizeof (srvsvc_sd_t));
793*9832Samw@Sun.COM 		status = ERROR_SUCCESS;
794*9832Samw@Sun.COM 	}
795*9832Samw@Sun.COM 
796*9832Samw@Sun.COM 	return (status);
797*9832Samw@Sun.COM }
7988474SJose.Borrego@Sun.COM 
7998474SJose.Borrego@Sun.COM /*
8008474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareSetInfo
8018474SJose.Borrego@Sun.COM  *
8028474SJose.Borrego@Sun.COM  * This call is made by SrvMgr to set share information.
803*9832Samw@Sun.COM  * Only power users groups can manage shares.
804*9832Samw@Sun.COM  *
805*9832Samw@Sun.COM  * To avoid misleading errors, we don't report an error
806*9832Samw@Sun.COM  * when a FS doesn't support ACLs on shares.
8078474SJose.Borrego@Sun.COM  *
8088474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
8098474SJose.Borrego@Sun.COM  */
8108474SJose.Borrego@Sun.COM static int
8118474SJose.Borrego@Sun.COM srvsvc_s_NetShareSetInfo(void *arg, ndr_xa_t *mxa)
8128474SJose.Borrego@Sun.COM {
8138474SJose.Borrego@Sun.COM 	struct mlsm_NetShareSetInfo *param = arg;
814*9832Samw@Sun.COM 	struct mslm_NetShareInfo_0 *info0;
815*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1 *info1;
816*9832Samw@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
817*9832Samw@Sun.COM 	struct mslm_NetShareInfo_501 *info501;
818*9832Samw@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
819*9832Samw@Sun.COM 	struct mslm_NetShareInfo_503 *info503;
820*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1004 *info1004;
821*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1005 *info1005;
822*9832Samw@Sun.COM 	struct mslm_NetShareInfo_1501 *info1501;
823*9832Samw@Sun.COM 	static DWORD parm_err = 0;
824*9832Samw@Sun.COM 	srvsvc_netshare_setinfo_t info;
825*9832Samw@Sun.COM 	smb_share_t si;
826*9832Samw@Sun.COM 	uint8_t *sdbuf;
827*9832Samw@Sun.COM 	int32_t native_os;
828*9832Samw@Sun.COM 	DWORD status;
829*9832Samw@Sun.COM 
830*9832Samw@Sun.COM 	native_os = ndr_native_os(mxa);
831*9832Samw@Sun.COM 
832*9832Samw@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
833*9832Samw@Sun.COM 		status = ERROR_ACCESS_DENIED;
834*9832Samw@Sun.COM 		goto netsharesetinfo_exit;
835*9832Samw@Sun.COM 	}
836*9832Samw@Sun.COM 
837*9832Samw@Sun.COM 	if (smb_shr_get((char *)param->netname, &si) != NERR_Success) {
838*9832Samw@Sun.COM 		status = ERROR_INVALID_NETNAME;
839*9832Samw@Sun.COM 		goto netsharesetinfo_exit;
840*9832Samw@Sun.COM 	}
841*9832Samw@Sun.COM 
842*9832Samw@Sun.COM 	if (param->result.ru.nullptr == NULL) {
843*9832Samw@Sun.COM 		status = ERROR_INVALID_PARAMETER;
844*9832Samw@Sun.COM 		goto netsharesetinfo_exit;
845*9832Samw@Sun.COM 	}
846*9832Samw@Sun.COM 
847*9832Samw@Sun.COM 	bzero(&info, sizeof (srvsvc_netshare_setinfo_t));
848*9832Samw@Sun.COM 
849*9832Samw@Sun.COM 	switch (param->level) {
850*9832Samw@Sun.COM 	case 0:
851*9832Samw@Sun.COM 		info0 = (struct mslm_NetShareInfo_0 *)param->result.ru.info0;
852*9832Samw@Sun.COM 		info.nss_netname = (char *)info0->shi0_netname;
853*9832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
854*9832Samw@Sun.COM 		break;
855*9832Samw@Sun.COM 
856*9832Samw@Sun.COM 	case 1:
857*9832Samw@Sun.COM 		info1 = (struct mslm_NetShareInfo_1 *)param->result.ru.info1;
858*9832Samw@Sun.COM 		info.nss_netname = (char *)info1->shi1_netname;
859*9832Samw@Sun.COM 		info.nss_comment = (char *)info1->shi1_comment;
860*9832Samw@Sun.COM 		info.nss_type = info1->shi1_type;
861*9832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
862*9832Samw@Sun.COM 		break;
863*9832Samw@Sun.COM 
864*9832Samw@Sun.COM 	case 2:
865*9832Samw@Sun.COM 		info2 = (struct mslm_NetShareInfo_2 *)param->result.ru.info2;
866*9832Samw@Sun.COM 		info.nss_netname = (char *)info2->shi2_netname;
867*9832Samw@Sun.COM 		info.nss_comment = (char *)info2->shi2_comment;
868*9832Samw@Sun.COM 		info.nss_path = (char *)info2->shi2_path;
869*9832Samw@Sun.COM 		info.nss_type = info2->shi2_type;
870*9832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
871*9832Samw@Sun.COM 		break;
872*9832Samw@Sun.COM 
873*9832Samw@Sun.COM 	case 501:
874*9832Samw@Sun.COM 		info501 = (struct mslm_NetShareInfo_501 *)
875*9832Samw@Sun.COM 		    param->result.ru.info501;
876*9832Samw@Sun.COM 		info.nss_netname = (char *)info501->shi501_netname;
877*9832Samw@Sun.COM 		info.nss_comment = (char *)info501->shi501_comment;
878*9832Samw@Sun.COM 		info.nss_type = info501->shi501_type;
879*9832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
880*9832Samw@Sun.COM 		break;
881*9832Samw@Sun.COM 
882*9832Samw@Sun.COM 	case 502:
883*9832Samw@Sun.COM 		info502 = (struct mslm_NetShareInfo_502 *)
884*9832Samw@Sun.COM 		    param->result.ru.info502;
885*9832Samw@Sun.COM 		info.nss_netname = (char *)info502->shi502_netname;
886*9832Samw@Sun.COM 		info.nss_comment = (char *)info502->shi502_comment;
887*9832Samw@Sun.COM 		info.nss_path = (char *)info502->shi502_path;
888*9832Samw@Sun.COM 		info.nss_type = info502->shi502_type;
889*9832Samw@Sun.COM 		info.nss_sd.sd_buf = info502->shi502_security_descriptor;
890*9832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
891*9832Samw@Sun.COM 		break;
892*9832Samw@Sun.COM 
893*9832Samw@Sun.COM 	case 503:
894*9832Samw@Sun.COM 		info503 = (struct mslm_NetShareInfo_503 *)
895*9832Samw@Sun.COM 		    param->result.ru.info503;
896*9832Samw@Sun.COM 		info.nss_netname = (char *)info503->shi503_netname;
897*9832Samw@Sun.COM 		info.nss_comment = (char *)info503->shi503_comment;
898*9832Samw@Sun.COM 		info.nss_path = (char *)info503->shi503_path;
899*9832Samw@Sun.COM 		info.nss_type = info503->shi503_type;
900*9832Samw@Sun.COM 		info.nss_sd.sd_buf = info503->shi503_security_descriptor;
901*9832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
902*9832Samw@Sun.COM 		break;
903*9832Samw@Sun.COM 
904*9832Samw@Sun.COM 	case 1004:
905*9832Samw@Sun.COM 		info1004 = (struct mslm_NetShareInfo_1004 *)
906*9832Samw@Sun.COM 		    param->result.ru.info1004;
907*9832Samw@Sun.COM 		info.nss_comment = (char *)info1004->shi1004_comment;
908*9832Samw@Sun.COM 		status = srvsvc_modify_share(&si, &info);
909*9832Samw@Sun.COM 		break;
910*9832Samw@Sun.COM 
911*9832Samw@Sun.COM 	case 1005:
912*9832Samw@Sun.COM 		info1005 = (struct mslm_NetShareInfo_1005 *)
913*9832Samw@Sun.COM 		    param->result.ru.info1005;
914*9832Samw@Sun.COM 		status = srvsvc_update_share_flags(&si,
915*9832Samw@Sun.COM 		    info1005->shi1005_flags);
916*9832Samw@Sun.COM 		break;
917*9832Samw@Sun.COM 
918*9832Samw@Sun.COM 	case 1006:
919*9832Samw@Sun.COM 		/*
920*9832Samw@Sun.COM 		 * We don't limit the maximum number of concurrent
921*9832Samw@Sun.COM 		 * connections to a share.
922*9832Samw@Sun.COM 		 */
923*9832Samw@Sun.COM 		status = ERROR_SUCCESS;
924*9832Samw@Sun.COM 		break;
925*9832Samw@Sun.COM 
926*9832Samw@Sun.COM 	case 1501:
927*9832Samw@Sun.COM 		info1501 = (struct mslm_NetShareInfo_1501 *)
928*9832Samw@Sun.COM 		    param->result.ru.info1501;
929*9832Samw@Sun.COM 		sdbuf = info1501->shi1501_security_descriptor;
930*9832Samw@Sun.COM 		status = ERROR_SUCCESS;
931*9832Samw@Sun.COM 
932*9832Samw@Sun.COM 		if (sdbuf != NULL) {
933*9832Samw@Sun.COM 			status = srvsvc_sd_set(&si, sdbuf);
934*9832Samw@Sun.COM 			if (status == ERROR_PATH_NOT_FOUND)
935*9832Samw@Sun.COM 				status = ERROR_SUCCESS;
936*9832Samw@Sun.COM 		}
937*9832Samw@Sun.COM 		break;
938*9832Samw@Sun.COM 
939*9832Samw@Sun.COM 	default:
940*9832Samw@Sun.COM 		status = ERROR_ACCESS_DENIED;
941*9832Samw@Sun.COM 		break;
942*9832Samw@Sun.COM 	}
943*9832Samw@Sun.COM 
944*9832Samw@Sun.COM netsharesetinfo_exit:
945*9832Samw@Sun.COM 	if (status != ERROR_SUCCESS)
946*9832Samw@Sun.COM 		bzero(param, sizeof (struct mlsm_NetShareSetInfo));
947*9832Samw@Sun.COM 
948*9832Samw@Sun.COM 	param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
949*9832Samw@Sun.COM 	param->status = status;
9508474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9518474SJose.Borrego@Sun.COM }
9528474SJose.Borrego@Sun.COM 
953*9832Samw@Sun.COM static uint32_t
954*9832Samw@Sun.COM srvsvc_modify_share(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
955*9832Samw@Sun.COM {
956*9832Samw@Sun.COM 	uint32_t nerr = NERR_Success;
957*9832Samw@Sun.COM 
958*9832Samw@Sun.COM 	if (si->shr_flags & SMB_SHRF_TRANS)
959*9832Samw@Sun.COM 		return (srvsvc_modify_transient_share(si, info));
960*9832Samw@Sun.COM 
961*9832Samw@Sun.COM 	if (info->nss_sd.sd_buf != NULL) {
962*9832Samw@Sun.COM 		nerr = srvsvc_sd_set(si, info->nss_sd.sd_buf);
963*9832Samw@Sun.COM 		if (nerr == ERROR_PATH_NOT_FOUND)
964*9832Samw@Sun.COM 			nerr = NERR_Success;
965*9832Samw@Sun.COM 	}
966*9832Samw@Sun.COM 
967*9832Samw@Sun.COM 	if ((nerr = srvsvc_sa_modify(si, info)) == NERR_Success)
968*9832Samw@Sun.COM 		nerr = smb_shr_modify(si);
969*9832Samw@Sun.COM 
970*9832Samw@Sun.COM 	return (nerr);
971*9832Samw@Sun.COM }
972*9832Samw@Sun.COM 
973*9832Samw@Sun.COM /*
974*9832Samw@Sun.COM  * Update transient shares.  This includes autohome shares.
975*9832Samw@Sun.COM  */
976*9832Samw@Sun.COM static uint32_t
977*9832Samw@Sun.COM srvsvc_modify_transient_share(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
978*9832Samw@Sun.COM {
979*9832Samw@Sun.COM 	uint32_t nerr;
980*9832Samw@Sun.COM 
981*9832Samw@Sun.COM 	if (info->nss_netname != NULL && info->nss_netname[0] != '\0' &&
982*9832Samw@Sun.COM 	    utf8_strcasecmp(info->nss_netname, si->shr_name) != 0) {
983*9832Samw@Sun.COM 		nerr = smb_shr_rename(si->shr_name, info->nss_netname);
984*9832Samw@Sun.COM 		if (nerr != NERR_Success)
985*9832Samw@Sun.COM 			return (nerr);
986*9832Samw@Sun.COM 
987*9832Samw@Sun.COM 		(void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN);
988*9832Samw@Sun.COM 	}
989*9832Samw@Sun.COM 
990*9832Samw@Sun.COM 	if ((info->nss_comment != NULL) &&
991*9832Samw@Sun.COM 	    (strcmp(info->nss_comment, si->shr_cmnt) != 0)) {
992*9832Samw@Sun.COM 		(void) strlcpy(si->shr_cmnt, info->nss_comment,
993*9832Samw@Sun.COM 		    SMB_SHARE_CMNT_MAX);
994*9832Samw@Sun.COM 
995*9832Samw@Sun.COM 		if ((nerr = smb_shr_modify(si)) != NERR_Success)
996*9832Samw@Sun.COM 			return (nerr);
997*9832Samw@Sun.COM 	}
998*9832Samw@Sun.COM 
999*9832Samw@Sun.COM 	return (NERR_Success);
1000*9832Samw@Sun.COM }
1001*9832Samw@Sun.COM 
1002*9832Samw@Sun.COM static uint32_t
1003*9832Samw@Sun.COM srvsvc_update_share_flags(smb_share_t *si, uint32_t shi_flags)
1004*9832Samw@Sun.COM {
1005*9832Samw@Sun.COM 	uint32_t cscflg = 0;
1006*9832Samw@Sun.COM 	uint32_t nerr = NERR_Success;
1007*9832Samw@Sun.COM 
1008*9832Samw@Sun.COM 	switch ((shi_flags & CSC_MASK)) {
1009*9832Samw@Sun.COM 	case CSC_CACHE_AUTO_REINT:
1010*9832Samw@Sun.COM 		cscflg = SMB_SHRF_CSC_AUTO;
1011*9832Samw@Sun.COM 		break;
1012*9832Samw@Sun.COM 	case CSC_CACHE_VDO:
1013*9832Samw@Sun.COM 		cscflg = SMB_SHRF_CSC_VDO;
1014*9832Samw@Sun.COM 		break;
1015*9832Samw@Sun.COM 	case CSC_CACHE_NONE:
1016*9832Samw@Sun.COM 		cscflg = SMB_SHRF_CSC_DISABLED;
1017*9832Samw@Sun.COM 		break;
1018*9832Samw@Sun.COM 	case CSC_CACHE_MANUAL_REINT:
1019*9832Samw@Sun.COM 		cscflg = SMB_SHRF_CSC_MANUAL;
1020*9832Samw@Sun.COM 		break;
1021*9832Samw@Sun.COM 	default:
1022*9832Samw@Sun.COM 		return (NERR_Success);
1023*9832Samw@Sun.COM 	}
1024*9832Samw@Sun.COM 
1025*9832Samw@Sun.COM 	if (cscflg == (si->shr_flags & SMB_SHRF_CSC_MASK))
1026*9832Samw@Sun.COM 		return (NERR_Success);
1027*9832Samw@Sun.COM 
1028*9832Samw@Sun.COM 	si->shr_flags &= ~SMB_SHRF_CSC_MASK;
1029*9832Samw@Sun.COM 	si->shr_flags |= cscflg;
1030*9832Samw@Sun.COM 
1031*9832Samw@Sun.COM 	if ((si->shr_flags & SMB_SHRF_TRANS) == 0) {
1032*9832Samw@Sun.COM 		if ((nerr = srvsvc_sa_setattr(si)) != NERR_Success)
1033*9832Samw@Sun.COM 			return (nerr);
1034*9832Samw@Sun.COM 	}
1035*9832Samw@Sun.COM 
1036*9832Samw@Sun.COM 	return (smb_shr_modify(si));
1037*9832Samw@Sun.COM }
1038*9832Samw@Sun.COM 
10398474SJose.Borrego@Sun.COM /*
10408474SJose.Borrego@Sun.COM  * srvsvc_s_NetSessionEnum
10418474SJose.Borrego@Sun.COM  *
10428474SJose.Borrego@Sun.COM  * Level 1 request is made by (Server Manager (srvmgr) on NT Server when
10438474SJose.Borrego@Sun.COM  * the user info icon is selected.
10448474SJose.Borrego@Sun.COM  *
10458474SJose.Borrego@Sun.COM  * On success, the return value is NERR_Success.
10468474SJose.Borrego@Sun.COM  * On error, the return value can be one of the following error codes:
10478474SJose.Borrego@Sun.COM  *
10488474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED      The user does not have access to the requested
10498474SJose.Borrego@Sun.COM  *                          information.
10508474SJose.Borrego@Sun.COM  * ERROR_INVALID_LEVEL      The value specified for the level is invalid.
10518474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER  The specified parameter is invalid.
10528474SJose.Borrego@Sun.COM  * ERROR_MORE_DATA          More entries are available. Specify a large
10538474SJose.Borrego@Sun.COM  *                          enough buffer to receive all entries.
10548474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY  Insufficient memory is available.
10558474SJose.Borrego@Sun.COM  * NERR_ClientNameNotFound  A session does not exist with the computer name.
10568474SJose.Borrego@Sun.COM  * NERR_InvalidComputer     The computer name is invalid.
10578474SJose.Borrego@Sun.COM  * NERR_UserNotFound        The user name could not be found.
10588474SJose.Borrego@Sun.COM  */
10598474SJose.Borrego@Sun.COM static int
10608474SJose.Borrego@Sun.COM srvsvc_s_NetSessionEnum(void *arg, ndr_xa_t *mxa)
10618474SJose.Borrego@Sun.COM {
10628474SJose.Borrego@Sun.COM 	struct mslm_NetSessionEnum *param = arg;
10638474SJose.Borrego@Sun.COM 	struct mslm_infonres *infonres;
10648474SJose.Borrego@Sun.COM 	DWORD status;
10658474SJose.Borrego@Sun.COM 	DWORD n_sessions;
10668474SJose.Borrego@Sun.COM 
10678474SJose.Borrego@Sun.COM 	infonres = NDR_NEW(mxa, struct mslm_infonres);
10688474SJose.Borrego@Sun.COM 	if (infonres == NULL) {
10698474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetSessionEnum));
10708474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
10718474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
10728474SJose.Borrego@Sun.COM 	}
10738474SJose.Borrego@Sun.COM 
10748474SJose.Borrego@Sun.COM 	infonres->entriesread = 0;
10758474SJose.Borrego@Sun.COM 	infonres->entries = NULL;
10768474SJose.Borrego@Sun.COM 	param->result.level = param->level;
10778474SJose.Borrego@Sun.COM 	param->result.bufptr.p = infonres;
10788474SJose.Borrego@Sun.COM 	param->total_entries = 0;
10798474SJose.Borrego@Sun.COM 	param->resume_handle = NULL;
10808474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
10818474SJose.Borrego@Sun.COM 
10828474SJose.Borrego@Sun.COM 	if ((n_sessions = (DWORD) mlsvc_get_num_users()) == 0)
10838474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
10848474SJose.Borrego@Sun.COM 
10858474SJose.Borrego@Sun.COM 	switch (param->level) {
10868474SJose.Borrego@Sun.COM 	case 0:
10878474SJose.Borrego@Sun.COM 		status = mlsvc_NetSessionEnumLevel0(infonres, n_sessions, mxa);
10888474SJose.Borrego@Sun.COM 		break;
10898474SJose.Borrego@Sun.COM 
10908474SJose.Borrego@Sun.COM 	case 1:
10918474SJose.Borrego@Sun.COM 		status = mlsvc_NetSessionEnumLevel1(infonres, n_sessions, mxa);
10928474SJose.Borrego@Sun.COM 		break;
10938474SJose.Borrego@Sun.COM 
1094*9832Samw@Sun.COM 	case 2:
1095*9832Samw@Sun.COM 		status = mlsvc_NetSessionEnumLevel2(infonres, n_sessions, mxa);
1096*9832Samw@Sun.COM 		break;
1097*9832Samw@Sun.COM 
1098*9832Samw@Sun.COM 	case 10:
1099*9832Samw@Sun.COM 		status = mlsvc_NetSessionEnumLevel10(infonres, n_sessions, mxa);
1100*9832Samw@Sun.COM 		break;
1101*9832Samw@Sun.COM 
1102*9832Samw@Sun.COM 	case 502:
1103*9832Samw@Sun.COM 		status = mlsvc_NetSessionEnumLevel502(infonres, n_sessions,
1104*9832Samw@Sun.COM 		    mxa);
1105*9832Samw@Sun.COM 		break;
1106*9832Samw@Sun.COM 
11078474SJose.Borrego@Sun.COM 	default:
11088474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
11098474SJose.Borrego@Sun.COM 		break;
11108474SJose.Borrego@Sun.COM 	}
11118474SJose.Borrego@Sun.COM 
11128474SJose.Borrego@Sun.COM 	if (status != 0) {
11138474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetSessionEnum));
11148474SJose.Borrego@Sun.COM 		param->status = status;
11158474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
11168474SJose.Borrego@Sun.COM 	}
11178474SJose.Borrego@Sun.COM 
11188474SJose.Borrego@Sun.COM 	param->total_entries = infonres->entriesread;
11198474SJose.Borrego@Sun.COM 	param->status = status;
11208474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
11218474SJose.Borrego@Sun.COM }
11228474SJose.Borrego@Sun.COM 
11238474SJose.Borrego@Sun.COM /*
11248474SJose.Borrego@Sun.COM  * mlsvc_NetSessionEnumLevel0
11258474SJose.Borrego@Sun.COM  *
11268474SJose.Borrego@Sun.COM  * Build the level 0 session information.
11278474SJose.Borrego@Sun.COM  */
11288474SJose.Borrego@Sun.COM static DWORD
11298474SJose.Borrego@Sun.COM mlsvc_NetSessionEnumLevel0(struct mslm_infonres *infonres, DWORD n_sessions,
11308474SJose.Borrego@Sun.COM     ndr_xa_t *mxa)
11318474SJose.Borrego@Sun.COM {
11328474SJose.Borrego@Sun.COM 	struct mslm_SESSION_INFO_0 *info0;
1133*9832Samw@Sun.COM 	smb_ulist_t *ulist;
11348474SJose.Borrego@Sun.COM 	smb_opipe_context_t *user;
11358474SJose.Borrego@Sun.COM 	char *workstation;
11368670SJose.Borrego@Sun.COM 	char ipaddr_buf[INET6_ADDRSTRLEN];
11378474SJose.Borrego@Sun.COM 	int i;
11388474SJose.Borrego@Sun.COM 
1139*9832Samw@Sun.COM 	ulist = smb_ulist_alloc();
1140*9832Samw@Sun.COM 	if (ulist == NULL)
11418474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
11428474SJose.Borrego@Sun.COM 
1143*9832Samw@Sun.COM 	if (mlsvc_get_user_list(ulist) != 0) {
1144*9832Samw@Sun.COM 		smb_ulist_free(ulist);
11458474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
11468474SJose.Borrego@Sun.COM 	}
11478474SJose.Borrego@Sun.COM 
1148*9832Samw@Sun.COM 	if (ulist->ul_cnt < n_sessions)
1149*9832Samw@Sun.COM 		n_sessions = ulist->ul_cnt;
11508474SJose.Borrego@Sun.COM 
11518474SJose.Borrego@Sun.COM 	info0 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_0, n_sessions);
11528474SJose.Borrego@Sun.COM 	if (info0 == NULL) {
1153*9832Samw@Sun.COM 		smb_ulist_free(ulist);
11548474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
11558474SJose.Borrego@Sun.COM 	}
11568474SJose.Borrego@Sun.COM 
1157*9832Samw@Sun.COM 	user = ulist->ul_users;
1158*9832Samw@Sun.COM 	for (i = 0; i < n_sessions; ++i, user++) {
11598474SJose.Borrego@Sun.COM 		workstation = user->oc_workstation;
11608474SJose.Borrego@Sun.COM 		if (workstation == NULL || *workstation == '\0') {
11618670SJose.Borrego@Sun.COM 			(void) smb_inet_ntop(&user->oc_ipaddr,
11628670SJose.Borrego@Sun.COM 			    ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
11638474SJose.Borrego@Sun.COM 			workstation = ipaddr_buf;
11648474SJose.Borrego@Sun.COM 		}
11658474SJose.Borrego@Sun.COM 
11668474SJose.Borrego@Sun.COM 		info0[i].sesi0_cname = NDR_STRDUP(mxa, workstation);
11678474SJose.Borrego@Sun.COM 		if (info0[i].sesi0_cname == NULL) {
1168*9832Samw@Sun.COM 			smb_ulist_free(ulist);
11698474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
11708474SJose.Borrego@Sun.COM 		}
11718474SJose.Borrego@Sun.COM 	}
11728474SJose.Borrego@Sun.COM 
1173*9832Samw@Sun.COM 	smb_ulist_free(ulist);
11748474SJose.Borrego@Sun.COM 	infonres->entriesread = n_sessions;
11758474SJose.Borrego@Sun.COM 	infonres->entries = info0;
11768474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
11778474SJose.Borrego@Sun.COM }
11788474SJose.Borrego@Sun.COM 
11798474SJose.Borrego@Sun.COM /*
11808474SJose.Borrego@Sun.COM  * mlsvc_NetSessionEnumLevel1
11818474SJose.Borrego@Sun.COM  *
11828474SJose.Borrego@Sun.COM  * Build the level 1 session information.
11838474SJose.Borrego@Sun.COM  */
11848474SJose.Borrego@Sun.COM static DWORD
11858474SJose.Borrego@Sun.COM mlsvc_NetSessionEnumLevel1(struct mslm_infonres *infonres, DWORD n_sessions,
11868474SJose.Borrego@Sun.COM     ndr_xa_t *mxa)
11878474SJose.Borrego@Sun.COM {
11888474SJose.Borrego@Sun.COM 	struct mslm_SESSION_INFO_1 *info1;
1189*9832Samw@Sun.COM 	smb_ulist_t *ulist;
11908474SJose.Borrego@Sun.COM 	smb_opipe_context_t *user;
11918474SJose.Borrego@Sun.COM 	char *workstation;
11928474SJose.Borrego@Sun.COM 	char account[MAXNAMELEN];
11938670SJose.Borrego@Sun.COM 	char ipaddr_buf[INET6_ADDRSTRLEN];
11948474SJose.Borrego@Sun.COM 	int i;
11958474SJose.Borrego@Sun.COM 
1196*9832Samw@Sun.COM 	ulist = smb_ulist_alloc();
1197*9832Samw@Sun.COM 	if (ulist == NULL)
11988474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
11998474SJose.Borrego@Sun.COM 
1200*9832Samw@Sun.COM 	if (mlsvc_get_user_list(ulist) != 0) {
1201*9832Samw@Sun.COM 		smb_ulist_free(ulist);
12028474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
12038474SJose.Borrego@Sun.COM 	}
12048474SJose.Borrego@Sun.COM 
1205*9832Samw@Sun.COM 	if (ulist->ul_cnt < n_sessions)
1206*9832Samw@Sun.COM 		n_sessions = ulist->ul_cnt;
12078474SJose.Borrego@Sun.COM 
12088474SJose.Borrego@Sun.COM 	info1 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_1, n_sessions);
12098474SJose.Borrego@Sun.COM 	if (info1 == NULL) {
1210*9832Samw@Sun.COM 		smb_ulist_free(ulist);
12118474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
12128474SJose.Borrego@Sun.COM 	}
12138474SJose.Borrego@Sun.COM 
1214*9832Samw@Sun.COM 	user = ulist->ul_users;
1215*9832Samw@Sun.COM 	for (i = 0; i < n_sessions; ++i, user++) {
12168474SJose.Borrego@Sun.COM 		workstation = user->oc_workstation;
12178474SJose.Borrego@Sun.COM 		if (workstation == NULL || *workstation == '\0') {
12188670SJose.Borrego@Sun.COM 			(void) smb_inet_ntop(&user->oc_ipaddr,
12198670SJose.Borrego@Sun.COM 			    ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
12208474SJose.Borrego@Sun.COM 			workstation = ipaddr_buf;
12218474SJose.Borrego@Sun.COM 		}
12228474SJose.Borrego@Sun.COM 
12238474SJose.Borrego@Sun.COM 		(void) snprintf(account, MAXNAMELEN, "%s\\%s",
12248474SJose.Borrego@Sun.COM 		    user->oc_domain, user->oc_account);
12258474SJose.Borrego@Sun.COM 
12268474SJose.Borrego@Sun.COM 		info1[i].sesi1_cname = NDR_STRDUP(mxa, workstation);
12278474SJose.Borrego@Sun.COM 		info1[i].sesi1_uname = NDR_STRDUP(mxa, account);
12288474SJose.Borrego@Sun.COM 
12298474SJose.Borrego@Sun.COM 		if (info1[i].sesi1_cname == NULL ||
12308474SJose.Borrego@Sun.COM 		    info1[i].sesi1_uname == NULL) {
1231*9832Samw@Sun.COM 			smb_ulist_free(ulist);
12328474SJose.Borrego@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
12338474SJose.Borrego@Sun.COM 		}
12348474SJose.Borrego@Sun.COM 
12358474SJose.Borrego@Sun.COM 		info1[i].sesi1_nopens = 1;
12368474SJose.Borrego@Sun.COM 		info1[i].sesi1_time = time(0) - user->oc_logon_time;
12378474SJose.Borrego@Sun.COM 		info1[i].sesi1_itime = 0;
12388474SJose.Borrego@Sun.COM 		info1[i].sesi1_uflags =
12398474SJose.Borrego@Sun.COM 		    (user->oc_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0;
12408474SJose.Borrego@Sun.COM 	}
12418474SJose.Borrego@Sun.COM 
1242*9832Samw@Sun.COM 	smb_ulist_free(ulist);
12438474SJose.Borrego@Sun.COM 	infonres->entriesread = n_sessions;
12448474SJose.Borrego@Sun.COM 	infonres->entries = info1;
12458474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
12468474SJose.Borrego@Sun.COM }
12478474SJose.Borrego@Sun.COM 
12488474SJose.Borrego@Sun.COM /*
1249*9832Samw@Sun.COM  * mlsvc_NetSessionEnumLevel2
1250*9832Samw@Sun.COM  *
1251*9832Samw@Sun.COM  * Build the level 2 session information.
1252*9832Samw@Sun.COM  */
1253*9832Samw@Sun.COM static DWORD
1254*9832Samw@Sun.COM mlsvc_NetSessionEnumLevel2(struct mslm_infonres *infonres, DWORD n_sessions,
1255*9832Samw@Sun.COM     ndr_xa_t *mxa)
1256*9832Samw@Sun.COM {
1257*9832Samw@Sun.COM 	struct mslm_SESSION_INFO_2 *info2;
1258*9832Samw@Sun.COM 	smb_ulist_t *ulist;
1259*9832Samw@Sun.COM 	smb_opipe_context_t *user;
1260*9832Samw@Sun.COM 	char *workstation;
1261*9832Samw@Sun.COM 	char account[MAXNAMELEN];
1262*9832Samw@Sun.COM 	char ipaddr_buf[INET6_ADDRSTRLEN];
1263*9832Samw@Sun.COM 	int i;
1264*9832Samw@Sun.COM 
1265*9832Samw@Sun.COM 	if ((ulist = smb_ulist_alloc()) == NULL)
1266*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1267*9832Samw@Sun.COM 
1268*9832Samw@Sun.COM 	if (mlsvc_get_user_list(ulist) != 0) {
1269*9832Samw@Sun.COM 		smb_ulist_free(ulist);
1270*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1271*9832Samw@Sun.COM 	}
1272*9832Samw@Sun.COM 
1273*9832Samw@Sun.COM 	if (ulist->ul_cnt < n_sessions)
1274*9832Samw@Sun.COM 		n_sessions = ulist->ul_cnt;
1275*9832Samw@Sun.COM 
1276*9832Samw@Sun.COM 	info2 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_2, n_sessions);
1277*9832Samw@Sun.COM 	if (info2 == NULL) {
1278*9832Samw@Sun.COM 		smb_ulist_free(ulist);
1279*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1280*9832Samw@Sun.COM 	}
1281*9832Samw@Sun.COM 
1282*9832Samw@Sun.COM 	user = ulist->ul_users;
1283*9832Samw@Sun.COM 	for (i = 0; i < n_sessions; ++i, user++) {
1284*9832Samw@Sun.COM 		workstation = user->oc_workstation;
1285*9832Samw@Sun.COM 		if (workstation == NULL || *workstation == '\0') {
1286*9832Samw@Sun.COM 			(void) smb_inet_ntop(&user->oc_ipaddr,
1287*9832Samw@Sun.COM 			    ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
1288*9832Samw@Sun.COM 			workstation = ipaddr_buf;
1289*9832Samw@Sun.COM 		}
1290*9832Samw@Sun.COM 
1291*9832Samw@Sun.COM 		(void) snprintf(account, MAXNAMELEN, "%s\\%s",
1292*9832Samw@Sun.COM 		    user->oc_domain, user->oc_account);
1293*9832Samw@Sun.COM 
1294*9832Samw@Sun.COM 		info2[i].sesi2_cname = NDR_STRDUP(mxa, workstation);
1295*9832Samw@Sun.COM 		info2[i].sesi2_uname = NDR_STRDUP(mxa, account);
1296*9832Samw@Sun.COM 
1297*9832Samw@Sun.COM 		if (info2[i].sesi2_cname == NULL ||
1298*9832Samw@Sun.COM 		    info2[i].sesi2_uname == NULL) {
1299*9832Samw@Sun.COM 			smb_ulist_free(ulist);
1300*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
1301*9832Samw@Sun.COM 		}
1302*9832Samw@Sun.COM 
1303*9832Samw@Sun.COM 		info2[i].sesi2_nopens = 1;
1304*9832Samw@Sun.COM 		info2[i].sesi2_time = time(0) - user->oc_logon_time;
1305*9832Samw@Sun.COM 		info2[i].sesi2_itime = 0;
1306*9832Samw@Sun.COM 		info2[i].sesi2_uflags =
1307*9832Samw@Sun.COM 		    (user->oc_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0;
1308*9832Samw@Sun.COM 		info2[i].sesi2_cltype_name = (uint8_t *)"";
1309*9832Samw@Sun.COM 	}
1310*9832Samw@Sun.COM 
1311*9832Samw@Sun.COM 	smb_ulist_free(ulist);
1312*9832Samw@Sun.COM 	infonres->entriesread = n_sessions;
1313*9832Samw@Sun.COM 	infonres->entries = info2;
1314*9832Samw@Sun.COM 	return (ERROR_SUCCESS);
1315*9832Samw@Sun.COM }
1316*9832Samw@Sun.COM 
1317*9832Samw@Sun.COM /*
1318*9832Samw@Sun.COM  * mlsvc_NetSessionEnumLevel10
1319*9832Samw@Sun.COM  *
1320*9832Samw@Sun.COM  * Build the level 10 session information.
1321*9832Samw@Sun.COM  */
1322*9832Samw@Sun.COM static DWORD
1323*9832Samw@Sun.COM mlsvc_NetSessionEnumLevel10(struct mslm_infonres *infonres, DWORD n_sessions,
1324*9832Samw@Sun.COM     ndr_xa_t *mxa)
1325*9832Samw@Sun.COM {
1326*9832Samw@Sun.COM 	struct mslm_SESSION_INFO_10 *info10;
1327*9832Samw@Sun.COM 	smb_ulist_t *ulist;
1328*9832Samw@Sun.COM 	smb_opipe_context_t *user;
1329*9832Samw@Sun.COM 	char *workstation;
1330*9832Samw@Sun.COM 	char account[MAXNAMELEN];
1331*9832Samw@Sun.COM 	char ipaddr_buf[INET6_ADDRSTRLEN];
1332*9832Samw@Sun.COM 	int i;
1333*9832Samw@Sun.COM 
1334*9832Samw@Sun.COM 	if ((ulist = smb_ulist_alloc()) == NULL)
1335*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1336*9832Samw@Sun.COM 
1337*9832Samw@Sun.COM 	if (mlsvc_get_user_list(ulist) != 0) {
1338*9832Samw@Sun.COM 		smb_ulist_free(ulist);
1339*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1340*9832Samw@Sun.COM 	}
1341*9832Samw@Sun.COM 
1342*9832Samw@Sun.COM 	if (ulist->ul_cnt < n_sessions)
1343*9832Samw@Sun.COM 		n_sessions = ulist->ul_cnt;
1344*9832Samw@Sun.COM 
1345*9832Samw@Sun.COM 	info10 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_10, n_sessions);
1346*9832Samw@Sun.COM 	if (info10 == NULL) {
1347*9832Samw@Sun.COM 		smb_ulist_free(ulist);
1348*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1349*9832Samw@Sun.COM 	}
1350*9832Samw@Sun.COM 
1351*9832Samw@Sun.COM 	user = ulist->ul_users;
1352*9832Samw@Sun.COM 	for (i = 0; i < n_sessions; ++i, user++) {
1353*9832Samw@Sun.COM 		workstation = user->oc_workstation;
1354*9832Samw@Sun.COM 		if (workstation == NULL || *workstation == '\0') {
1355*9832Samw@Sun.COM 			(void) smb_inet_ntop(&user->oc_ipaddr,
1356*9832Samw@Sun.COM 			    ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
1357*9832Samw@Sun.COM 			workstation = ipaddr_buf;
1358*9832Samw@Sun.COM 		}
1359*9832Samw@Sun.COM 
1360*9832Samw@Sun.COM 		(void) snprintf(account, MAXNAMELEN, "%s\\%s",
1361*9832Samw@Sun.COM 		    user->oc_domain, user->oc_account);
1362*9832Samw@Sun.COM 
1363*9832Samw@Sun.COM 		info10[i].sesi10_cname = NDR_STRDUP(mxa, workstation);
1364*9832Samw@Sun.COM 		info10[i].sesi10_uname = NDR_STRDUP(mxa, account);
1365*9832Samw@Sun.COM 
1366*9832Samw@Sun.COM 		if (info10[i].sesi10_cname == NULL ||
1367*9832Samw@Sun.COM 		    info10[i].sesi10_uname == NULL) {
1368*9832Samw@Sun.COM 			smb_ulist_free(ulist);
1369*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
1370*9832Samw@Sun.COM 		}
1371*9832Samw@Sun.COM 
1372*9832Samw@Sun.COM 		info10[i].sesi10_time = time(0) - user->oc_logon_time;
1373*9832Samw@Sun.COM 		info10[i].sesi10_itime = 0;
1374*9832Samw@Sun.COM 	}
1375*9832Samw@Sun.COM 
1376*9832Samw@Sun.COM 	smb_ulist_free(ulist);
1377*9832Samw@Sun.COM 	infonres->entriesread = n_sessions;
1378*9832Samw@Sun.COM 	infonres->entries = info10;
1379*9832Samw@Sun.COM 	return (ERROR_SUCCESS);
1380*9832Samw@Sun.COM }
1381*9832Samw@Sun.COM 
1382*9832Samw@Sun.COM /*
1383*9832Samw@Sun.COM  * mlsvc_NetSessionEnumLevel502
1384*9832Samw@Sun.COM  *
1385*9832Samw@Sun.COM  * Build the level 502 session information.
1386*9832Samw@Sun.COM  */
1387*9832Samw@Sun.COM static DWORD
1388*9832Samw@Sun.COM mlsvc_NetSessionEnumLevel502(struct mslm_infonres *infonres, DWORD n_sessions,
1389*9832Samw@Sun.COM     ndr_xa_t *mxa)
1390*9832Samw@Sun.COM {
1391*9832Samw@Sun.COM 	struct mslm_SESSION_INFO_502 *info502;
1392*9832Samw@Sun.COM 	smb_ulist_t *ulist;
1393*9832Samw@Sun.COM 	smb_opipe_context_t *user;
1394*9832Samw@Sun.COM 	char *workstation;
1395*9832Samw@Sun.COM 	char account[MAXNAMELEN];
1396*9832Samw@Sun.COM 	char ipaddr_buf[INET6_ADDRSTRLEN];
1397*9832Samw@Sun.COM 	int i;
1398*9832Samw@Sun.COM 
1399*9832Samw@Sun.COM 	if ((ulist = smb_ulist_alloc()) == NULL)
1400*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1401*9832Samw@Sun.COM 
1402*9832Samw@Sun.COM 	if (mlsvc_get_user_list(ulist) != 0) {
1403*9832Samw@Sun.COM 		smb_ulist_free(ulist);
1404*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1405*9832Samw@Sun.COM 	}
1406*9832Samw@Sun.COM 
1407*9832Samw@Sun.COM 	if (ulist->ul_cnt < n_sessions)
1408*9832Samw@Sun.COM 		n_sessions = ulist->ul_cnt;
1409*9832Samw@Sun.COM 
1410*9832Samw@Sun.COM 	info502 = NDR_NEWN(mxa, struct mslm_SESSION_INFO_502, n_sessions);
1411*9832Samw@Sun.COM 	if (info502 == NULL) {
1412*9832Samw@Sun.COM 		smb_ulist_free(ulist);
1413*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
1414*9832Samw@Sun.COM 	}
1415*9832Samw@Sun.COM 
1416*9832Samw@Sun.COM 	user = ulist->ul_users;
1417*9832Samw@Sun.COM 	for (i = 0; i < n_sessions; ++i, user++) {
1418*9832Samw@Sun.COM 		workstation = user->oc_workstation;
1419*9832Samw@Sun.COM 		if (workstation == NULL || *workstation == '\0') {
1420*9832Samw@Sun.COM 			(void) smb_inet_ntop(&user->oc_ipaddr,
1421*9832Samw@Sun.COM 			    ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
1422*9832Samw@Sun.COM 			workstation = ipaddr_buf;
1423*9832Samw@Sun.COM 		}
1424*9832Samw@Sun.COM 
1425*9832Samw@Sun.COM 		(void) snprintf(account, MAXNAMELEN, "%s\\%s",
1426*9832Samw@Sun.COM 		    user->oc_domain, user->oc_account);
1427*9832Samw@Sun.COM 
1428*9832Samw@Sun.COM 		info502[i].sesi502_cname = NDR_STRDUP(mxa, workstation);
1429*9832Samw@Sun.COM 		info502[i].sesi502_uname = NDR_STRDUP(mxa, account);
1430*9832Samw@Sun.COM 
1431*9832Samw@Sun.COM 		if (info502[i].sesi502_cname == NULL ||
1432*9832Samw@Sun.COM 		    info502[i].sesi502_uname == NULL) {
1433*9832Samw@Sun.COM 			smb_ulist_free(ulist);
1434*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
1435*9832Samw@Sun.COM 		}
1436*9832Samw@Sun.COM 
1437*9832Samw@Sun.COM 		info502[i].sesi502_nopens = 1;
1438*9832Samw@Sun.COM 		info502[i].sesi502_time = time(0) - user->oc_logon_time;
1439*9832Samw@Sun.COM 		info502[i].sesi502_itime = 0;
1440*9832Samw@Sun.COM 		info502[i].sesi502_uflags =
1441*9832Samw@Sun.COM 		    (user->oc_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0;
1442*9832Samw@Sun.COM 		info502[i].sesi502_cltype_name = (uint8_t *)"";
1443*9832Samw@Sun.COM 		info502[i].sesi502_transport = (uint8_t *)"";
1444*9832Samw@Sun.COM 	}
1445*9832Samw@Sun.COM 
1446*9832Samw@Sun.COM 	smb_ulist_free(ulist);
1447*9832Samw@Sun.COM 	infonres->entriesread = n_sessions;
1448*9832Samw@Sun.COM 	infonres->entries = info502;
1449*9832Samw@Sun.COM 	return (ERROR_SUCCESS);
1450*9832Samw@Sun.COM }
1451*9832Samw@Sun.COM 
1452*9832Samw@Sun.COM /*
14538474SJose.Borrego@Sun.COM  * srvsvc_s_NetSessionDel
14548474SJose.Borrego@Sun.COM  *
14558474SJose.Borrego@Sun.COM  * Ends a network session between a server and a workstation.
14568474SJose.Borrego@Sun.COM  * On NT only members of the Administrators or Account Operators
14578474SJose.Borrego@Sun.COM  * local groups are permitted to use NetSessionDel.
14588474SJose.Borrego@Sun.COM  *
14598474SJose.Borrego@Sun.COM  * Return Values
14608474SJose.Borrego@Sun.COM  * If the function succeeds, the return value is NERR_Success/
14618474SJose.Borrego@Sun.COM  * ERROR_SUCCESS. If the function fails, the return value can be
14628474SJose.Borrego@Sun.COM  * one of the following error codes:
14638474SJose.Borrego@Sun.COM  *
14648474SJose.Borrego@Sun.COM  * ERROR_ACCESS_DENIED 		The user does not have access to the
14658474SJose.Borrego@Sun.COM  * 							requested information.
14668474SJose.Borrego@Sun.COM  * ERROR_INVALID_PARAMETER	The specified parameter is invalid.
14678474SJose.Borrego@Sun.COM  * ERROR_NOT_ENOUGH_MEMORY	Insufficient memory is available.
14688474SJose.Borrego@Sun.COM  * NERR_ClientNameNotFound	A session does not exist with that
14698474SJose.Borrego@Sun.COM  *                          computer name.
14708474SJose.Borrego@Sun.COM  */
14718474SJose.Borrego@Sun.COM static int
14728474SJose.Borrego@Sun.COM srvsvc_s_NetSessionDel(void *arg, ndr_xa_t *mxa)
14738474SJose.Borrego@Sun.COM {
14748474SJose.Borrego@Sun.COM 	struct mslm_NetSessionDel *param = arg;
14758474SJose.Borrego@Sun.COM 
14768474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
14778474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
14788474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
14798474SJose.Borrego@Sun.COM 	}
14808474SJose.Borrego@Sun.COM 
14818474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
14828474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
14838474SJose.Borrego@Sun.COM }
14848474SJose.Borrego@Sun.COM 
14858474SJose.Borrego@Sun.COM /*
14868474SJose.Borrego@Sun.COM  * SRVSVC NetServerGetInfo
14878474SJose.Borrego@Sun.COM  *
14888474SJose.Borrego@Sun.COM  *	IN	LPTSTR servername,
14898474SJose.Borrego@Sun.COM  *	IN	DWORD level,
14908474SJose.Borrego@Sun.COM  *	OUT	union switch(level) {
14918474SJose.Borrego@Sun.COM  *		case 100:	mslm_SERVER_INFO_100 *p100;
14928474SJose.Borrego@Sun.COM  *		case 101:	mslm_SERVER_INFO_101 *p101;
14938474SJose.Borrego@Sun.COM  *		case 102:	mslm_SERVER_INFO_102 *p102;
1494*9832Samw@Sun.COM  *		...
14958474SJose.Borrego@Sun.COM  *		default:	char *nullptr;
14968474SJose.Borrego@Sun.COM  *		} bufptr,
14978474SJose.Borrego@Sun.COM  *	OUT	DWORD status
14988474SJose.Borrego@Sun.COM  */
14998474SJose.Borrego@Sun.COM static int
15008474SJose.Borrego@Sun.COM srvsvc_s_NetServerGetInfo(void *arg, ndr_xa_t *mxa)
15018474SJose.Borrego@Sun.COM {
15028474SJose.Borrego@Sun.COM 	struct mslm_NetServerGetInfo *param = arg;
15038474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_100 *info100;
15048474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_101 *info101;
15058474SJose.Borrego@Sun.COM 	struct mslm_SERVER_INFO_102 *info102;
1506*9832Samw@Sun.COM 	struct mslm_SERVER_INFO_502 *info502;
1507*9832Samw@Sun.COM 	struct mslm_SERVER_INFO_503 *info503;
15088474SJose.Borrego@Sun.COM 	char sys_comment[SMB_PI_MAX_COMMENT];
15098474SJose.Borrego@Sun.COM 	char hostname[NETBIOS_NAME_SZ];
15108474SJose.Borrego@Sun.COM 
15118474SJose.Borrego@Sun.COM 	if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) {
15128474SJose.Borrego@Sun.COM netservergetinfo_no_memory:
15138474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetServerGetInfo));
15148474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
15158474SJose.Borrego@Sun.COM 	}
15168474SJose.Borrego@Sun.COM 
15178474SJose.Borrego@Sun.COM 	(void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment,
15188474SJose.Borrego@Sun.COM 	    sizeof (sys_comment));
15198474SJose.Borrego@Sun.COM 	if (*sys_comment == '\0')
15208474SJose.Borrego@Sun.COM 		(void) strcpy(sys_comment, " ");
15218474SJose.Borrego@Sun.COM 
15228474SJose.Borrego@Sun.COM 	switch (param->level) {
15238474SJose.Borrego@Sun.COM 	case 100:
15248474SJose.Borrego@Sun.COM 		info100 = NDR_NEW(mxa, struct mslm_SERVER_INFO_100);
15258474SJose.Borrego@Sun.COM 		if (info100 == NULL)
15268474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
15278474SJose.Borrego@Sun.COM 
15288474SJose.Borrego@Sun.COM 		bzero(info100, sizeof (struct mslm_SERVER_INFO_100));
15298474SJose.Borrego@Sun.COM 		info100->sv100_platform_id = SV_PLATFORM_ID_NT;
15308474SJose.Borrego@Sun.COM 		info100->sv100_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
15318474SJose.Borrego@Sun.COM 		if (info100->sv100_name == NULL)
15328474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
15338474SJose.Borrego@Sun.COM 
15348474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr100 = info100;
15358474SJose.Borrego@Sun.COM 		break;
15368474SJose.Borrego@Sun.COM 
15378474SJose.Borrego@Sun.COM 	case 101:
15388474SJose.Borrego@Sun.COM 		info101 = NDR_NEW(mxa, struct mslm_SERVER_INFO_101);
15398474SJose.Borrego@Sun.COM 		if (info101 == NULL)
15408474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
15418474SJose.Borrego@Sun.COM 
15428474SJose.Borrego@Sun.COM 		bzero(info101, sizeof (struct mslm_SERVER_INFO_101));
15438474SJose.Borrego@Sun.COM 		info101->sv101_platform_id = SV_PLATFORM_ID_NT;
15448474SJose.Borrego@Sun.COM 		info101->sv101_version_major = 4;
15458474SJose.Borrego@Sun.COM 		info101->sv101_version_minor = 0;
15468474SJose.Borrego@Sun.COM 		info101->sv101_type = SV_TYPE_SENT_BY_ME;
15478474SJose.Borrego@Sun.COM 		info101->sv101_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
15488474SJose.Borrego@Sun.COM 		info101->sv101_comment
15498474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, sys_comment);
15508474SJose.Borrego@Sun.COM 
15518474SJose.Borrego@Sun.COM 		if (info101->sv101_name == NULL ||
15528474SJose.Borrego@Sun.COM 		    info101->sv101_comment == NULL)
15538474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
15548474SJose.Borrego@Sun.COM 
15558474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr101 = info101;
15568474SJose.Borrego@Sun.COM 		break;
15578474SJose.Borrego@Sun.COM 
15588474SJose.Borrego@Sun.COM 	case 102:
15598474SJose.Borrego@Sun.COM 		info102 = NDR_NEW(mxa, struct mslm_SERVER_INFO_102);
15608474SJose.Borrego@Sun.COM 		if (info102 == NULL)
15618474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
15628474SJose.Borrego@Sun.COM 
15638474SJose.Borrego@Sun.COM 		bzero(info102, sizeof (struct mslm_SERVER_INFO_102));
15648474SJose.Borrego@Sun.COM 		info102->sv102_platform_id = SV_PLATFORM_ID_NT;
15658474SJose.Borrego@Sun.COM 		info102->sv102_version_major = 4;
15668474SJose.Borrego@Sun.COM 		info102->sv102_version_minor = 0;
15678474SJose.Borrego@Sun.COM 		info102->sv102_type = SV_TYPE_SENT_BY_ME;
15688474SJose.Borrego@Sun.COM 		info102->sv102_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
15698474SJose.Borrego@Sun.COM 		info102->sv102_comment
15708474SJose.Borrego@Sun.COM 		    = (uint8_t *)NDR_STRDUP(mxa, sys_comment);
15718474SJose.Borrego@Sun.COM 
15728474SJose.Borrego@Sun.COM 		/*
15738474SJose.Borrego@Sun.COM 		 * The following level 102 fields are defaulted to zero
15748474SJose.Borrego@Sun.COM 		 * by virtue of the call to bzero above.
15758474SJose.Borrego@Sun.COM 		 *
15768474SJose.Borrego@Sun.COM 		 * sv102_users
15778474SJose.Borrego@Sun.COM 		 * sv102_disc
15788474SJose.Borrego@Sun.COM 		 * sv102_hidden
15798474SJose.Borrego@Sun.COM 		 * sv102_announce
15808474SJose.Borrego@Sun.COM 		 * sv102_anndelta
15818474SJose.Borrego@Sun.COM 		 * sv102_licenses
15828474SJose.Borrego@Sun.COM 		 * sv102_userpath
15838474SJose.Borrego@Sun.COM 		 */
15848474SJose.Borrego@Sun.COM 		if (info102->sv102_name == NULL ||
15858474SJose.Borrego@Sun.COM 		    info102->sv102_comment == NULL)
15868474SJose.Borrego@Sun.COM 			goto netservergetinfo_no_memory;
15878474SJose.Borrego@Sun.COM 
15888474SJose.Borrego@Sun.COM 		param->result.bufptr.bufptr102 = info102;
15898474SJose.Borrego@Sun.COM 		break;
15908474SJose.Borrego@Sun.COM 
1591*9832Samw@Sun.COM 	case 502:
1592*9832Samw@Sun.COM 		info502 = NDR_NEW(mxa, struct mslm_SERVER_INFO_502);
1593*9832Samw@Sun.COM 		if (info502 == NULL)
1594*9832Samw@Sun.COM 			goto netservergetinfo_no_memory;
1595*9832Samw@Sun.COM 
1596*9832Samw@Sun.COM 		bzero(info502, sizeof (struct mslm_SERVER_INFO_502));
1597*9832Samw@Sun.COM 		param->result.bufptr.bufptr502 = info502;
1598*9832Samw@Sun.COM #ifdef SRVSVC_SATISFY_SMBTORTURE
1599*9832Samw@Sun.COM 		break;
1600*9832Samw@Sun.COM #else
1601*9832Samw@Sun.COM 		param->result.level = param->level;
1602*9832Samw@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
1603*9832Samw@Sun.COM 		return (NDR_DRC_OK);
1604*9832Samw@Sun.COM #endif /* SRVSVC_SATISFY_SMBTORTURE */
1605*9832Samw@Sun.COM 
1606*9832Samw@Sun.COM 	case 503:
1607*9832Samw@Sun.COM 		info503 = NDR_NEW(mxa, struct mslm_SERVER_INFO_503);
1608*9832Samw@Sun.COM 		if (info503 == NULL)
1609*9832Samw@Sun.COM 			goto netservergetinfo_no_memory;
1610*9832Samw@Sun.COM 
1611*9832Samw@Sun.COM 		bzero(info503, sizeof (struct mslm_SERVER_INFO_503));
1612*9832Samw@Sun.COM 		param->result.bufptr.bufptr503 = info503;
1613*9832Samw@Sun.COM #ifdef SRVSVC_SATISFY_SMBTORTURE
1614*9832Samw@Sun.COM 		break;
1615*9832Samw@Sun.COM #else
1616*9832Samw@Sun.COM 		param->result.level = param->level;
1617*9832Samw@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
1618*9832Samw@Sun.COM 		return (NDR_DRC_OK);
1619*9832Samw@Sun.COM #endif /* SRVSVC_SATISFY_SMBTORTURE */
1620*9832Samw@Sun.COM 
16218474SJose.Borrego@Sun.COM 	default:
16228474SJose.Borrego@Sun.COM 		bzero(&param->result,
16238474SJose.Borrego@Sun.COM 		    sizeof (struct mslm_NetServerGetInfo_result));
16248474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
16258474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
16268474SJose.Borrego@Sun.COM 	}
16278474SJose.Borrego@Sun.COM 
16288474SJose.Borrego@Sun.COM 	param->result.level = param->level;
1629*9832Samw@Sun.COM 	param->status = ERROR_SUCCESS;
16308474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
16318474SJose.Borrego@Sun.COM }
16328474SJose.Borrego@Sun.COM 
16338474SJose.Borrego@Sun.COM /*
16348474SJose.Borrego@Sun.COM  * NetRemoteTOD
16358474SJose.Borrego@Sun.COM  *
16368474SJose.Borrego@Sun.COM  * Returns information about the time of day on this server.
16378474SJose.Borrego@Sun.COM  *
16388474SJose.Borrego@Sun.COM  * typedef struct _TIME_OF_DAY_INFO {
16398474SJose.Borrego@Sun.COM  *	DWORD tod_elapsedt;  // seconds since 00:00:00 January 1 1970 GMT
16408474SJose.Borrego@Sun.COM  *	DWORD tod_msecs;     // arbitrary milliseconds (since reset)
16418474SJose.Borrego@Sun.COM  *	DWORD tod_hours;     // current hour [0-23]
16428474SJose.Borrego@Sun.COM  *	DWORD tod_mins;      // current minute [0-59]
16438474SJose.Borrego@Sun.COM  *	DWORD tod_secs;      // current second [0-59]
16448474SJose.Borrego@Sun.COM  *	DWORD tod_hunds;     // current hundredth (0.01) second [0-99]
16458474SJose.Borrego@Sun.COM  *	LONG tod_timezone;   // time zone of the server
16468474SJose.Borrego@Sun.COM  *	DWORD tod_tinterval; // clock tick time interval
16478474SJose.Borrego@Sun.COM  *	DWORD tod_day;       // day of the month [1-31]
16488474SJose.Borrego@Sun.COM  *	DWORD tod_month;     // month of the year [1-12]
16498474SJose.Borrego@Sun.COM  *	DWORD tod_year;      // current year
16508474SJose.Borrego@Sun.COM  *	DWORD tod_weekday;   // day of the week since Sunday [0-6]
16518474SJose.Borrego@Sun.COM  * } TIME_OF_DAY_INFO;
16528474SJose.Borrego@Sun.COM  *
16538474SJose.Borrego@Sun.COM  * The time zone of the server is calculated in minutes from Greenwich
16548474SJose.Borrego@Sun.COM  * Mean Time (GMT). For time zones west of Greenwich, the value is
16558474SJose.Borrego@Sun.COM  * positive; for time zones east of Greenwich, the value is negative.
16568474SJose.Borrego@Sun.COM  * A value of -1 indicates that the time zone is undefined.
16578474SJose.Borrego@Sun.COM  *
16588474SJose.Borrego@Sun.COM  * The clock tick value represents a resolution of one ten-thousandth
16598474SJose.Borrego@Sun.COM  * (0.0001) second.
16608474SJose.Borrego@Sun.COM  */
16618474SJose.Borrego@Sun.COM static int
16628474SJose.Borrego@Sun.COM srvsvc_s_NetRemoteTOD(void *arg, ndr_xa_t *mxa)
16638474SJose.Borrego@Sun.COM {
16648474SJose.Borrego@Sun.COM 	struct mslm_NetRemoteTOD *param = arg;
16658474SJose.Borrego@Sun.COM 	struct mslm_TIME_OF_DAY_INFO *tod;
16668474SJose.Borrego@Sun.COM 	struct timeval		time_val;
16678474SJose.Borrego@Sun.COM 	struct tm		tm;
16688474SJose.Borrego@Sun.COM 
16698474SJose.Borrego@Sun.COM 	(void) gettimeofday(&time_val, 0);
16708474SJose.Borrego@Sun.COM 	(void) gmtime_r(&time_val.tv_sec, &tm);
16718474SJose.Borrego@Sun.COM 
16728474SJose.Borrego@Sun.COM 	tod = NDR_NEW(mxa, struct mslm_TIME_OF_DAY_INFO);
16738474SJose.Borrego@Sun.COM 	if (tod == NULL) {
16748474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetRemoteTOD));
16758474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
16768474SJose.Borrego@Sun.COM 	}
16778474SJose.Borrego@Sun.COM 
16788474SJose.Borrego@Sun.COM 	tod->tod_elapsedt = time_val.tv_sec;
16798474SJose.Borrego@Sun.COM 	tod->tod_msecs = time_val.tv_usec;
16808474SJose.Borrego@Sun.COM 	tod->tod_hours = tm.tm_hour;
16818474SJose.Borrego@Sun.COM 	tod->tod_mins = tm.tm_min;
16828474SJose.Borrego@Sun.COM 	tod->tod_secs = tm.tm_sec;
16838474SJose.Borrego@Sun.COM 	tod->tod_hunds = 0;
16848474SJose.Borrego@Sun.COM 	tod->tod_tinterval = 1000;
16858474SJose.Borrego@Sun.COM 	tod->tod_day = tm.tm_mday;
16868474SJose.Borrego@Sun.COM 	tod->tod_month = tm.tm_mon+1;
16878474SJose.Borrego@Sun.COM 	tod->tod_year = tm.tm_year+1900;
16888474SJose.Borrego@Sun.COM 	tod->tod_weekday = tm.tm_wday;
16898474SJose.Borrego@Sun.COM 
16908474SJose.Borrego@Sun.COM 	(void) localtime_r(&time_val.tv_sec, &tm);
16918474SJose.Borrego@Sun.COM 
16928474SJose.Borrego@Sun.COM 	param->bufptr = tod;
16938474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
16948474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
16958474SJose.Borrego@Sun.COM }
16968474SJose.Borrego@Sun.COM 
16978474SJose.Borrego@Sun.COM /*
16988474SJose.Borrego@Sun.COM  * srvsvc_s_NetNameValidate
16998474SJose.Borrego@Sun.COM  *
17008474SJose.Borrego@Sun.COM  * Perform name validation.
17018474SJose.Borrego@Sun.COM  *
17028474SJose.Borrego@Sun.COM  * The share name is considered invalid if it contains any of the
17038474SJose.Borrego@Sun.COM  * following character (MSDN 236388).
17048474SJose.Borrego@Sun.COM  *
17058474SJose.Borrego@Sun.COM  * " / \ [ ] : | < > + ; , ? * =
17068474SJose.Borrego@Sun.COM  *
17078474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
17088474SJose.Borrego@Sun.COM  */
17098474SJose.Borrego@Sun.COM /*ARGSUSED*/
17108474SJose.Borrego@Sun.COM static int
17118474SJose.Borrego@Sun.COM srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa)
17128474SJose.Borrego@Sun.COM {
17138474SJose.Borrego@Sun.COM 	struct mslm_NetNameValidate *param = arg;
17148474SJose.Borrego@Sun.COM 	char *name;
17158474SJose.Borrego@Sun.COM 	int len;
17168474SJose.Borrego@Sun.COM 
17178474SJose.Borrego@Sun.COM 	if ((name = (char *)param->pathname) == NULL) {
17188474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
17198474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
17208474SJose.Borrego@Sun.COM 	}
17218474SJose.Borrego@Sun.COM 
17228474SJose.Borrego@Sun.COM 	len = strlen(name);
17238474SJose.Borrego@Sun.COM 
17248474SJose.Borrego@Sun.COM 	if ((param->flags == 0 && len > 81) ||
17258474SJose.Borrego@Sun.COM 	    (param->flags == 0x80000000 && len > 13)) {
17268474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_NAME;
17278474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
17288474SJose.Borrego@Sun.COM 	}
17298474SJose.Borrego@Sun.COM 
17308474SJose.Borrego@Sun.COM 	switch (param->type) {
17318474SJose.Borrego@Sun.COM 	case NAMETYPE_SHARE:
17328474SJose.Borrego@Sun.COM 		if (smb_shr_chkname(name))
17338474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
17348474SJose.Borrego@Sun.COM 		else
17358474SJose.Borrego@Sun.COM 			param->status = ERROR_INVALID_NAME;
17368474SJose.Borrego@Sun.COM 		break;
17378474SJose.Borrego@Sun.COM 
17388474SJose.Borrego@Sun.COM 	case NAMETYPE_USER:
17398474SJose.Borrego@Sun.COM 	case NAMETYPE_PASSWORD:
17408474SJose.Borrego@Sun.COM 	case NAMETYPE_GROUP:
17418474SJose.Borrego@Sun.COM 	case NAMETYPE_COMPUTER:
17428474SJose.Borrego@Sun.COM 	case NAMETYPE_EVENT:
17438474SJose.Borrego@Sun.COM 	case NAMETYPE_DOMAIN:
17448474SJose.Borrego@Sun.COM 	case NAMETYPE_SERVICE:
17458474SJose.Borrego@Sun.COM 	case NAMETYPE_NET:
17468474SJose.Borrego@Sun.COM 	case NAMETYPE_MESSAGE:
17478474SJose.Borrego@Sun.COM 	case NAMETYPE_MESSAGEDEST:
17488474SJose.Borrego@Sun.COM 	case NAMETYPE_SHAREPASSWORD:
17498474SJose.Borrego@Sun.COM 	case NAMETYPE_WORKGROUP:
17508474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_SUPPORTED;
17518474SJose.Borrego@Sun.COM 		break;
17528474SJose.Borrego@Sun.COM 
17538474SJose.Borrego@Sun.COM 	default:
17548474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
17558474SJose.Borrego@Sun.COM 		break;
17568474SJose.Borrego@Sun.COM 	}
17578474SJose.Borrego@Sun.COM 
17588474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
17598474SJose.Borrego@Sun.COM }
17608474SJose.Borrego@Sun.COM 
17618474SJose.Borrego@Sun.COM /*
17628474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareAdd
17638474SJose.Borrego@Sun.COM  *
1764*9832Samw@Sun.COM  * Add a new share. Only power users groups can manage shares.
17658474SJose.Borrego@Sun.COM  *
17668474SJose.Borrego@Sun.COM  * This interface is used by the rmtshare command from the NT resource
17678474SJose.Borrego@Sun.COM  * kit. Rmtshare allows a client to add or remove shares on a server
17688474SJose.Borrego@Sun.COM  * from the client's command line.
17698474SJose.Borrego@Sun.COM  *
17708474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
17718474SJose.Borrego@Sun.COM  */
17728474SJose.Borrego@Sun.COM static int
17738474SJose.Borrego@Sun.COM srvsvc_s_NetShareAdd(void *arg, ndr_xa_t *mxa)
17748474SJose.Borrego@Sun.COM {
17758474SJose.Borrego@Sun.COM 	static DWORD parm_err = 0;
17768474SJose.Borrego@Sun.COM 	DWORD parm_stat;
17778474SJose.Borrego@Sun.COM 	struct mslm_NetShareAdd *param = arg;
17789343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
1779*9832Samw@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
17808474SJose.Borrego@Sun.COM 	char realpath[MAXPATHLEN];
17818474SJose.Borrego@Sun.COM 	int32_t native_os;
1782*9832Samw@Sun.COM 	uint8_t *sdbuf = NULL;
1783*9832Samw@Sun.COM 	uint32_t status;
1784*9832Samw@Sun.COM 	smb_share_t si;
17858474SJose.Borrego@Sun.COM 
17868474SJose.Borrego@Sun.COM 	native_os = ndr_native_os(mxa);
17878474SJose.Borrego@Sun.COM 
17888474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa)) {
17898474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
17908474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
17918474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
17928474SJose.Borrego@Sun.COM 	}
17938474SJose.Borrego@Sun.COM 
17948474SJose.Borrego@Sun.COM 	switch (param->level) {
17958474SJose.Borrego@Sun.COM 	case 2:
1796*9832Samw@Sun.COM 		info2 = (struct mslm_NetShareInfo_2 *)param->info.un.info2;
17978474SJose.Borrego@Sun.COM 		break;
17988474SJose.Borrego@Sun.COM 
17998474SJose.Borrego@Sun.COM 	case 502:
1800*9832Samw@Sun.COM 		info502 = (struct mslm_NetShareInfo_502 *)
1801*9832Samw@Sun.COM 		    param->info.un.info502;
1802*9832Samw@Sun.COM 		sdbuf = info502->shi502_security_descriptor;
1803*9832Samw@Sun.COM 		info2 = (struct mslm_NetShareInfo_2 *)info502;
18048474SJose.Borrego@Sun.COM 		break;
18058474SJose.Borrego@Sun.COM 
18068474SJose.Borrego@Sun.COM 	default:
18078474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
18088474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
18098474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
18108474SJose.Borrego@Sun.COM 	}
18118474SJose.Borrego@Sun.COM 
18128474SJose.Borrego@Sun.COM 	if (info2->shi2_netname == NULL || info2->shi2_path == NULL) {
18138474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
18148474SJose.Borrego@Sun.COM 		param->status = NERR_NetNameNotFound;
18158474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
18168474SJose.Borrego@Sun.COM 	}
18178474SJose.Borrego@Sun.COM 
18188474SJose.Borrego@Sun.COM 	if (smb_shr_is_restricted((char *)info2->shi2_netname)) {
18198474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
18208474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
18218474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
18228474SJose.Borrego@Sun.COM 	}
18238474SJose.Borrego@Sun.COM 
18249343SAfshin.Ardakani@Sun.COM 	if (info2->shi2_comment == NULL)
18259343SAfshin.Ardakani@Sun.COM 		info2->shi2_comment = (uint8_t *)"";
18268474SJose.Borrego@Sun.COM 
18278474SJose.Borrego@Sun.COM 	/*
18288474SJose.Borrego@Sun.COM 	 * Derive the real path which will be stored in the
18298474SJose.Borrego@Sun.COM 	 * directory field of the smb_share_t structure
18308474SJose.Borrego@Sun.COM 	 * from the path field in this RPC request.
18318474SJose.Borrego@Sun.COM 	 */
18328474SJose.Borrego@Sun.COM 	parm_stat = smb_shr_get_realpath((const char *)info2->shi2_path,
18338474SJose.Borrego@Sun.COM 	    realpath, MAXPATHLEN);
18348474SJose.Borrego@Sun.COM 
18358474SJose.Borrego@Sun.COM 	if (parm_stat != NERR_Success) {
18368474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareAdd));
18378474SJose.Borrego@Sun.COM 		param->status = parm_stat;
18388474SJose.Borrego@Sun.COM 		param->parm_err
18398474SJose.Borrego@Sun.COM 		    = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
18408474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
18418474SJose.Borrego@Sun.COM 	}
18428474SJose.Borrego@Sun.COM 
18438474SJose.Borrego@Sun.COM 	param->status = srvsvc_sa_add((char *)info2->shi2_netname, realpath,
18449343SAfshin.Ardakani@Sun.COM 	    (char *)info2->shi2_comment);
18458474SJose.Borrego@Sun.COM 	if (param->status == NERR_Success) {
1846*9832Samw@Sun.COM 		status = smb_shr_get((char *)info2->shi2_netname, &si);
1847*9832Samw@Sun.COM 
1848*9832Samw@Sun.COM 		if ((sdbuf != NULL) && (status == NERR_Success))
1849*9832Samw@Sun.COM 			(void) srvsvc_sd_set(&si, sdbuf);
18508474SJose.Borrego@Sun.COM 	}
18518474SJose.Borrego@Sun.COM 	param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
18528474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
18538474SJose.Borrego@Sun.COM }
18548474SJose.Borrego@Sun.COM 
18558474SJose.Borrego@Sun.COM /*
18568474SJose.Borrego@Sun.COM  * srvsvc_estimate_objcnt
18578474SJose.Borrego@Sun.COM  *
18588474SJose.Borrego@Sun.COM  * Estimate the number of objects that will fit in prefmaxlen.
18598474SJose.Borrego@Sun.COM  */
18608474SJose.Borrego@Sun.COM static uint32_t
18618474SJose.Borrego@Sun.COM srvsvc_estimate_objcnt(uint32_t prefmaxlen, uint32_t n_obj, uint32_t obj_size)
18628474SJose.Borrego@Sun.COM {
18638474SJose.Borrego@Sun.COM 	DWORD max_cnt;
18648474SJose.Borrego@Sun.COM 
18658474SJose.Borrego@Sun.COM 	if (obj_size == 0)
18668474SJose.Borrego@Sun.COM 		return (0);
18678474SJose.Borrego@Sun.COM 
18688474SJose.Borrego@Sun.COM 	if ((max_cnt = (prefmaxlen / obj_size)) == 0)
18698474SJose.Borrego@Sun.COM 		return (0);
18708474SJose.Borrego@Sun.COM 
18718474SJose.Borrego@Sun.COM 	if (n_obj > max_cnt)
18728474SJose.Borrego@Sun.COM 		n_obj = max_cnt;
18738474SJose.Borrego@Sun.COM 
18748474SJose.Borrego@Sun.COM 	return (n_obj);
18758474SJose.Borrego@Sun.COM }
18768474SJose.Borrego@Sun.COM 
18778474SJose.Borrego@Sun.COM /*
18788474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareEnum
18798474SJose.Borrego@Sun.COM  *
18808474SJose.Borrego@Sun.COM  * Enumerate all shares (see also NetShareEnumSticky).
18818474SJose.Borrego@Sun.COM  *
18828474SJose.Borrego@Sun.COM  * Request for various levels of information about our shares.
18838474SJose.Borrego@Sun.COM  * Level 0: share names.
18848474SJose.Borrego@Sun.COM  * Level 1: share name, share type and comment field.
18858474SJose.Borrego@Sun.COM  * Level 2: everything that we know about the shares.
18868474SJose.Borrego@Sun.COM  * Level 501: level 1 + flags (flags must be zero).
18878474SJose.Borrego@Sun.COM  * Level 502: level 2 + security descriptor.
18888474SJose.Borrego@Sun.COM  */
18898474SJose.Borrego@Sun.COM static int
18908474SJose.Borrego@Sun.COM srvsvc_s_NetShareEnum(void *arg, ndr_xa_t *mxa)
18918474SJose.Borrego@Sun.COM {
18928474SJose.Borrego@Sun.COM 	struct mslm_NetShareEnum *param = arg;
18938474SJose.Borrego@Sun.COM 	struct mslm_infonres *infonres;
18948474SJose.Borrego@Sun.COM 	srvsvc_enum_t se;
18958474SJose.Borrego@Sun.COM 	DWORD status;
18968474SJose.Borrego@Sun.COM 
18978474SJose.Borrego@Sun.COM 	infonres = NDR_NEW(mxa, struct mslm_infonres);
18988474SJose.Borrego@Sun.COM 	if (infonres == NULL) {
18998474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
19008474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
19018474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
19028474SJose.Borrego@Sun.COM 	}
19038474SJose.Borrego@Sun.COM 
19048474SJose.Borrego@Sun.COM 	infonres->entriesread = 0;
19058474SJose.Borrego@Sun.COM 	infonres->entries = NULL;
19068474SJose.Borrego@Sun.COM 	param->result.level = param->level;
19078474SJose.Borrego@Sun.COM 	param->result.bufptr.p = infonres;
19088474SJose.Borrego@Sun.COM 
19098474SJose.Borrego@Sun.COM 	bzero(&se, sizeof (srvsvc_enum_t));
19108474SJose.Borrego@Sun.COM 	se.se_level = param->level;
19118474SJose.Borrego@Sun.COM 	se.se_n_total = smb_shr_count();
19128474SJose.Borrego@Sun.COM 
19138474SJose.Borrego@Sun.COM 	if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN ||
19148474SJose.Borrego@Sun.COM 	    param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN)
19158474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
19168474SJose.Borrego@Sun.COM 	else
19178474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = param->prefmaxlen;
19188474SJose.Borrego@Sun.COM 
19198474SJose.Borrego@Sun.COM 	if (param->resume_handle) {
19208474SJose.Borrego@Sun.COM 		se.se_resume_handle = *param->resume_handle;
19218474SJose.Borrego@Sun.COM 		se.se_n_skip = se.se_resume_handle;
19228474SJose.Borrego@Sun.COM 	}
19238474SJose.Borrego@Sun.COM 
19248474SJose.Borrego@Sun.COM 	switch (param->level) {
19258474SJose.Borrego@Sun.COM 	case 0:
19268474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 0);
19278474SJose.Borrego@Sun.COM 		break;
19288474SJose.Borrego@Sun.COM 
19298474SJose.Borrego@Sun.COM 	case 1:
19308474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 0);
19318474SJose.Borrego@Sun.COM 		break;
19328474SJose.Borrego@Sun.COM 
19338474SJose.Borrego@Sun.COM 	case 2:
19348474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 0);
19358474SJose.Borrego@Sun.COM 		break;
19368474SJose.Borrego@Sun.COM 
19378474SJose.Borrego@Sun.COM 	case 501:
19388474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel501(mxa, infonres, &se, 0);
19398474SJose.Borrego@Sun.COM 		break;
19408474SJose.Borrego@Sun.COM 
19418474SJose.Borrego@Sun.COM 	case 502:
19428474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 0);
19438474SJose.Borrego@Sun.COM 		break;
19448474SJose.Borrego@Sun.COM 
19458474SJose.Borrego@Sun.COM 	default:
1946*9832Samw@Sun.COM 		status = ERROR_INVALID_LEVEL;
19478474SJose.Borrego@Sun.COM 		break;
19488474SJose.Borrego@Sun.COM 	}
19498474SJose.Borrego@Sun.COM 
19508474SJose.Borrego@Sun.COM 	if (status != 0) {
19518474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
19528474SJose.Borrego@Sun.COM 		param->status = status;
19538474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
19548474SJose.Borrego@Sun.COM 	}
19558474SJose.Borrego@Sun.COM 
19568474SJose.Borrego@Sun.COM 	if (se.se_n_enum == 0) {
19578474SJose.Borrego@Sun.COM 		if (param->resume_handle)
19588474SJose.Borrego@Sun.COM 			*param->resume_handle = 0;
19598474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
19608474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
19618474SJose.Borrego@Sun.COM 	}
19628474SJose.Borrego@Sun.COM 
19638474SJose.Borrego@Sun.COM 	if (param->resume_handle &&
19648474SJose.Borrego@Sun.COM 	    param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) {
19658474SJose.Borrego@Sun.COM 		if (se.se_resume_handle < se.se_n_total) {
19668474SJose.Borrego@Sun.COM 			*param->resume_handle = se.se_resume_handle;
19678474SJose.Borrego@Sun.COM 			status = ERROR_MORE_DATA;
19688474SJose.Borrego@Sun.COM 		} else {
19698474SJose.Borrego@Sun.COM 			*param->resume_handle = 0;
19708474SJose.Borrego@Sun.COM 		}
19718474SJose.Borrego@Sun.COM 	}
19728474SJose.Borrego@Sun.COM 
19738474SJose.Borrego@Sun.COM 	param->totalentries = se.se_n_total;
19748474SJose.Borrego@Sun.COM 	param->status = status;
19758474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
19768474SJose.Borrego@Sun.COM }
19778474SJose.Borrego@Sun.COM 
19788474SJose.Borrego@Sun.COM /*
19798474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareEnumSticky
19808474SJose.Borrego@Sun.COM  *
19818474SJose.Borrego@Sun.COM  * Enumerate sticky shares: all shares except those marked STYPE_SPECIAL.
19828474SJose.Borrego@Sun.COM  * Except for excluding STYPE_SPECIAL shares, NetShareEnumSticky is the
19838474SJose.Borrego@Sun.COM  * same as NetShareEnum.
19848474SJose.Borrego@Sun.COM  *
19858474SJose.Borrego@Sun.COM  * Request for various levels of information about our shares.
19868474SJose.Borrego@Sun.COM  * Level 0: share names.
19878474SJose.Borrego@Sun.COM  * Level 1: share name, share type and comment field.
19888474SJose.Borrego@Sun.COM  * Level 2: everything that we know about the shares.
19898474SJose.Borrego@Sun.COM  * Level 501: not valid for this request.
19908474SJose.Borrego@Sun.COM  * Level 502: level 2 + security descriptor.
19918474SJose.Borrego@Sun.COM  *
19928474SJose.Borrego@Sun.COM  * We set n_skip to resume_handle, which is used to find the appropriate
19938474SJose.Borrego@Sun.COM  * place to resume.  The resume_handle is similar to the readdir cookie.
19948474SJose.Borrego@Sun.COM  */
19958474SJose.Borrego@Sun.COM static int
19968474SJose.Borrego@Sun.COM srvsvc_s_NetShareEnumSticky(void *arg, ndr_xa_t *mxa)
19978474SJose.Borrego@Sun.COM {
19988474SJose.Borrego@Sun.COM 	struct mslm_NetShareEnum *param = arg;
19998474SJose.Borrego@Sun.COM 	struct mslm_infonres *infonres;
20008474SJose.Borrego@Sun.COM 	srvsvc_enum_t se;
20018474SJose.Borrego@Sun.COM 	DWORD status;
20028474SJose.Borrego@Sun.COM 
20038474SJose.Borrego@Sun.COM 	infonres = NDR_NEW(mxa, struct mslm_infonres);
20048474SJose.Borrego@Sun.COM 	if (infonres == NULL) {
20058474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
20068474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
20078474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
20088474SJose.Borrego@Sun.COM 	}
20098474SJose.Borrego@Sun.COM 
20108474SJose.Borrego@Sun.COM 	infonres->entriesread = 0;
20118474SJose.Borrego@Sun.COM 	infonres->entries = NULL;
20128474SJose.Borrego@Sun.COM 	param->result.level = param->level;
20138474SJose.Borrego@Sun.COM 	param->result.bufptr.p = infonres;
20148474SJose.Borrego@Sun.COM 
20158474SJose.Borrego@Sun.COM 	bzero(&se, sizeof (srvsvc_enum_t));
20168474SJose.Borrego@Sun.COM 	se.se_level = param->level;
20178474SJose.Borrego@Sun.COM 	se.se_n_total = smb_shr_count();
20188474SJose.Borrego@Sun.COM 
20198474SJose.Borrego@Sun.COM 	if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN ||
20208474SJose.Borrego@Sun.COM 	    param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN)
20218474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
20228474SJose.Borrego@Sun.COM 	else
20238474SJose.Borrego@Sun.COM 		se.se_prefmaxlen = param->prefmaxlen;
20248474SJose.Borrego@Sun.COM 
20258474SJose.Borrego@Sun.COM 	if (param->resume_handle) {
20268474SJose.Borrego@Sun.COM 		se.se_resume_handle = *param->resume_handle;
20278474SJose.Borrego@Sun.COM 		se.se_n_skip = se.se_resume_handle;
20288474SJose.Borrego@Sun.COM 	}
20298474SJose.Borrego@Sun.COM 
20308474SJose.Borrego@Sun.COM 	switch (param->level) {
20318474SJose.Borrego@Sun.COM 	case 0:
20328474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 1);
20338474SJose.Borrego@Sun.COM 		break;
20348474SJose.Borrego@Sun.COM 
20358474SJose.Borrego@Sun.COM 	case 1:
20368474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 1);
20378474SJose.Borrego@Sun.COM 		break;
20388474SJose.Borrego@Sun.COM 
20398474SJose.Borrego@Sun.COM 	case 2:
20408474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 1);
20418474SJose.Borrego@Sun.COM 		break;
20428474SJose.Borrego@Sun.COM 
20438474SJose.Borrego@Sun.COM 	case 502:
20448474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 1);
20458474SJose.Borrego@Sun.COM 		break;
20468474SJose.Borrego@Sun.COM 
2047*9832Samw@Sun.COM 	case 501:
20488474SJose.Borrego@Sun.COM 	default:
20498474SJose.Borrego@Sun.COM 		status = ERROR_INVALID_LEVEL;
20508474SJose.Borrego@Sun.COM 		break;
20518474SJose.Borrego@Sun.COM 	}
20528474SJose.Borrego@Sun.COM 
20538474SJose.Borrego@Sun.COM 	if (status != ERROR_SUCCESS) {
20548474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct mslm_NetShareEnum));
20558474SJose.Borrego@Sun.COM 		param->status = status;
20568474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
20578474SJose.Borrego@Sun.COM 	}
20588474SJose.Borrego@Sun.COM 
20598474SJose.Borrego@Sun.COM 	if (se.se_n_enum == 0) {
20608474SJose.Borrego@Sun.COM 		if (param->resume_handle)
20618474SJose.Borrego@Sun.COM 			*param->resume_handle = 0;
20628474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
20638474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
20648474SJose.Borrego@Sun.COM 	}
20658474SJose.Borrego@Sun.COM 
20668474SJose.Borrego@Sun.COM 	if (param->resume_handle &&
20678474SJose.Borrego@Sun.COM 	    param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) {
20688474SJose.Borrego@Sun.COM 		if (se.se_resume_handle < se.se_n_total) {
20698474SJose.Borrego@Sun.COM 			*param->resume_handle = se.se_resume_handle;
20708474SJose.Borrego@Sun.COM 			status = ERROR_MORE_DATA;
20718474SJose.Borrego@Sun.COM 		} else {
20728474SJose.Borrego@Sun.COM 			*param->resume_handle = 0;
20738474SJose.Borrego@Sun.COM 		}
20748474SJose.Borrego@Sun.COM 	}
20758474SJose.Borrego@Sun.COM 
20768474SJose.Borrego@Sun.COM 	param->totalentries = se.se_n_total;
20778474SJose.Borrego@Sun.COM 	param->status = status;
20788474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
20798474SJose.Borrego@Sun.COM }
20808474SJose.Borrego@Sun.COM 
20818474SJose.Borrego@Sun.COM /*
20828474SJose.Borrego@Sun.COM  * NetShareEnum Level 0
20838474SJose.Borrego@Sun.COM  */
20848474SJose.Borrego@Sun.COM static DWORD
20858474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel0(ndr_xa_t *mxa,
20868474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
20878474SJose.Borrego@Sun.COM {
20889343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_0 *info0;
20898474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
20908474SJose.Borrego@Sun.COM 	smb_share_t *si;
20918474SJose.Borrego@Sun.COM 	DWORD status;
20928474SJose.Borrego@Sun.COM 
20938474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
20949343SAfshin.Ardakani@Sun.COM 	    se->se_n_total, sizeof (struct mslm_NetShareInfo_0) + MAXNAMELEN);
20958474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
20968474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
20978474SJose.Borrego@Sun.COM 
20989343SAfshin.Ardakani@Sun.COM 	info0 = NDR_NEWN(mxa, struct mslm_NetShareInfo_0, se->se_n_enum);
20998474SJose.Borrego@Sun.COM 	if (info0 == NULL)
21008474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
21018474SJose.Borrego@Sun.COM 
21028474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
21038474SJose.Borrego@Sun.COM 
21048474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
21058474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
21068474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
21078474SJose.Borrego@Sun.COM 			--se->se_n_skip;
21088474SJose.Borrego@Sun.COM 			continue;
21098474SJose.Borrego@Sun.COM 		}
21108474SJose.Borrego@Sun.COM 
21118474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
21128474SJose.Borrego@Sun.COM 
21138474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
21148474SJose.Borrego@Sun.COM 			continue;
21158474SJose.Borrego@Sun.COM 
21168474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
21178474SJose.Borrego@Sun.COM 			continue;
21188474SJose.Borrego@Sun.COM 
21198474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
21208474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
21218474SJose.Borrego@Sun.COM 			break;
21228474SJose.Borrego@Sun.COM 		}
21238474SJose.Borrego@Sun.COM 
21248474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info0);
21258474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
21268474SJose.Borrego@Sun.COM 			break;
21278474SJose.Borrego@Sun.COM 
21288474SJose.Borrego@Sun.COM 		++se->se_n_read;
21298474SJose.Borrego@Sun.COM 	}
21308474SJose.Borrego@Sun.COM 
21318474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
21328474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info0))
21338474SJose.Borrego@Sun.COM 			++se->se_n_read;
21348474SJose.Borrego@Sun.COM 	}
21358474SJose.Borrego@Sun.COM 
21368474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
21378474SJose.Borrego@Sun.COM 	infonres->entries = info0;
21388474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
21398474SJose.Borrego@Sun.COM }
21408474SJose.Borrego@Sun.COM 
21418474SJose.Borrego@Sun.COM /*
21428474SJose.Borrego@Sun.COM  * NetShareEnum Level 1
21438474SJose.Borrego@Sun.COM  */
21448474SJose.Borrego@Sun.COM static DWORD
21458474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel1(ndr_xa_t *mxa,
21468474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
21478474SJose.Borrego@Sun.COM {
21489343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1 *info1;
21498474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
21508474SJose.Borrego@Sun.COM 	smb_share_t *si;
21518474SJose.Borrego@Sun.COM 	DWORD status;
21528474SJose.Borrego@Sun.COM 
21538474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
21549343SAfshin.Ardakani@Sun.COM 	    se->se_n_total, sizeof (struct mslm_NetShareInfo_1) + MAXNAMELEN);
21558474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
21568474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
21578474SJose.Borrego@Sun.COM 
21589343SAfshin.Ardakani@Sun.COM 	info1 = NDR_NEWN(mxa, struct mslm_NetShareInfo_1, se->se_n_enum);
21598474SJose.Borrego@Sun.COM 	if (info1 == NULL)
21608474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
21618474SJose.Borrego@Sun.COM 
21628474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
21638474SJose.Borrego@Sun.COM 
21648474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
21658474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
21668474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
21678474SJose.Borrego@Sun.COM 			--se->se_n_skip;
21688474SJose.Borrego@Sun.COM 			continue;
21698474SJose.Borrego@Sun.COM 		}
21708474SJose.Borrego@Sun.COM 
21718474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
21728474SJose.Borrego@Sun.COM 
21738474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
21748474SJose.Borrego@Sun.COM 			continue;
21758474SJose.Borrego@Sun.COM 
21768474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
21778474SJose.Borrego@Sun.COM 			continue;
21788474SJose.Borrego@Sun.COM 
21798474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
21808474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
21818474SJose.Borrego@Sun.COM 			break;
21828474SJose.Borrego@Sun.COM 		}
21838474SJose.Borrego@Sun.COM 
21848474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info1);
21858474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
21868474SJose.Borrego@Sun.COM 			break;
21878474SJose.Borrego@Sun.COM 
21888474SJose.Borrego@Sun.COM 		++se->se_n_read;
21898474SJose.Borrego@Sun.COM 	}
21908474SJose.Borrego@Sun.COM 
21918474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
21928474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info1))
21938474SJose.Borrego@Sun.COM 			++se->se_n_read;
21948474SJose.Borrego@Sun.COM 	}
21958474SJose.Borrego@Sun.COM 
21968474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
21978474SJose.Borrego@Sun.COM 	infonres->entries = info1;
21988474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
21998474SJose.Borrego@Sun.COM }
22008474SJose.Borrego@Sun.COM 
22018474SJose.Borrego@Sun.COM /*
22028474SJose.Borrego@Sun.COM  * NetShareEnum Level 2
22038474SJose.Borrego@Sun.COM  */
22048474SJose.Borrego@Sun.COM static DWORD
22058474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel2(ndr_xa_t *mxa,
22068474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
22078474SJose.Borrego@Sun.COM {
22089343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
22098474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
22108474SJose.Borrego@Sun.COM 	smb_share_t *si;
22118474SJose.Borrego@Sun.COM 	DWORD status;
22128474SJose.Borrego@Sun.COM 
22138474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
22149343SAfshin.Ardakani@Sun.COM 	    se->se_n_total, sizeof (struct mslm_NetShareInfo_2) + MAXNAMELEN);
22158474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
22168474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
22178474SJose.Borrego@Sun.COM 
22189343SAfshin.Ardakani@Sun.COM 	info2 = NDR_NEWN(mxa, struct mslm_NetShareInfo_2, se->se_n_enum);
22198474SJose.Borrego@Sun.COM 	if (info2 == NULL)
22208474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
22218474SJose.Borrego@Sun.COM 
22228474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
22238474SJose.Borrego@Sun.COM 
22248474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
22258474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
22268474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
22278474SJose.Borrego@Sun.COM 			--se->se_n_skip;
22288474SJose.Borrego@Sun.COM 			continue;
22298474SJose.Borrego@Sun.COM 		}
22308474SJose.Borrego@Sun.COM 
22318474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
22328474SJose.Borrego@Sun.COM 
22338474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
22348474SJose.Borrego@Sun.COM 			continue;
22358474SJose.Borrego@Sun.COM 
22368474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
22378474SJose.Borrego@Sun.COM 			continue;
22388474SJose.Borrego@Sun.COM 
22398474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
22408474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
22418474SJose.Borrego@Sun.COM 			break;
22428474SJose.Borrego@Sun.COM 		}
22438474SJose.Borrego@Sun.COM 
22448474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info2);
22458474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
22468474SJose.Borrego@Sun.COM 			break;
22478474SJose.Borrego@Sun.COM 
22488474SJose.Borrego@Sun.COM 		++se->se_n_read;
22498474SJose.Borrego@Sun.COM 	}
22508474SJose.Borrego@Sun.COM 
22518474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
22528474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info2))
22538474SJose.Borrego@Sun.COM 			++se->se_n_read;
22548474SJose.Borrego@Sun.COM 	}
22558474SJose.Borrego@Sun.COM 
22568474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
22578474SJose.Borrego@Sun.COM 	infonres->entries = info2;
22588474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
22598474SJose.Borrego@Sun.COM }
22608474SJose.Borrego@Sun.COM 
22618474SJose.Borrego@Sun.COM /*
22628474SJose.Borrego@Sun.COM  * NetShareEnum Level 501
22638474SJose.Borrego@Sun.COM  */
22648474SJose.Borrego@Sun.COM static DWORD
22658474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel501(ndr_xa_t *mxa,
22668474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
22678474SJose.Borrego@Sun.COM {
22689343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_501 *info501;
22698474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
22708474SJose.Borrego@Sun.COM 	smb_share_t *si;
22718474SJose.Borrego@Sun.COM 	DWORD status;
22728474SJose.Borrego@Sun.COM 
22738474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
22749343SAfshin.Ardakani@Sun.COM 	    se->se_n_total, sizeof (struct mslm_NetShareInfo_501) + MAXNAMELEN);
22758474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
22768474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
22778474SJose.Borrego@Sun.COM 
22789343SAfshin.Ardakani@Sun.COM 	info501 = NDR_NEWN(mxa, struct mslm_NetShareInfo_501,
22798474SJose.Borrego@Sun.COM 	    se->se_n_enum);
22808474SJose.Borrego@Sun.COM 	if (info501 == NULL)
22818474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
22828474SJose.Borrego@Sun.COM 
22838474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
22848474SJose.Borrego@Sun.COM 
22858474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
22868474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != 0) {
22878474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
22888474SJose.Borrego@Sun.COM 			--se->se_n_skip;
22898474SJose.Borrego@Sun.COM 			continue;
22908474SJose.Borrego@Sun.COM 		}
22918474SJose.Borrego@Sun.COM 
22928474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
22938474SJose.Borrego@Sun.COM 
22948474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
22958474SJose.Borrego@Sun.COM 			continue;
22968474SJose.Borrego@Sun.COM 
22978474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
22988474SJose.Borrego@Sun.COM 			continue;
22998474SJose.Borrego@Sun.COM 
23008474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
23018474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
23028474SJose.Borrego@Sun.COM 			break;
23038474SJose.Borrego@Sun.COM 		}
23048474SJose.Borrego@Sun.COM 
23058474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info501);
23068474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
23078474SJose.Borrego@Sun.COM 			break;
23088474SJose.Borrego@Sun.COM 
23098474SJose.Borrego@Sun.COM 		++se->se_n_read;
23108474SJose.Borrego@Sun.COM 	}
23118474SJose.Borrego@Sun.COM 
23128474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
23138474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info501))
23148474SJose.Borrego@Sun.COM 			++se->se_n_read;
23158474SJose.Borrego@Sun.COM 	}
23168474SJose.Borrego@Sun.COM 
23178474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
23188474SJose.Borrego@Sun.COM 	infonres->entries = info501;
23198474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
23208474SJose.Borrego@Sun.COM }
23218474SJose.Borrego@Sun.COM 
23228474SJose.Borrego@Sun.COM /*
23238474SJose.Borrego@Sun.COM  * NetShareEnum Level 502
23248474SJose.Borrego@Sun.COM  */
23258474SJose.Borrego@Sun.COM static DWORD
23268474SJose.Borrego@Sun.COM mlsvc_NetShareEnumLevel502(ndr_xa_t *mxa,
23278474SJose.Borrego@Sun.COM     struct mslm_infonres *infonres, srvsvc_enum_t *se, int sticky)
23288474SJose.Borrego@Sun.COM {
23299343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
23308474SJose.Borrego@Sun.COM 	smb_shriter_t iterator;
23318474SJose.Borrego@Sun.COM 	smb_share_t *si;
23328474SJose.Borrego@Sun.COM 	DWORD status;
23338474SJose.Borrego@Sun.COM 
23348474SJose.Borrego@Sun.COM 	se->se_n_enum = srvsvc_estimate_objcnt(se->se_prefmaxlen,
23359343SAfshin.Ardakani@Sun.COM 	    se->se_n_total, sizeof (struct mslm_NetShareInfo_502) + MAXNAMELEN);
23368474SJose.Borrego@Sun.COM 	if (se->se_n_enum == 0)
23378474SJose.Borrego@Sun.COM 		return (ERROR_SUCCESS);
23388474SJose.Borrego@Sun.COM 
23399343SAfshin.Ardakani@Sun.COM 	info502 = NDR_NEWN(mxa, struct mslm_NetShareInfo_502,
23408474SJose.Borrego@Sun.COM 	    se->se_n_enum);
23418474SJose.Borrego@Sun.COM 	if (info502 == NULL)
23428474SJose.Borrego@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
23438474SJose.Borrego@Sun.COM 
23448474SJose.Borrego@Sun.COM 	smb_shr_iterinit(&iterator);
23458474SJose.Borrego@Sun.COM 
23468474SJose.Borrego@Sun.COM 	se->se_n_read = 0;
23478474SJose.Borrego@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
23488474SJose.Borrego@Sun.COM 		if (se->se_n_skip > 0) {
23498474SJose.Borrego@Sun.COM 			--se->se_n_skip;
23508474SJose.Borrego@Sun.COM 			continue;
23518474SJose.Borrego@Sun.COM 		}
23528474SJose.Borrego@Sun.COM 
23538474SJose.Borrego@Sun.COM 		++se->se_resume_handle;
23548474SJose.Borrego@Sun.COM 
23558474SJose.Borrego@Sun.COM 		if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
23568474SJose.Borrego@Sun.COM 			continue;
23578474SJose.Borrego@Sun.COM 
23588474SJose.Borrego@Sun.COM 		if (si->shr_flags & SMB_SHRF_AUTOHOME)
23598474SJose.Borrego@Sun.COM 			continue;
23608474SJose.Borrego@Sun.COM 
23618474SJose.Borrego@Sun.COM 		if (se->se_n_read >= se->se_n_enum) {
23628474SJose.Borrego@Sun.COM 			se->se_n_read = se->se_n_enum;
23638474SJose.Borrego@Sun.COM 			break;
23648474SJose.Borrego@Sun.COM 		}
23658474SJose.Borrego@Sun.COM 
23668474SJose.Borrego@Sun.COM 		status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info502);
23678474SJose.Borrego@Sun.COM 		if (status != ERROR_SUCCESS)
23688474SJose.Borrego@Sun.COM 			break;
23698474SJose.Borrego@Sun.COM 
23708474SJose.Borrego@Sun.COM 		++se->se_n_read;
23718474SJose.Borrego@Sun.COM 	}
23728474SJose.Borrego@Sun.COM 
23738474SJose.Borrego@Sun.COM 	if (se->se_n_read < se->se_n_enum) {
23748474SJose.Borrego@Sun.COM 		if (srvsvc_add_autohome(mxa, se, (void *)info502))
23758474SJose.Borrego@Sun.COM 			++se->se_n_read;
23768474SJose.Borrego@Sun.COM 	}
23778474SJose.Borrego@Sun.COM 
23788474SJose.Borrego@Sun.COM 	infonres->entriesread = se->se_n_read;
23798474SJose.Borrego@Sun.COM 	infonres->entries = info502;
23808474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
23818474SJose.Borrego@Sun.COM }
23828474SJose.Borrego@Sun.COM 
23838474SJose.Borrego@Sun.COM /*
23848474SJose.Borrego@Sun.COM  * mlsvc_NetShareEnumCommon
23858474SJose.Borrego@Sun.COM  *
23868474SJose.Borrego@Sun.COM  * Build the levels 0, 1, 2, 501 and 502 share information. This function
23878474SJose.Borrego@Sun.COM  * is called by the various NetShareEnum levels for each share. If
23888474SJose.Borrego@Sun.COM  * we cannot build the share data for some reason, we return an error
23898474SJose.Borrego@Sun.COM  * but the actual value of the error is not important to the caller.
23908474SJose.Borrego@Sun.COM  * The caller just needs to know not to include this info in the RPC
23918474SJose.Borrego@Sun.COM  * response.
23928474SJose.Borrego@Sun.COM  *
23938474SJose.Borrego@Sun.COM  * Returns:
23948474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS
23958474SJose.Borrego@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
23968474SJose.Borrego@Sun.COM  *	ERROR_INVALID_LEVEL
23978474SJose.Borrego@Sun.COM  */
23988474SJose.Borrego@Sun.COM static DWORD
23998474SJose.Borrego@Sun.COM mlsvc_NetShareEnumCommon(ndr_xa_t *mxa, srvsvc_enum_t *se,
24008474SJose.Borrego@Sun.COM     smb_share_t *si, void *infop)
24018474SJose.Borrego@Sun.COM {
24029343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_0 *info0;
24039343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_1 *info1;
24049343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_2 *info2;
24059343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_501 *info501;
24069343SAfshin.Ardakani@Sun.COM 	struct mslm_NetShareInfo_502 *info502;
2407*9832Samw@Sun.COM 	srvsvc_sd_t sd;
2408*9832Samw@Sun.COM 	uint8_t *netname;
2409*9832Samw@Sun.COM 	uint8_t *comment;
2410*9832Samw@Sun.COM 	uint8_t *passwd;
2411*9832Samw@Sun.COM 	uint8_t *path;
24128474SJose.Borrego@Sun.COM 	int i = se->se_n_read;
24138474SJose.Borrego@Sun.COM 
2414*9832Samw@Sun.COM 	netname = (uint8_t *)NDR_STRDUP(mxa, si->shr_name);
2415*9832Samw@Sun.COM 	comment = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt);
2416*9832Samw@Sun.COM 	passwd = (uint8_t *)NDR_STRDUP(mxa, empty_string);
2417*9832Samw@Sun.COM 	path = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path);
2418*9832Samw@Sun.COM 
2419*9832Samw@Sun.COM 	if (!netname || !comment || !passwd || !path)
2420*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
2421*9832Samw@Sun.COM 
24228474SJose.Borrego@Sun.COM 	switch (se->se_level) {
24238474SJose.Borrego@Sun.COM 	case 0:
24249343SAfshin.Ardakani@Sun.COM 		info0 = (struct mslm_NetShareInfo_0 *)infop;
2425*9832Samw@Sun.COM 		info0[i].shi0_netname = netname;
24268474SJose.Borrego@Sun.COM 		break;
24278474SJose.Borrego@Sun.COM 
24288474SJose.Borrego@Sun.COM 	case 1:
24299343SAfshin.Ardakani@Sun.COM 		info1 = (struct mslm_NetShareInfo_1 *)infop;
2430*9832Samw@Sun.COM 		info1[i].shi1_netname = netname;
2431*9832Samw@Sun.COM 		info1[i].shi1_comment = comment;
24328474SJose.Borrego@Sun.COM 		info1[i].shi1_type = si->shr_type;
24338474SJose.Borrego@Sun.COM 		break;
24348474SJose.Borrego@Sun.COM 
24358474SJose.Borrego@Sun.COM 	case 2:
24369343SAfshin.Ardakani@Sun.COM 		info2 = (struct mslm_NetShareInfo_2 *)infop;
2437*9832Samw@Sun.COM 		info2[i].shi2_netname = netname;
2438*9832Samw@Sun.COM 		info2[i].shi2_comment = comment;
2439*9832Samw@Sun.COM 		info2[i].shi2_path = path;
24408474SJose.Borrego@Sun.COM 		info2[i].shi2_type = si->shr_type;
24418474SJose.Borrego@Sun.COM 		info2[i].shi2_permissions = 0;
24428474SJose.Borrego@Sun.COM 		info2[i].shi2_max_uses = SHI_USES_UNLIMITED;
24438474SJose.Borrego@Sun.COM 		info2[i].shi2_current_uses = 0;
2444*9832Samw@Sun.COM 		info2[i].shi2_passwd = passwd;
24458474SJose.Borrego@Sun.COM 		break;
24468474SJose.Borrego@Sun.COM 
24478474SJose.Borrego@Sun.COM 	case 501:
24489343SAfshin.Ardakani@Sun.COM 		info501 = (struct mslm_NetShareInfo_501 *)infop;
2449*9832Samw@Sun.COM 		info501[i].shi501_netname = netname;
2450*9832Samw@Sun.COM 		info501[i].shi501_comment = comment;
24518474SJose.Borrego@Sun.COM 		info501[i].shi501_type = si->shr_type;
24529343SAfshin.Ardakani@Sun.COM 		info501[i].shi501_reserved = 0;
24538474SJose.Borrego@Sun.COM 		break;
24548474SJose.Borrego@Sun.COM 
24558474SJose.Borrego@Sun.COM 	case 502:
24569343SAfshin.Ardakani@Sun.COM 		info502 = (struct mslm_NetShareInfo_502 *)infop;
2457*9832Samw@Sun.COM 		info502[i].shi502_netname = netname;
2458*9832Samw@Sun.COM 		info502[i].shi502_comment = comment;
2459*9832Samw@Sun.COM 		info502[i].shi502_path = path;
24608474SJose.Borrego@Sun.COM 		info502[i].shi502_type = si->shr_type;
24618474SJose.Borrego@Sun.COM 		info502[i].shi502_permissions = 0;
24628474SJose.Borrego@Sun.COM 		info502[i].shi502_max_uses = SHI_USES_UNLIMITED;
24638474SJose.Borrego@Sun.COM 		info502[i].shi502_current_uses = 0;
2464*9832Samw@Sun.COM 		info502[i].shi502_passwd = passwd;
2465*9832Samw@Sun.COM 
2466*9832Samw@Sun.COM 		if (srvsvc_share_getsd(mxa, si, &sd) == ERROR_SUCCESS) {
2467*9832Samw@Sun.COM 			info502[i].shi502_reserved = sd.sd_size;
2468*9832Samw@Sun.COM 			info502[i].shi502_security_descriptor = sd.sd_buf;
2469*9832Samw@Sun.COM 		} else {
2470*9832Samw@Sun.COM 			info502[i].shi502_reserved = 0;
2471*9832Samw@Sun.COM 			info502[i].shi502_security_descriptor = NULL;
2472*9832Samw@Sun.COM 		}
2473*9832Samw@Sun.COM 
24748474SJose.Borrego@Sun.COM 		break;
24758474SJose.Borrego@Sun.COM 
24768474SJose.Borrego@Sun.COM 	default:
24778474SJose.Borrego@Sun.COM 		return (ERROR_INVALID_LEVEL);
24788474SJose.Borrego@Sun.COM 	}
24798474SJose.Borrego@Sun.COM 
24808474SJose.Borrego@Sun.COM 	return (ERROR_SUCCESS);
24818474SJose.Borrego@Sun.COM }
24828474SJose.Borrego@Sun.COM 
24838474SJose.Borrego@Sun.COM /*
24848474SJose.Borrego@Sun.COM  * srvsvc_add_autohome
24858474SJose.Borrego@Sun.COM  *
24868474SJose.Borrego@Sun.COM  * Add the autohome share for the user. The share must not be a permanent
24878474SJose.Borrego@Sun.COM  * share to avoid duplicates.
24888474SJose.Borrego@Sun.COM  */
24898474SJose.Borrego@Sun.COM static boolean_t
24908474SJose.Borrego@Sun.COM srvsvc_add_autohome(ndr_xa_t *mxa, srvsvc_enum_t *se, void *infop)
24918474SJose.Borrego@Sun.COM {
24928474SJose.Borrego@Sun.COM 	smb_opipe_context_t *ctx = &mxa->pipe->np_ctx;
24938474SJose.Borrego@Sun.COM 	char *username = ctx->oc_account;
24948474SJose.Borrego@Sun.COM 	smb_share_t si;
24958474SJose.Borrego@Sun.COM 	DWORD status;
24968474SJose.Borrego@Sun.COM 
24978474SJose.Borrego@Sun.COM 	if (smb_shr_get(username, &si) != NERR_Success)
24988474SJose.Borrego@Sun.COM 		return (B_FALSE);
24998474SJose.Borrego@Sun.COM 
25008474SJose.Borrego@Sun.COM 	if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0)
25018474SJose.Borrego@Sun.COM 		return (B_FALSE);
25028474SJose.Borrego@Sun.COM 
25038474SJose.Borrego@Sun.COM 	status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop);
25048474SJose.Borrego@Sun.COM 	return (status == ERROR_SUCCESS);
25058474SJose.Borrego@Sun.COM }
25068474SJose.Borrego@Sun.COM 
25078474SJose.Borrego@Sun.COM /*
25088474SJose.Borrego@Sun.COM  * srvsvc_share_mkpath
25098474SJose.Borrego@Sun.COM  *
25108474SJose.Borrego@Sun.COM  * Create the share path required by the share enum calls. The path
25118474SJose.Borrego@Sun.COM  * is created in a heap buffer ready for use by the caller.
25128474SJose.Borrego@Sun.COM  *
25138474SJose.Borrego@Sun.COM  * Some Windows over-the-wire backup applications do not work unless a
25148474SJose.Borrego@Sun.COM  * drive letter is present in the share path.  We don't care about the
25158474SJose.Borrego@Sun.COM  * drive letter since the path is fully qualified with the volume name.
25168474SJose.Borrego@Sun.COM  *
25178474SJose.Borrego@Sun.COM  * Windows clients seem to be mostly okay with forward slashes in
25188474SJose.Borrego@Sun.COM  * share paths but they cannot handle one immediately after the drive
25198474SJose.Borrego@Sun.COM  * letter, i.e. B:/.  For consistency we convert all the slashes in
25208474SJose.Borrego@Sun.COM  * the path.
25218474SJose.Borrego@Sun.COM  *
25228474SJose.Borrego@Sun.COM  * Returns a pointer to a heap buffer containing the share path, which
25238474SJose.Borrego@Sun.COM  * could be a null pointer if the heap allocation fails.
25248474SJose.Borrego@Sun.COM  */
25258474SJose.Borrego@Sun.COM static char *
25268474SJose.Borrego@Sun.COM srvsvc_share_mkpath(ndr_xa_t *mxa, char *path)
25278474SJose.Borrego@Sun.COM {
25288474SJose.Borrego@Sun.COM 	char tmpbuf[MAXPATHLEN];
25298474SJose.Borrego@Sun.COM 	char *p;
25308474SJose.Borrego@Sun.COM 
25318474SJose.Borrego@Sun.COM 	if (strlen(path) == 0)
25328474SJose.Borrego@Sun.COM 		return (NDR_STRDUP(mxa, path));
25338474SJose.Borrego@Sun.COM 
25348474SJose.Borrego@Sun.COM 	/*
25358474SJose.Borrego@Sun.COM 	 * Strip the volume name from the path (/vol1/home -> /home).
25368474SJose.Borrego@Sun.COM 	 */
25378474SJose.Borrego@Sun.COM 	p = path;
25388474SJose.Borrego@Sun.COM 	p += strspn(p, "/");
25398474SJose.Borrego@Sun.COM 	p += strcspn(p, "/");
25408474SJose.Borrego@Sun.COM 	p += strspn(p, "/");
25418474SJose.Borrego@Sun.COM 	(void) snprintf(tmpbuf, MAXPATHLEN, "%c:/%s", 'B', p);
25428474SJose.Borrego@Sun.COM 	(void) strsubst(tmpbuf, '/', '\\');
25438474SJose.Borrego@Sun.COM 
25448474SJose.Borrego@Sun.COM 	return (NDR_STRDUP(mxa, tmpbuf));
25458474SJose.Borrego@Sun.COM }
25468474SJose.Borrego@Sun.COM 
2547*9832Samw@Sun.COM static int
2548*9832Samw@Sun.COM srvsvc_s_NetShareCheck(void *arg, ndr_xa_t *mxa)
2549*9832Samw@Sun.COM {
2550*9832Samw@Sun.COM 	struct mslm_NetShareCheck *param = arg;
2551*9832Samw@Sun.COM 	smb_shriter_t iterator;
2552*9832Samw@Sun.COM 	smb_share_t *si;
2553*9832Samw@Sun.COM 	char *path;
2554*9832Samw@Sun.COM 
2555*9832Samw@Sun.COM 	if (param->path == NULL) {
2556*9832Samw@Sun.COM 		param->stype = STYPE_DISKTREE;
2557*9832Samw@Sun.COM 		param->status = NERR_NetNameNotFound;
2558*9832Samw@Sun.COM 		return (NDR_DRC_OK);
2559*9832Samw@Sun.COM 	}
2560*9832Samw@Sun.COM 
2561*9832Samw@Sun.COM 	(void) strsubst((char *)param->path, '/', '\\');
2562*9832Samw@Sun.COM 
2563*9832Samw@Sun.COM 	smb_shr_iterinit(&iterator);
2564*9832Samw@Sun.COM 
2565*9832Samw@Sun.COM 	while ((si = smb_shr_iterate(&iterator)) != NULL) {
2566*9832Samw@Sun.COM 		path = srvsvc_share_mkpath(mxa, si->shr_path);
2567*9832Samw@Sun.COM 
2568*9832Samw@Sun.COM 		if (utf8_strcasecmp(path, (char *)param->path) == 0) {
2569*9832Samw@Sun.COM 			param->stype = (si->shr_type & STYPE_MASK);
2570*9832Samw@Sun.COM 			param->status = NERR_Success;
2571*9832Samw@Sun.COM 			return (NDR_DRC_OK);
2572*9832Samw@Sun.COM 		}
2573*9832Samw@Sun.COM 	}
2574*9832Samw@Sun.COM 
2575*9832Samw@Sun.COM 	param->stype = STYPE_DISKTREE;
2576*9832Samw@Sun.COM 	param->status = NERR_NetNameNotFound;
2577*9832Samw@Sun.COM 	return (NDR_DRC_OK);
2578*9832Samw@Sun.COM }
2579*9832Samw@Sun.COM 
25808474SJose.Borrego@Sun.COM /*
25818474SJose.Borrego@Sun.COM  * srvsvc_s_NetShareDel
25828474SJose.Borrego@Sun.COM  *
25838474SJose.Borrego@Sun.COM  * Delete a share. Only the administrator, or a member of the domain
25848474SJose.Borrego@Sun.COM  * administrators group, is allowed to delete shares.
25858474SJose.Borrego@Sun.COM  *
25868474SJose.Borrego@Sun.COM  * This interface is used by the rmtshare command from the NT resource
25878474SJose.Borrego@Sun.COM  * kit. Rmtshare allows a client to add or remove shares on a server
25888474SJose.Borrego@Sun.COM  * from the client's command line.
25898474SJose.Borrego@Sun.COM  *
25908474SJose.Borrego@Sun.COM  * Returns Win32 error codes.
25918474SJose.Borrego@Sun.COM  */
25928474SJose.Borrego@Sun.COM static int
25938474SJose.Borrego@Sun.COM srvsvc_s_NetShareDel(void *arg, ndr_xa_t *mxa)
25948474SJose.Borrego@Sun.COM {
25958474SJose.Borrego@Sun.COM 	struct mslm_NetShareDel *param = arg;
25968474SJose.Borrego@Sun.COM 
25978474SJose.Borrego@Sun.COM 	if (!ndr_is_poweruser(mxa) ||
25988474SJose.Borrego@Sun.COM 	    smb_shr_is_restricted((char *)param->netname)) {
25998474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
26008474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
26018474SJose.Borrego@Sun.COM 	}
26028474SJose.Borrego@Sun.COM 
26038474SJose.Borrego@Sun.COM 	param->status = srvsvc_sa_delete((char *)param->netname);
26048474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
26058474SJose.Borrego@Sun.COM }
26068474SJose.Borrego@Sun.COM 
26078474SJose.Borrego@Sun.COM /*
26088474SJose.Borrego@Sun.COM  * srvsvc_s_NetGetFileSecurity
26098474SJose.Borrego@Sun.COM  *
26108474SJose.Borrego@Sun.COM  * Get security descriptor of the requested file/folder
26118474SJose.Borrego@Sun.COM  *
26128474SJose.Borrego@Sun.COM  * Right now, just returns ERROR_ACCESS_DENIED, because we cannot
26138474SJose.Borrego@Sun.COM  * get the requested SD here in RPC code.
26148474SJose.Borrego@Sun.COM  */
26158474SJose.Borrego@Sun.COM /*ARGSUSED*/
26168474SJose.Borrego@Sun.COM static int
26178474SJose.Borrego@Sun.COM srvsvc_s_NetGetFileSecurity(void *arg, ndr_xa_t *mxa)
26188474SJose.Borrego@Sun.COM {
26198474SJose.Borrego@Sun.COM 	struct mslm_NetGetFileSecurity *param = arg;
26208474SJose.Borrego@Sun.COM 
26218474SJose.Borrego@Sun.COM 	param->length = 0;
26228474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
26238474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
26248474SJose.Borrego@Sun.COM }
26258474SJose.Borrego@Sun.COM 
26268474SJose.Borrego@Sun.COM /*
26278474SJose.Borrego@Sun.COM  * srvsvc_s_NetSetFileSecurity
26288474SJose.Borrego@Sun.COM  *
26298474SJose.Borrego@Sun.COM  * Set the given security descriptor for the requested file/folder
26308474SJose.Borrego@Sun.COM  *
26318474SJose.Borrego@Sun.COM  * Right now, just returns ERROR_ACCESS_DENIED, because we cannot
26328474SJose.Borrego@Sun.COM  * set the requested SD here in RPC code.
26338474SJose.Borrego@Sun.COM  */
26348474SJose.Borrego@Sun.COM /*ARGSUSED*/
26358474SJose.Borrego@Sun.COM static int
26368474SJose.Borrego@Sun.COM srvsvc_s_NetSetFileSecurity(void *arg, ndr_xa_t *mxa)
26378474SJose.Borrego@Sun.COM {
26388474SJose.Borrego@Sun.COM 	struct mslm_NetSetFileSecurity *param = arg;
26398474SJose.Borrego@Sun.COM 
26408474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
26418474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
26428474SJose.Borrego@Sun.COM }
26438474SJose.Borrego@Sun.COM 
26448474SJose.Borrego@Sun.COM /*
26458474SJose.Borrego@Sun.COM  * If the default "smb" share group exists then return the group
26468474SJose.Borrego@Sun.COM  * handle, otherwise create the group and return the handle.
26478474SJose.Borrego@Sun.COM  *
26488474SJose.Borrego@Sun.COM  * All shares created via the srvsvc will be added to the "smb"
26498474SJose.Borrego@Sun.COM  * group.
26508474SJose.Borrego@Sun.COM  */
26518474SJose.Borrego@Sun.COM static sa_group_t
26528474SJose.Borrego@Sun.COM srvsvc_sa_get_smbgrp(sa_handle_t handle)
26538474SJose.Borrego@Sun.COM {
26548474SJose.Borrego@Sun.COM 	sa_group_t group = NULL;
26558474SJose.Borrego@Sun.COM 	int err;
26568474SJose.Borrego@Sun.COM 
26578474SJose.Borrego@Sun.COM 	group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP);
26588474SJose.Borrego@Sun.COM 	if (group != NULL)
26598474SJose.Borrego@Sun.COM 		return (group);
26608474SJose.Borrego@Sun.COM 
26618474SJose.Borrego@Sun.COM 	group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err);
26628474SJose.Borrego@Sun.COM 	if (group == NULL)
26638474SJose.Borrego@Sun.COM 		return (NULL);
26648474SJose.Borrego@Sun.COM 
26658474SJose.Borrego@Sun.COM 	if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) {
26668474SJose.Borrego@Sun.COM 		(void) sa_remove_group(group);
26678474SJose.Borrego@Sun.COM 		group = NULL;
26688474SJose.Borrego@Sun.COM 	}
26698474SJose.Borrego@Sun.COM 
26708474SJose.Borrego@Sun.COM 	return (group);
26718474SJose.Borrego@Sun.COM }
26728474SJose.Borrego@Sun.COM 
26738474SJose.Borrego@Sun.COM /*
26748474SJose.Borrego@Sun.COM  * Stores the given share in sharemgr
26758474SJose.Borrego@Sun.COM  */
26768474SJose.Borrego@Sun.COM static uint32_t
26778474SJose.Borrego@Sun.COM srvsvc_sa_add(char *sharename, char *path, char *cmnt)
26788474SJose.Borrego@Sun.COM {
26798474SJose.Borrego@Sun.COM 	sa_handle_t handle;
26808474SJose.Borrego@Sun.COM 	sa_share_t share;
26818474SJose.Borrego@Sun.COM 	sa_group_t group;
26828474SJose.Borrego@Sun.COM 	sa_resource_t resource;
26838474SJose.Borrego@Sun.COM 	boolean_t new_share = B_FALSE;
26848474SJose.Borrego@Sun.COM 	uint32_t status = NERR_Success;
26858474SJose.Borrego@Sun.COM 	int err;
26868474SJose.Borrego@Sun.COM 
26878474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
26888474SJose.Borrego@Sun.COM 		return (NERR_InternalError);
26898474SJose.Borrego@Sun.COM 
26908474SJose.Borrego@Sun.COM 	share = sa_find_share(handle, path);
26918474SJose.Borrego@Sun.COM 	if (share == NULL) {
26928474SJose.Borrego@Sun.COM 		group = srvsvc_sa_get_smbgrp(handle);
26938474SJose.Borrego@Sun.COM 		if (group == NULL) {
26948474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
26958474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
26968474SJose.Borrego@Sun.COM 		}
26978474SJose.Borrego@Sun.COM 
26988474SJose.Borrego@Sun.COM 		share = sa_add_share(group, path, SA_SHARE_PERMANENT, &err);
26998474SJose.Borrego@Sun.COM 		if (share == NULL) {
27008474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
27018474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
27028474SJose.Borrego@Sun.COM 		}
27038474SJose.Borrego@Sun.COM 		new_share = B_TRUE;
27048474SJose.Borrego@Sun.COM 	}
27058474SJose.Borrego@Sun.COM 
27068474SJose.Borrego@Sun.COM 	resource = sa_get_share_resource(share, sharename);
27078474SJose.Borrego@Sun.COM 	if (resource == NULL) {
27088474SJose.Borrego@Sun.COM 		resource = sa_add_resource(share, sharename,
27098474SJose.Borrego@Sun.COM 		    SA_SHARE_PERMANENT, &err);
27108474SJose.Borrego@Sun.COM 		if (resource == NULL) {
27118474SJose.Borrego@Sun.COM 			if (new_share)
27128474SJose.Borrego@Sun.COM 				(void) sa_remove_share(share);
27138474SJose.Borrego@Sun.COM 			smb_shr_sa_exit();
27148474SJose.Borrego@Sun.COM 			return (NERR_InternalError);
27158474SJose.Borrego@Sun.COM 		}
27168474SJose.Borrego@Sun.COM 	}
27178474SJose.Borrego@Sun.COM 
27188474SJose.Borrego@Sun.COM 	(void) sa_set_resource_description(resource, cmnt);
27198474SJose.Borrego@Sun.COM 
27208474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
27218474SJose.Borrego@Sun.COM 	return (status);
27228474SJose.Borrego@Sun.COM }
27238474SJose.Borrego@Sun.COM 
27248474SJose.Borrego@Sun.COM /*
27258474SJose.Borrego@Sun.COM  * Removes the share from sharemgr
27268474SJose.Borrego@Sun.COM  */
27278474SJose.Borrego@Sun.COM static uint32_t
27288474SJose.Borrego@Sun.COM srvsvc_sa_delete(char *sharename)
27298474SJose.Borrego@Sun.COM {
27308474SJose.Borrego@Sun.COM 	sa_handle_t handle;
27318474SJose.Borrego@Sun.COM 	sa_resource_t resource;
27328474SJose.Borrego@Sun.COM 	uint32_t status;
27338474SJose.Borrego@Sun.COM 
27348474SJose.Borrego@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
27358474SJose.Borrego@Sun.COM 		return (NERR_InternalError);
27368474SJose.Borrego@Sun.COM 
27378474SJose.Borrego@Sun.COM 	status = NERR_InternalError;
27388474SJose.Borrego@Sun.COM 	if ((resource = sa_find_resource(handle, sharename)) != NULL) {
27398474SJose.Borrego@Sun.COM 		if (sa_remove_resource(resource) == SA_OK)
27408474SJose.Borrego@Sun.COM 			status = NERR_Success;
27418474SJose.Borrego@Sun.COM 	}
27428474SJose.Borrego@Sun.COM 
27438474SJose.Borrego@Sun.COM 	smb_shr_sa_exit();
27448474SJose.Borrego@Sun.COM 	return (status);
27458474SJose.Borrego@Sun.COM }
27468474SJose.Borrego@Sun.COM 
2747*9832Samw@Sun.COM /*
2748*9832Samw@Sun.COM  * Update the share information.
2749*9832Samw@Sun.COM  */
2750*9832Samw@Sun.COM static uint32_t
2751*9832Samw@Sun.COM srvsvc_sa_modify(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
2752*9832Samw@Sun.COM {
2753*9832Samw@Sun.COM 	sa_handle_t handle;
2754*9832Samw@Sun.COM 	sa_share_t share;
2755*9832Samw@Sun.COM 	sa_resource_t resource;
2756*9832Samw@Sun.COM 	boolean_t renamed = B_FALSE;
2757*9832Samw@Sun.COM 	uint32_t nerr = NERR_Success;
2758*9832Samw@Sun.COM 
2759*9832Samw@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
2760*9832Samw@Sun.COM 		return (NERR_InternalError);
2761*9832Samw@Sun.COM 
2762*9832Samw@Sun.COM 	if ((share = sa_find_share(handle, si->shr_path)) == NULL) {
2763*9832Samw@Sun.COM 		smb_shr_sa_exit();
2764*9832Samw@Sun.COM 		return (NERR_InternalError);
2765*9832Samw@Sun.COM 	}
2766*9832Samw@Sun.COM 
2767*9832Samw@Sun.COM 	if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) {
2768*9832Samw@Sun.COM 		smb_shr_sa_exit();
2769*9832Samw@Sun.COM 		return (NERR_InternalError);
2770*9832Samw@Sun.COM 	}
2771*9832Samw@Sun.COM 
2772*9832Samw@Sun.COM 	if (info->nss_netname != NULL && info->nss_netname[0] != '\0' &&
2773*9832Samw@Sun.COM 	    utf8_strcasecmp(info->nss_netname, si->shr_name) != 0) {
2774*9832Samw@Sun.COM 		(void) sa_set_resource_attr(resource, SHOPT_NAME,
2775*9832Samw@Sun.COM 		    info->nss_netname);
2776*9832Samw@Sun.COM 		renamed = B_TRUE;
2777*9832Samw@Sun.COM 	}
2778*9832Samw@Sun.COM 
2779*9832Samw@Sun.COM 	if ((info->nss_comment != NULL) &&
2780*9832Samw@Sun.COM 	    (strcmp(info->nss_comment, si->shr_cmnt) != 0)) {
2781*9832Samw@Sun.COM 		(void) sa_set_resource_description(resource, info->nss_comment);
2782*9832Samw@Sun.COM 		(void) strlcpy(si->shr_cmnt, info->nss_comment,
2783*9832Samw@Sun.COM 		    SMB_SHARE_CMNT_MAX);
2784*9832Samw@Sun.COM 	}
2785*9832Samw@Sun.COM 
2786*9832Samw@Sun.COM 	smb_shr_sa_exit();
2787*9832Samw@Sun.COM 
2788*9832Samw@Sun.COM 	if (renamed) {
2789*9832Samw@Sun.COM 		nerr = smb_shr_rename(si->shr_name, info->nss_netname);
2790*9832Samw@Sun.COM 		if (nerr != NERR_Success)
2791*9832Samw@Sun.COM 			return (nerr);
2792*9832Samw@Sun.COM 
2793*9832Samw@Sun.COM 		(void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN);
2794*9832Samw@Sun.COM 	}
2795*9832Samw@Sun.COM 
2796*9832Samw@Sun.COM 	return (nerr);
2797*9832Samw@Sun.COM }
2798*9832Samw@Sun.COM 
2799*9832Samw@Sun.COM /*
2800*9832Samw@Sun.COM  * Update the share flags.
2801*9832Samw@Sun.COM  */
2802*9832Samw@Sun.COM static uint32_t
2803*9832Samw@Sun.COM srvsvc_sa_setattr(smb_share_t *si)
2804*9832Samw@Sun.COM {
2805*9832Samw@Sun.COM 	sa_handle_t handle;
2806*9832Samw@Sun.COM 	sa_share_t share;
2807*9832Samw@Sun.COM 	sa_resource_t resource;
2808*9832Samw@Sun.COM 	char *value;
2809*9832Samw@Sun.COM 
2810*9832Samw@Sun.COM 	if ((handle = smb_shr_sa_enter()) == NULL)
2811*9832Samw@Sun.COM 		return (NERR_InternalError);
2812*9832Samw@Sun.COM 
2813*9832Samw@Sun.COM 	if ((share = sa_find_share(handle, si->shr_path)) == NULL) {
2814*9832Samw@Sun.COM 		smb_shr_sa_exit();
2815*9832Samw@Sun.COM 		return (NERR_InternalError);
2816*9832Samw@Sun.COM 	}
2817*9832Samw@Sun.COM 
2818*9832Samw@Sun.COM 	if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) {
2819*9832Samw@Sun.COM 		smb_shr_sa_exit();
2820*9832Samw@Sun.COM 		return (NERR_InternalError);
2821*9832Samw@Sun.COM 	}
2822*9832Samw@Sun.COM 
2823*9832Samw@Sun.COM 	if ((value = smb_shr_sa_csc_name(si)) == NULL) {
2824*9832Samw@Sun.COM 		smb_shr_sa_exit();
2825*9832Samw@Sun.COM 		return (NERR_InternalError);
2826*9832Samw@Sun.COM 	}
2827*9832Samw@Sun.COM 
2828*9832Samw@Sun.COM 	(void) sa_set_resource_attr(resource, SHOPT_CSC, value);
2829*9832Samw@Sun.COM 	smb_shr_sa_exit();
2830*9832Samw@Sun.COM 	return (NERR_Success);
2831*9832Samw@Sun.COM }
2832*9832Samw@Sun.COM 
28338474SJose.Borrego@Sun.COM static ndr_stub_table_t srvsvc_stub_table[] = {
28348474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetConnectEnum,	SRVSVC_OPNUM_NetConnectEnum },
28358474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetFileEnum,		SRVSVC_OPNUM_NetFileEnum },
28368474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetFileClose,	SRVSVC_OPNUM_NetFileClose },
28378474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareGetInfo,	SRVSVC_OPNUM_NetShareGetInfo },
28388474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareSetInfo,	SRVSVC_OPNUM_NetShareSetInfo },
28398474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSessionEnum,	SRVSVC_OPNUM_NetSessionEnum },
28408474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSessionDel,	SRVSVC_OPNUM_NetSessionDel },
28418474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetServerGetInfo,	SRVSVC_OPNUM_NetServerGetInfo },
28428474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetRemoteTOD,	SRVSVC_OPNUM_NetRemoteTOD },
28438474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetNameValidate,	SRVSVC_OPNUM_NetNameValidate },
28448474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareAdd,		SRVSVC_OPNUM_NetShareAdd },
28458474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareDel,		SRVSVC_OPNUM_NetShareDel },
28468474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareEnum,	SRVSVC_OPNUM_NetShareEnum },
28478474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetShareEnumSticky,	SRVSVC_OPNUM_NetShareEnumSticky },
2848*9832Samw@Sun.COM 	{ srvsvc_s_NetShareCheck,	SRVSVC_OPNUM_NetShareCheck },
28498474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetGetFileSecurity,	SRVSVC_OPNUM_NetGetFileSecurity },
28508474SJose.Borrego@Sun.COM 	{ srvsvc_s_NetSetFileSecurity,	SRVSVC_OPNUM_NetSetFileSecurity },
28518474SJose.Borrego@Sun.COM 	{0}
28528474SJose.Borrego@Sun.COM };
2853