xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.c (revision 12508:edb7861a1533)
19832Samw@Sun.COM /*
29832Samw@Sun.COM  * CDDL HEADER START
39832Samw@Sun.COM  *
49832Samw@Sun.COM  * The contents of this file are subject to the terms of the
59832Samw@Sun.COM  * Common Development and Distribution License (the "License").
69832Samw@Sun.COM  * You may not use this file except in compliance with the License.
79832Samw@Sun.COM  *
89832Samw@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99832Samw@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109832Samw@Sun.COM  * See the License for the specific language governing permissions
119832Samw@Sun.COM  * and limitations under the License.
129832Samw@Sun.COM  *
139832Samw@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149832Samw@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159832Samw@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169832Samw@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179832Samw@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189832Samw@Sun.COM  *
199832Samw@Sun.COM  * CDDL HEADER END
209832Samw@Sun.COM  */
21*12508Samw@Sun.COM 
229832Samw@Sun.COM /*
23*12508Samw@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
249832Samw@Sun.COM  */
259832Samw@Sun.COM 
269832Samw@Sun.COM /*
279832Samw@Sun.COM  * This is a helper file to get/set Windows SD. This is used by
289832Samw@Sun.COM  * SRVSVC service.
299832Samw@Sun.COM  */
309832Samw@Sun.COM #include <strings.h>
319832Samw@Sun.COM #include <libzfs.h>
32*12508Samw@Sun.COM 
33*12508Samw@Sun.COM #include <smbsrv/libsmb.h>
349832Samw@Sun.COM #include <smbsrv/libmlsvc.h>
359832Samw@Sun.COM #include <smbsrv/ndl/srvsvc.ndl>
369832Samw@Sun.COM 
379832Samw@Sun.COM /* Size of offset members in mslm_security_descriptor structure */
389832Samw@Sun.COM #define	SRVSVC_SD_OFFSET_SZ	16
399832Samw@Sun.COM 
409832Samw@Sun.COM #define	SRVSVC_ACE_OFFSET	8
419832Samw@Sun.COM #define	SRVSVC_SID_OFFSET	8
429832Samw@Sun.COM 
4311447Samw@Sun.COM uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
4411447Samw@Sun.COM 
4511337SWilliam.Krier@Sun.COM static uint32_t srvsvc_sd_get_autohome(const smb_share_t *, smb_sd_t *);
469832Samw@Sun.COM static uint32_t srvsvc_sd_status_to_error(uint32_t);
479832Samw@Sun.COM static uint32_t srvsvc_sd_set_absolute(uint8_t *, smb_sd_t *);
489832Samw@Sun.COM 
499832Samw@Sun.COM /*
509832Samw@Sun.COM  * This method computes ACL on share path from a share name.
519832Samw@Sun.COM  * Return 0 upon success, -1 upon failure.
529832Samw@Sun.COM  */
539832Samw@Sun.COM static int
srvsvc_shareacl_getpath(smb_share_t * si,char * shr_acl_path)549832Samw@Sun.COM srvsvc_shareacl_getpath(smb_share_t *si, char *shr_acl_path)
559832Samw@Sun.COM {
569832Samw@Sun.COM 	char dataset[MAXPATHLEN];
579832Samw@Sun.COM 	char mp[ZFS_MAXPROPLEN];
589832Samw@Sun.COM 	libzfs_handle_t *libhd;
599832Samw@Sun.COM 	zfs_handle_t *zfshd;
609832Samw@Sun.COM 	int ret = 0;
619832Samw@Sun.COM 
629832Samw@Sun.COM 	ret = smb_getdataset(si->shr_path, dataset, MAXPATHLEN);
639832Samw@Sun.COM 	if (ret != 0)
649832Samw@Sun.COM 		return (ret);
659832Samw@Sun.COM 
669832Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
679832Samw@Sun.COM 		return (-1);
689832Samw@Sun.COM 
699832Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
709832Samw@Sun.COM 		libzfs_fini(libhd);
719832Samw@Sun.COM 		return (-1);
729832Samw@Sun.COM 	}
739832Samw@Sun.COM 
749832Samw@Sun.COM 	if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL,
759832Samw@Sun.COM 	    NULL, 0, B_FALSE) != 0) {
769832Samw@Sun.COM 		zfs_close(zfshd);
779832Samw@Sun.COM 		libzfs_fini(libhd);
789832Samw@Sun.COM 		return (-1);
799832Samw@Sun.COM 	}
809832Samw@Sun.COM 
819832Samw@Sun.COM 	zfs_close(zfshd);
829832Samw@Sun.COM 	libzfs_fini(libhd);
839832Samw@Sun.COM 
849832Samw@Sun.COM 	(void) snprintf(shr_acl_path, MAXPATHLEN, "%s/.zfs/shares/%s",
859832Samw@Sun.COM 	    mp, si->shr_name);
869832Samw@Sun.COM 
879832Samw@Sun.COM 	return (ret);
889832Samw@Sun.COM }
899832Samw@Sun.COM 
909832Samw@Sun.COM /*
919832Samw@Sun.COM  * This method sets Security Descriptor on a share path.
929832Samw@Sun.COM  *
939832Samw@Sun.COM  * Returns:
949832Samw@Sun.COM  *	ERROR_SUCCESS
959832Samw@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
969832Samw@Sun.COM  *	ERROR_INVALID_ACL
979832Samw@Sun.COM  *	ERROR_INVALID_SID
989832Samw@Sun.COM  *	ERROR_INVALID_SECURITY_DESCR
999832Samw@Sun.COM  *	ERROR_NONE_MAPPED
1009832Samw@Sun.COM  *	ERROR_INTERNAL_ERROR
1019832Samw@Sun.COM  *	ERROR_PATH_NOT_FOUND
1029832Samw@Sun.COM  */
1039832Samw@Sun.COM uint32_t
srvsvc_sd_set(smb_share_t * si,uint8_t * sdbuf)1049832Samw@Sun.COM srvsvc_sd_set(smb_share_t *si, uint8_t *sdbuf)
1059832Samw@Sun.COM {
1069832Samw@Sun.COM 	smb_sd_t sd;
1079832Samw@Sun.COM 	uint32_t status = ERROR_SUCCESS;
1089832Samw@Sun.COM 	char path[MAXPATHLEN];
1099832Samw@Sun.COM 	int ret = 0;
1109832Samw@Sun.COM 
1119832Samw@Sun.COM 	ret = srvsvc_shareacl_getpath(si, path);
1129832Samw@Sun.COM 	if (ret != 0)
1139832Samw@Sun.COM 		return (ERROR_PATH_NOT_FOUND);
1149832Samw@Sun.COM 
1159832Samw@Sun.COM 	smb_sd_init(&sd, 0);
1169832Samw@Sun.COM 	status = srvsvc_sd_set_absolute(sdbuf, &sd);
1179832Samw@Sun.COM 	if (status != ERROR_SUCCESS) {
1189832Samw@Sun.COM 		smb_sd_term(&sd);
1199832Samw@Sun.COM 		return (status);
1209832Samw@Sun.COM 	}
1219832Samw@Sun.COM 
1229832Samw@Sun.COM 	status = smb_sd_write(path, &sd, SMB_DACL_SECINFO);
1239832Samw@Sun.COM 	status = srvsvc_sd_status_to_error(status);
1249832Samw@Sun.COM 	smb_sd_term(&sd);
1259832Samw@Sun.COM 
1269832Samw@Sun.COM 	return (status);
1279832Samw@Sun.COM }
1289832Samw@Sun.COM 
1299832Samw@Sun.COM /*
1309832Samw@Sun.COM  * This method returns a Security Descriptor of a share path in self relative
1319832Samw@Sun.COM  * format. Call to this function with NULL buffer, returns the size of the
1329832Samw@Sun.COM  * security descriptor, which can be used to allocate buffer.
1339832Samw@Sun.COM  *
1349832Samw@Sun.COM  * Returns:
1359832Samw@Sun.COM  *	ERROR_SUCCESS
1369832Samw@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
1379832Samw@Sun.COM  *	ERROR_INVALID_ACL
1389832Samw@Sun.COM  *	ERROR_INVALID_SID
1399832Samw@Sun.COM  *	ERROR_INVALID_SECURITY_DESCR
1409832Samw@Sun.COM  *	ERROR_INVALID_PARAMETER
1419832Samw@Sun.COM  *	ERROR_NONE_MAPPED
1429832Samw@Sun.COM  *	ERROR_INTERNAL_ERROR
1439832Samw@Sun.COM  *	ERROR_PATH_NOT_FOUND
1449832Samw@Sun.COM  */
1459832Samw@Sun.COM uint32_t
srvsvc_sd_get(smb_share_t * si,uint8_t * sdbuf,uint32_t * size)1469832Samw@Sun.COM srvsvc_sd_get(smb_share_t *si, uint8_t *sdbuf, uint32_t *size)
1479832Samw@Sun.COM {
1489832Samw@Sun.COM 	smb_sd_t sd;
1499832Samw@Sun.COM 	uint32_t status = ERROR_SUCCESS;
1509832Samw@Sun.COM 	char path[MAXPATHLEN];
1519832Samw@Sun.COM 	int ret = 0;
1529832Samw@Sun.COM 
1539832Samw@Sun.COM 	if (sdbuf == NULL && size == NULL)
1549832Samw@Sun.COM 		return (ERROR_INVALID_PARAMETER);
1559832Samw@Sun.COM 
15611337SWilliam.Krier@Sun.COM 	bzero(&sd, sizeof (smb_sd_t));
1579832Samw@Sun.COM 
15811337SWilliam.Krier@Sun.COM 	if (si->shr_flags & SMB_SHRF_AUTOHOME) {
15911337SWilliam.Krier@Sun.COM 		status = srvsvc_sd_get_autohome(si, &sd);
16011337SWilliam.Krier@Sun.COM 	} else {
16111337SWilliam.Krier@Sun.COM 		ret = srvsvc_shareacl_getpath(si, path);
16211337SWilliam.Krier@Sun.COM 		if (ret != 0)
16311337SWilliam.Krier@Sun.COM 			return (ERROR_PATH_NOT_FOUND);
16411337SWilliam.Krier@Sun.COM 
16511337SWilliam.Krier@Sun.COM 		status = smb_sd_read(path, &sd, SMB_ALL_SECINFO);
16611337SWilliam.Krier@Sun.COM 		status = srvsvc_sd_status_to_error(status);
16711337SWilliam.Krier@Sun.COM 	}
16811337SWilliam.Krier@Sun.COM 
1699832Samw@Sun.COM 	if (status != ERROR_SUCCESS) {
1709832Samw@Sun.COM 		smb_sd_term(&sd);
1719832Samw@Sun.COM 		return (status);
1729832Samw@Sun.COM 	}
1739832Samw@Sun.COM 
1749832Samw@Sun.COM 	if (sdbuf == NULL) {
1759832Samw@Sun.COM 		*size = smb_sd_len(&sd, SMB_ALL_SECINFO);
1769832Samw@Sun.COM 		smb_sd_term(&sd);
1779832Samw@Sun.COM 		return (status);
1789832Samw@Sun.COM 	}
1799832Samw@Sun.COM 
1809832Samw@Sun.COM 	status = srvsvc_sd_set_relative(&sd, sdbuf);
1819832Samw@Sun.COM 
1829832Samw@Sun.COM 	smb_sd_term(&sd);
1839832Samw@Sun.COM 	return (status);
1849832Samw@Sun.COM }
1859832Samw@Sun.COM 
18611337SWilliam.Krier@Sun.COM static uint32_t
srvsvc_sd_get_autohome(const smb_share_t * si,smb_sd_t * sd)18711337SWilliam.Krier@Sun.COM srvsvc_sd_get_autohome(const smb_share_t *si, smb_sd_t *sd)
18811337SWilliam.Krier@Sun.COM {
18911337SWilliam.Krier@Sun.COM 	smb_fssd_t	fs_sd;
19011337SWilliam.Krier@Sun.COM 	acl_t		*acl;
19111337SWilliam.Krier@Sun.COM 	uint32_t	status;
19211337SWilliam.Krier@Sun.COM 
19311337SWilliam.Krier@Sun.COM 	if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0)
19411337SWilliam.Krier@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
19511337SWilliam.Krier@Sun.COM 
19611337SWilliam.Krier@Sun.COM 	smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
19711337SWilliam.Krier@Sun.COM 	fs_sd.sd_uid = si->shr_uid;
19811337SWilliam.Krier@Sun.COM 	fs_sd.sd_gid = si->shr_gid;
19911337SWilliam.Krier@Sun.COM 	fs_sd.sd_zdacl = acl;
20011337SWilliam.Krier@Sun.COM 	fs_sd.sd_zsacl = NULL;
20111337SWilliam.Krier@Sun.COM 
20211337SWilliam.Krier@Sun.COM 	status = smb_sd_fromfs(&fs_sd, sd);
20311337SWilliam.Krier@Sun.COM 	status = srvsvc_sd_status_to_error(status);
20411337SWilliam.Krier@Sun.COM 	smb_fssd_term(&fs_sd);
20511337SWilliam.Krier@Sun.COM 	return (status);
20611337SWilliam.Krier@Sun.COM }
20711337SWilliam.Krier@Sun.COM 
2089832Samw@Sun.COM /*
2099832Samw@Sun.COM  * This method converts an ACE from absolute (pointer) to
2109832Samw@Sun.COM  * self relative (flat buffer) format.
2119832Samw@Sun.COM  *
2129832Samw@Sun.COM  * Returns Win32 error codes.
2139832Samw@Sun.COM  */
2149832Samw@Sun.COM static uint32_t
srvsvc_ace_set_relative(mslm_ace_t * m_ace,struct mslm_sid * m_sid,smb_ace_t * ace)2159832Samw@Sun.COM srvsvc_ace_set_relative(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
2169832Samw@Sun.COM     smb_ace_t *ace)
2179832Samw@Sun.COM {
2189832Samw@Sun.COM 	if ((m_ace == NULL) || (ace == NULL))
2199832Samw@Sun.COM 		return (ERROR_INVALID_PARAMETER);
2209832Samw@Sun.COM 
2219832Samw@Sun.COM 	bcopy(&ace->se_hdr, &m_ace->header, sizeof (mslm_ace_hdr_t));
2229832Samw@Sun.COM 	m_ace->mask = ace->se_mask;
2239832Samw@Sun.COM 
2249832Samw@Sun.COM 	if ((ace->se_sid == NULL) || (m_sid == NULL))
2259832Samw@Sun.COM 		return (ERROR_INVALID_PARAMETER);
2269832Samw@Sun.COM 	bcopy(ace->se_sid, m_sid, smb_sid_len(ace->se_sid));
2279832Samw@Sun.COM 
2289832Samw@Sun.COM 	return (ERROR_SUCCESS);
2299832Samw@Sun.COM }
2309832Samw@Sun.COM 
2319832Samw@Sun.COM /*
2329832Samw@Sun.COM  * This method converts an ACL from absolute (pointer) to
2339832Samw@Sun.COM  * self relative (flat buffer) format.
2349832Samw@Sun.COM  *
2359832Samw@Sun.COM  * Returns an initialized mslm_acl structure on success.
2369832Samw@Sun.COM  * Returns NULL on failure.
2379832Samw@Sun.COM  */
2389832Samw@Sun.COM static struct mslm_acl *
srvsvc_acl_set_relative(uint8_t * sdbuf,smb_acl_t * acl)2399832Samw@Sun.COM srvsvc_acl_set_relative(uint8_t *sdbuf, smb_acl_t *acl)
2409832Samw@Sun.COM {
2419832Samw@Sun.COM 	struct mslm_acl *m_acl;
2429832Samw@Sun.COM 
2439832Samw@Sun.COM 	if (sdbuf == NULL)
2449832Samw@Sun.COM 		return (NULL);
2459832Samw@Sun.COM 
2469832Samw@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
2479832Samw@Sun.COM 	m_acl = (struct mslm_acl *)sdbuf;
2489832Samw@Sun.COM 	m_acl->revision = acl->sl_revision;
2499832Samw@Sun.COM 	m_acl->sbz1 = 0;
2509832Samw@Sun.COM 	m_acl->size = acl->sl_bsize;
2519832Samw@Sun.COM 	m_acl->sbz2 = 0;
2529832Samw@Sun.COM 	m_acl->ace_count = acl->sl_acecnt;
2539832Samw@Sun.COM 
2549832Samw@Sun.COM 	return (m_acl);
2559832Samw@Sun.COM }
2569832Samw@Sun.COM 
2579832Samw@Sun.COM /*
2589832Samw@Sun.COM  * This method converts Security Descriptor from absolute (pointer) to
2599832Samw@Sun.COM  * self relative (flat buffer) format.
2609832Samw@Sun.COM  *
2619832Samw@Sun.COM  * Returns Win32 error codes.
2629832Samw@Sun.COM  */
26311447Samw@Sun.COM uint32_t
srvsvc_sd_set_relative(smb_sd_t * sd,uint8_t * sdbuf)2649832Samw@Sun.COM srvsvc_sd_set_relative(smb_sd_t *sd, uint8_t *sdbuf)
2659832Samw@Sun.COM {
2669832Samw@Sun.COM 	mslm_security_descriptor_t *msd;
2679832Samw@Sun.COM 	int offset, len, i;
2689832Samw@Sun.COM 	smb_ace_t *ace;
2699832Samw@Sun.COM 	mslm_ace_t *m_ace;
2709832Samw@Sun.COM 	struct mslm_sid *m_sid;
2719832Samw@Sun.COM 	uint16_t ace_cnt;
2729832Samw@Sun.COM 	uint32_t status = ERROR_SUCCESS;
2739832Samw@Sun.COM 
2749832Samw@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
2759832Samw@Sun.COM 	msd = (mslm_security_descriptor_t *)sdbuf;
2769832Samw@Sun.COM 	if (msd == NULL)
2779832Samw@Sun.COM 		return (ERROR_INVALID_SECURITY_DESCR);
2789832Samw@Sun.COM 
2799832Samw@Sun.COM 	msd->revision = sd->sd_revision;
2809832Samw@Sun.COM 	msd->sbz1 = 0;
2819832Samw@Sun.COM 	msd->control = sd->sd_control | SE_SELF_RELATIVE;
2829832Samw@Sun.COM 
2839832Samw@Sun.COM 	offset = sizeof (mslm_security_descriptor_t) - SRVSVC_SD_OFFSET_SZ;
2849832Samw@Sun.COM 	msd->offset_owner = msd->offset_group = 0;
2859832Samw@Sun.COM 	msd->offset_sacl = msd->offset_dacl = 0;
2869832Samw@Sun.COM 
2879832Samw@Sun.COM 	if (sd->sd_owner != NULL) {
2889832Samw@Sun.COM 		msd->offset_owner = offset;
2899832Samw@Sun.COM 
2909832Samw@Sun.COM 		if (sd->sd_owner == NULL)
2919832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
2929832Samw@Sun.COM 
2939832Samw@Sun.COM 		len = smb_sid_len(sd->sd_owner);
2949832Samw@Sun.COM 		bcopy(sd->sd_owner, &sdbuf[offset], len);
2959832Samw@Sun.COM 		offset += len;
2969832Samw@Sun.COM 	}
2979832Samw@Sun.COM 
2989832Samw@Sun.COM 	if (sd->sd_group != NULL) {
2999832Samw@Sun.COM 		msd->offset_group = offset;
3009832Samw@Sun.COM 
3019832Samw@Sun.COM 		if (sd->sd_group == NULL)
3029832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
3039832Samw@Sun.COM 
3049832Samw@Sun.COM 		len = smb_sid_len(sd->sd_group);
3059832Samw@Sun.COM 		bcopy(sd->sd_group, &sdbuf[offset], len);
3069832Samw@Sun.COM 		offset += len;
3079832Samw@Sun.COM 	}
3089832Samw@Sun.COM 
3099832Samw@Sun.COM 	if (sd->sd_sacl != NULL) {
3109832Samw@Sun.COM 		msd->offset_sacl = offset;
3119832Samw@Sun.COM 		msd->sacl = srvsvc_acl_set_relative(&sdbuf[offset],
3129832Samw@Sun.COM 		    sd->sd_sacl);
3139832Samw@Sun.COM 		if (msd->sacl == NULL)
3149832Samw@Sun.COM 			return (ERROR_INVALID_PARAMETER);
3159832Samw@Sun.COM 
3169832Samw@Sun.COM 		ace = sd->sd_sacl->sl_aces;
3179832Samw@Sun.COM 		ace_cnt = msd->sacl->ace_count;
3189832Samw@Sun.COM 		offset += SRVSVC_ACE_OFFSET;
3199832Samw@Sun.COM 
3209832Samw@Sun.COM 		for (i = 0; i < ace_cnt; i++, ace++) {
3219832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
3229832Samw@Sun.COM 			m_ace = (mslm_ace_t *)&sdbuf[offset];
3239832Samw@Sun.COM 			offset += SRVSVC_SID_OFFSET;
3249832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
3259832Samw@Sun.COM 			m_sid = (struct mslm_sid *)&sdbuf[offset];
3269832Samw@Sun.COM 
3279832Samw@Sun.COM 			status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
3289832Samw@Sun.COM 			if (status != ERROR_SUCCESS)
3299832Samw@Sun.COM 				return (status);
3309832Samw@Sun.COM 			offset += smb_sid_len(ace->se_sid);
3319832Samw@Sun.COM 		}
3329832Samw@Sun.COM 	}
3339832Samw@Sun.COM 
3349832Samw@Sun.COM 	if (sd->sd_dacl != NULL) {
3359832Samw@Sun.COM 		msd->offset_dacl = offset;
3369832Samw@Sun.COM 		msd->dacl = srvsvc_acl_set_relative(&sdbuf[offset],
3379832Samw@Sun.COM 		    sd->sd_dacl);
3389832Samw@Sun.COM 		if (msd->dacl == NULL)
3399832Samw@Sun.COM 			return (ERROR_INVALID_PARAMETER);
3409832Samw@Sun.COM 
3419832Samw@Sun.COM 		ace = sd->sd_dacl->sl_aces;
3429832Samw@Sun.COM 		ace_cnt = msd->dacl->ace_count;
3439832Samw@Sun.COM 		offset += SRVSVC_ACE_OFFSET;
3449832Samw@Sun.COM 
3459832Samw@Sun.COM 		for (i = 0; i < ace_cnt; i++, ace++) {
3469832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
3479832Samw@Sun.COM 			m_ace = (mslm_ace_t *)&sdbuf[offset];
3489832Samw@Sun.COM 			offset += SRVSVC_SID_OFFSET;
3499832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
3509832Samw@Sun.COM 			m_sid = (struct mslm_sid *)&sdbuf[offset];
3519832Samw@Sun.COM 
3529832Samw@Sun.COM 			status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
3539832Samw@Sun.COM 			if (status != ERROR_SUCCESS)
3549832Samw@Sun.COM 				return (status);
3559832Samw@Sun.COM 			offset += smb_sid_len(ace->se_sid);
3569832Samw@Sun.COM 		}
3579832Samw@Sun.COM 	}
3589832Samw@Sun.COM 
3599832Samw@Sun.COM 	return (status);
3609832Samw@Sun.COM }
3619832Samw@Sun.COM 
3629832Samw@Sun.COM /*
3639832Samw@Sun.COM  * This method converts an ACE from self relative (flat buffer) to
3649832Samw@Sun.COM  * absolute (pointer) format.
3659832Samw@Sun.COM  *
3669832Samw@Sun.COM  * Returns Win32 error codes.
3679832Samw@Sun.COM  */
3689832Samw@Sun.COM static uint32_t
srvsvc_ace_set_absolute(mslm_ace_t * m_ace,struct mslm_sid * m_sid,smb_ace_t * ace)3699832Samw@Sun.COM srvsvc_ace_set_absolute(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
3709832Samw@Sun.COM     smb_ace_t *ace)
3719832Samw@Sun.COM {
3729832Samw@Sun.COM 	int sid_size = 0;
3739832Samw@Sun.COM 	if ((m_ace == NULL) || (ace == NULL) || (m_sid == NULL))
3749832Samw@Sun.COM 		return (ERROR_INVALID_PARAMETER);
3759832Samw@Sun.COM 
3769832Samw@Sun.COM 	bzero(ace, sizeof (smb_ace_t));
3779832Samw@Sun.COM 	bcopy(&m_ace->header, &ace->se_hdr, sizeof (mslm_ace_hdr_t));
3789832Samw@Sun.COM 	ace->se_mask = m_ace->mask;
3799832Samw@Sun.COM 
3809832Samw@Sun.COM 	sid_size = smb_sid_len((smb_sid_t *)m_sid);
3819832Samw@Sun.COM 	if ((ace->se_sid = malloc(sid_size)) == NULL)
3829832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
3839832Samw@Sun.COM 	bcopy(m_sid, ace->se_sid, sid_size);
3849832Samw@Sun.COM 
3859832Samw@Sun.COM 	return (ERROR_SUCCESS);
3869832Samw@Sun.COM }
3879832Samw@Sun.COM 
3889832Samw@Sun.COM /*
3899832Samw@Sun.COM  * This method converts an ACL from self relative (flat buffer) to
3909832Samw@Sun.COM  * absolute (pointer) format.
3919832Samw@Sun.COM  *
3929832Samw@Sun.COM  * Returns an initialized smb_acl_t structure on success.
3939832Samw@Sun.COM  * Returns NULL on failure.
3949832Samw@Sun.COM  */
3959832Samw@Sun.COM static smb_acl_t *
srvsvc_acl_set_absolute(uint8_t * sdbuf,int * offset)3969832Samw@Sun.COM srvsvc_acl_set_absolute(uint8_t *sdbuf, int *offset)
3979832Samw@Sun.COM {
3989832Samw@Sun.COM 	uint8_t rev;
3999832Samw@Sun.COM 	uint16_t sz, ace_cnt;
4009832Samw@Sun.COM 	smb_acl_t *acl;
4019832Samw@Sun.COM 
4029832Samw@Sun.COM 	bcopy(&sdbuf[*offset], &rev, sizeof (uint8_t));
4039832Samw@Sun.COM 	*offset += 2; /* Pad for Sbz1 */
4049832Samw@Sun.COM 	bcopy(&sdbuf[*offset], &sz, sizeof (uint16_t));
4059832Samw@Sun.COM 	*offset += 2;
4069832Samw@Sun.COM 	bcopy(&sdbuf[*offset], &ace_cnt, sizeof (uint16_t));
4079832Samw@Sun.COM 	*offset += 4; /* Pad for Sbz2 */
4089832Samw@Sun.COM 
4099832Samw@Sun.COM 	acl = smb_acl_alloc(rev, sz, ace_cnt);
4109832Samw@Sun.COM 
4119832Samw@Sun.COM 	return (acl);
4129832Samw@Sun.COM }
4139832Samw@Sun.COM 
4149832Samw@Sun.COM /*
4159832Samw@Sun.COM  * This method converts Security Descriptor from self relative (flat buffer) to
4169832Samw@Sun.COM  * absolute (pointer) format.
4179832Samw@Sun.COM  *
4189832Samw@Sun.COM  * Returns Win32 error codes.
4199832Samw@Sun.COM  */
4209832Samw@Sun.COM static uint32_t
srvsvc_sd_set_absolute(uint8_t * sdbuf,smb_sd_t * sd)4219832Samw@Sun.COM srvsvc_sd_set_absolute(uint8_t *sdbuf, smb_sd_t *sd)
4229832Samw@Sun.COM {
4239832Samw@Sun.COM 	mslm_security_descriptor_t *msd;
4249832Samw@Sun.COM 	mslm_ace_t *m_ace;
4259832Samw@Sun.COM 	struct mslm_sid *m_sid;
4269832Samw@Sun.COM 	smb_ace_t *ace;
4279832Samw@Sun.COM 	uint16_t ace_cnt;
4289832Samw@Sun.COM 	int offset, i, sid_size;
4299832Samw@Sun.COM 	uint32_t status = ERROR_SUCCESS;
4309832Samw@Sun.COM 
4319832Samw@Sun.COM 	if (sdbuf == NULL)
4329832Samw@Sun.COM 		return (ERROR_INVALID_SECURITY_DESCR);
4339832Samw@Sun.COM 
4349832Samw@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
4359832Samw@Sun.COM 	msd = (mslm_security_descriptor_t *)sdbuf;
4369832Samw@Sun.COM 
4379832Samw@Sun.COM 	sd->sd_revision = msd->revision;
4389832Samw@Sun.COM 	sd->sd_control = msd->control & (~SE_SELF_RELATIVE);
4399832Samw@Sun.COM 
4409832Samw@Sun.COM 	if (msd->offset_owner != 0) {
4419832Samw@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
4429832Samw@Sun.COM 		m_sid = (struct mslm_sid *)&sdbuf[msd->offset_owner];
4439832Samw@Sun.COM 		sid_size = smb_sid_len((smb_sid_t *)m_sid);
4449832Samw@Sun.COM 
4459832Samw@Sun.COM 		if ((sd->sd_owner = malloc(sid_size)) == NULL)
4469832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
4479832Samw@Sun.COM 		bcopy(m_sid, sd->sd_owner, sid_size);
4489832Samw@Sun.COM 	}
4499832Samw@Sun.COM 
4509832Samw@Sun.COM 	if (msd->offset_group != 0) {
4519832Samw@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
4529832Samw@Sun.COM 		m_sid = (struct mslm_sid *)&sdbuf[msd->offset_group];
4539832Samw@Sun.COM 		sid_size = smb_sid_len((smb_sid_t *)m_sid);
4549832Samw@Sun.COM 
4559832Samw@Sun.COM 		if ((sd->sd_group = malloc(sid_size)) == NULL)
4569832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
4579832Samw@Sun.COM 		bcopy(m_sid, sd->sd_group, sid_size);
4589832Samw@Sun.COM 	}
4599832Samw@Sun.COM 
4609832Samw@Sun.COM 	if (msd->offset_sacl != 0) {
4619832Samw@Sun.COM 		offset = msd->offset_sacl;
4629832Samw@Sun.COM 		sd->sd_sacl = srvsvc_acl_set_absolute(sdbuf, &offset);
4639832Samw@Sun.COM 		if (sd->sd_sacl == NULL)
4649832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
4659832Samw@Sun.COM 
4669832Samw@Sun.COM 		ace = sd->sd_sacl->sl_aces;
4679832Samw@Sun.COM 		ace_cnt = sd->sd_sacl->sl_acecnt;
4689832Samw@Sun.COM 
4699832Samw@Sun.COM 		for (i = 0; i < ace_cnt; i++, ace++) {
4709832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
4719832Samw@Sun.COM 			m_ace = (mslm_ace_t *)&sdbuf[offset];
4729832Samw@Sun.COM 			offset += SRVSVC_SID_OFFSET;
4739832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
4749832Samw@Sun.COM 			m_sid = (struct mslm_sid *)&sdbuf[offset];
4759832Samw@Sun.COM 
4769832Samw@Sun.COM 			status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
4779832Samw@Sun.COM 			if (status != ERROR_SUCCESS)
4789832Samw@Sun.COM 				return (status);
4799832Samw@Sun.COM 			offset += smb_sid_len(ace->se_sid);
4809832Samw@Sun.COM 		}
4819832Samw@Sun.COM 	}
4829832Samw@Sun.COM 
4839832Samw@Sun.COM 	if (msd->offset_dacl != 0) {
4849832Samw@Sun.COM 		offset = msd->offset_dacl;
4859832Samw@Sun.COM 		sd->sd_dacl = srvsvc_acl_set_absolute(sdbuf, &offset);
4869832Samw@Sun.COM 		if (sd->sd_dacl == NULL)
4879832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
4889832Samw@Sun.COM 
4899832Samw@Sun.COM 		ace = sd->sd_dacl->sl_aces;
4909832Samw@Sun.COM 		ace_cnt = sd->sd_dacl->sl_acecnt;
4919832Samw@Sun.COM 
4929832Samw@Sun.COM 		for (i = 0; i < ace_cnt; i++, ace++) {
4939832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
4949832Samw@Sun.COM 			m_ace = (mslm_ace_t *)&sdbuf[offset];
4959832Samw@Sun.COM 			offset += SRVSVC_SID_OFFSET;
4969832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
4979832Samw@Sun.COM 			m_sid = (struct mslm_sid *)&sdbuf[offset];
4989832Samw@Sun.COM 
4999832Samw@Sun.COM 			status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
5009832Samw@Sun.COM 			if (status != ERROR_SUCCESS)
5019832Samw@Sun.COM 				return (status);
5029832Samw@Sun.COM 			offset += smb_sid_len(ace->se_sid);
5039832Samw@Sun.COM 		}
5049832Samw@Sun.COM 	}
5059832Samw@Sun.COM 
5069832Samw@Sun.COM 	return (status);
5079832Samw@Sun.COM }
5089832Samw@Sun.COM 
5099832Samw@Sun.COM /*
5109832Samw@Sun.COM  * This method maps NT status codes into Win 32 error codes.
5119832Samw@Sun.COM  * This method operates on status codes that are related
5129832Samw@Sun.COM  * to processing of Security Descriptor.
5139832Samw@Sun.COM  */
5149832Samw@Sun.COM static uint32_t
srvsvc_sd_status_to_error(uint32_t status)5159832Samw@Sun.COM srvsvc_sd_status_to_error(uint32_t status)
5169832Samw@Sun.COM {
5179832Samw@Sun.COM 	int i;
5189832Samw@Sun.COM 	static struct {
5199832Samw@Sun.COM 		uint32_t	nt_status;
5209832Samw@Sun.COM 		uint32_t	err_code;
5219832Samw@Sun.COM 	} errmap[] = {
5229832Samw@Sun.COM 		{ NT_STATUS_SUCCESS,		ERROR_SUCCESS },
5239832Samw@Sun.COM 		{ NT_STATUS_INVALID_ACL,	ERROR_INVALID_ACL },
5249832Samw@Sun.COM 		{ NT_STATUS_INVALID_SID,	ERROR_INVALID_SID },
5259832Samw@Sun.COM 		{ NT_STATUS_NONE_MAPPED,	ERROR_NONE_MAPPED }
5269832Samw@Sun.COM 	};
5279832Samw@Sun.COM 
5289832Samw@Sun.COM 	for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
5299832Samw@Sun.COM 		if (status == errmap[i].nt_status)
5309832Samw@Sun.COM 			return (errmap[i].err_code);
5319832Samw@Sun.COM 	}
5329832Samw@Sun.COM 
5339832Samw@Sun.COM 	return (ERROR_INTERNAL_ERROR);
5349832Samw@Sun.COM }
535