129bd2886SAlan Wright /*
229bd2886SAlan Wright  * CDDL HEADER START
329bd2886SAlan Wright  *
429bd2886SAlan Wright  * The contents of this file are subject to the terms of the
529bd2886SAlan Wright  * Common Development and Distribution License (the "License").
629bd2886SAlan Wright  * You may not use this file except in compliance with the License.
729bd2886SAlan Wright  *
829bd2886SAlan Wright  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
929bd2886SAlan Wright  * or http://www.opensolaris.org/os/licensing.
1029bd2886SAlan Wright  * See the License for the specific language governing permissions
1129bd2886SAlan Wright  * and limitations under the License.
1229bd2886SAlan Wright  *
1329bd2886SAlan Wright  * When distributing Covered Code, include this CDDL HEADER in each
1429bd2886SAlan Wright  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1529bd2886SAlan Wright  * If applicable, add the following below this CDDL HEADER, with the
1629bd2886SAlan Wright  * fields enclosed by brackets "[]" replaced with your own identifying
1729bd2886SAlan Wright  * information: Portions Copyright [yyyy] [name of copyright owner]
1829bd2886SAlan Wright  *
1929bd2886SAlan Wright  * CDDL HEADER END
2029bd2886SAlan Wright  */
21148c5f43SAlan Wright 
2229bd2886SAlan Wright /*
23148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24*87b81758SJoyce McIntosh  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
2529bd2886SAlan Wright  */
2629bd2886SAlan Wright 
2729bd2886SAlan Wright /*
2829bd2886SAlan Wright  * This is a helper file to get/set Windows SD. This is used by
2929bd2886SAlan Wright  * SRVSVC service.
3029bd2886SAlan Wright  */
3129bd2886SAlan Wright #include <strings.h>
3229bd2886SAlan Wright #include <libzfs.h>
33148c5f43SAlan Wright 
34148c5f43SAlan Wright #include <smbsrv/libsmb.h>
3529bd2886SAlan Wright #include <smbsrv/libmlsvc.h>
3629bd2886SAlan Wright #include <smbsrv/ndl/srvsvc.ndl>
3729bd2886SAlan Wright 
3829bd2886SAlan Wright /* Size of offset members in mslm_security_descriptor structure */
3929bd2886SAlan Wright #define	SRVSVC_SD_OFFSET_SZ	16
4029bd2886SAlan Wright 
4129bd2886SAlan Wright #define	SRVSVC_ACE_OFFSET	8
4229bd2886SAlan Wright #define	SRVSVC_SID_OFFSET	8
4329bd2886SAlan Wright 
44f96bd5c8SAlan Wright uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
45f96bd5c8SAlan Wright 
46fe1c642dSBill Krier static uint32_t srvsvc_sd_get_autohome(const smb_share_t *, smb_sd_t *);
4729bd2886SAlan Wright static uint32_t srvsvc_sd_status_to_error(uint32_t);
4829bd2886SAlan Wright static uint32_t srvsvc_sd_set_absolute(uint8_t *, smb_sd_t *);
4929bd2886SAlan Wright 
5029bd2886SAlan Wright /*
5129bd2886SAlan Wright  * This method computes ACL on share path from a share name.
5229bd2886SAlan Wright  * Return 0 upon success, -1 upon failure.
5329bd2886SAlan Wright  */
5429bd2886SAlan Wright static int
srvsvc_shareacl_getpath(smb_share_t * si,char * shr_acl_path)5529bd2886SAlan Wright srvsvc_shareacl_getpath(smb_share_t *si, char *shr_acl_path)
5629bd2886SAlan Wright {
5729bd2886SAlan Wright 	char dataset[MAXPATHLEN];
5829bd2886SAlan Wright 	char mp[ZFS_MAXPROPLEN];
5929bd2886SAlan Wright 	libzfs_handle_t *libhd;
6029bd2886SAlan Wright 	zfs_handle_t *zfshd;
6129bd2886SAlan Wright 	int ret = 0;
6229bd2886SAlan Wright 
6329bd2886SAlan Wright 	if ((libhd = libzfs_init()) == NULL)
6429bd2886SAlan Wright 		return (-1);
6529bd2886SAlan Wright 
66*87b81758SJoyce McIntosh 	ret = smb_getdataset(libhd, si->shr_path, dataset, MAXPATHLEN);
67*87b81758SJoyce McIntosh 	if (ret != 0) {
68*87b81758SJoyce McIntosh 		libzfs_fini(libhd);
69*87b81758SJoyce McIntosh 		return (ret);
70*87b81758SJoyce McIntosh 	}
71*87b81758SJoyce McIntosh 
72*87b81758SJoyce McIntosh 
7329bd2886SAlan Wright 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
7429bd2886SAlan Wright 		libzfs_fini(libhd);
7529bd2886SAlan Wright 		return (-1);
7629bd2886SAlan Wright 	}
7729bd2886SAlan Wright 
7829bd2886SAlan Wright 	if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL,
7929bd2886SAlan Wright 	    NULL, 0, B_FALSE) != 0) {
8029bd2886SAlan Wright 		zfs_close(zfshd);
8129bd2886SAlan Wright 		libzfs_fini(libhd);
8229bd2886SAlan Wright 		return (-1);
8329bd2886SAlan Wright 	}
8429bd2886SAlan Wright 
8529bd2886SAlan Wright 	zfs_close(zfshd);
8629bd2886SAlan Wright 	libzfs_fini(libhd);
8729bd2886SAlan Wright 
8829bd2886SAlan Wright 	(void) snprintf(shr_acl_path, MAXPATHLEN, "%s/.zfs/shares/%s",
8929bd2886SAlan Wright 	    mp, si->shr_name);
9029bd2886SAlan Wright 
9129bd2886SAlan Wright 	return (ret);
9229bd2886SAlan Wright }
9329bd2886SAlan Wright 
9429bd2886SAlan Wright /*
9529bd2886SAlan Wright  * This method sets Security Descriptor on a share path.
9629bd2886SAlan Wright  *
9729bd2886SAlan Wright  * Returns:
9829bd2886SAlan Wright  *	ERROR_SUCCESS
9929bd2886SAlan Wright  *	ERROR_NOT_ENOUGH_MEMORY
10029bd2886SAlan Wright  *	ERROR_INVALID_ACL
10129bd2886SAlan Wright  *	ERROR_INVALID_SID
10229bd2886SAlan Wright  *	ERROR_INVALID_SECURITY_DESCR
10329bd2886SAlan Wright  *	ERROR_NONE_MAPPED
10429bd2886SAlan Wright  *	ERROR_INTERNAL_ERROR
10529bd2886SAlan Wright  *	ERROR_PATH_NOT_FOUND
10629bd2886SAlan Wright  */
10729bd2886SAlan Wright uint32_t
srvsvc_sd_set(smb_share_t * si,uint8_t * sdbuf)10829bd2886SAlan Wright srvsvc_sd_set(smb_share_t *si, uint8_t *sdbuf)
10929bd2886SAlan Wright {
11029bd2886SAlan Wright 	smb_sd_t sd;
11129bd2886SAlan Wright 	uint32_t status = ERROR_SUCCESS;
11229bd2886SAlan Wright 	char path[MAXPATHLEN];
11329bd2886SAlan Wright 	int ret = 0;
11429bd2886SAlan Wright 
11529bd2886SAlan Wright 	ret = srvsvc_shareacl_getpath(si, path);
11629bd2886SAlan Wright 	if (ret != 0)
11729bd2886SAlan Wright 		return (ERROR_PATH_NOT_FOUND);
11829bd2886SAlan Wright 
11929bd2886SAlan Wright 	smb_sd_init(&sd, 0);
12029bd2886SAlan Wright 	status = srvsvc_sd_set_absolute(sdbuf, &sd);
12129bd2886SAlan Wright 	if (status != ERROR_SUCCESS) {
12229bd2886SAlan Wright 		smb_sd_term(&sd);
12329bd2886SAlan Wright 		return (status);
12429bd2886SAlan Wright 	}
12529bd2886SAlan Wright 
12629bd2886SAlan Wright 	status = smb_sd_write(path, &sd, SMB_DACL_SECINFO);
12729bd2886SAlan Wright 	status = srvsvc_sd_status_to_error(status);
12829bd2886SAlan Wright 	smb_sd_term(&sd);
12929bd2886SAlan Wright 
13029bd2886SAlan Wright 	return (status);
13129bd2886SAlan Wright }
13229bd2886SAlan Wright 
13329bd2886SAlan Wright /*
13429bd2886SAlan Wright  * This method returns a Security Descriptor of a share path in self relative
13529bd2886SAlan Wright  * format. Call to this function with NULL buffer, returns the size of the
13629bd2886SAlan Wright  * security descriptor, which can be used to allocate buffer.
13729bd2886SAlan Wright  *
13829bd2886SAlan Wright  * Returns:
13929bd2886SAlan Wright  *	ERROR_SUCCESS
14029bd2886SAlan Wright  *	ERROR_NOT_ENOUGH_MEMORY
14129bd2886SAlan Wright  *	ERROR_INVALID_ACL
14229bd2886SAlan Wright  *	ERROR_INVALID_SID
14329bd2886SAlan Wright  *	ERROR_INVALID_SECURITY_DESCR
14429bd2886SAlan Wright  *	ERROR_INVALID_PARAMETER
14529bd2886SAlan Wright  *	ERROR_NONE_MAPPED
14629bd2886SAlan Wright  *	ERROR_INTERNAL_ERROR
14729bd2886SAlan Wright  *	ERROR_PATH_NOT_FOUND
14829bd2886SAlan Wright  */
14929bd2886SAlan Wright uint32_t
srvsvc_sd_get(smb_share_t * si,uint8_t * sdbuf,uint32_t * size)15029bd2886SAlan Wright srvsvc_sd_get(smb_share_t *si, uint8_t *sdbuf, uint32_t *size)
15129bd2886SAlan Wright {
15229bd2886SAlan Wright 	smb_sd_t sd;
15329bd2886SAlan Wright 	uint32_t status = ERROR_SUCCESS;
15429bd2886SAlan Wright 	char path[MAXPATHLEN];
15529bd2886SAlan Wright 	int ret = 0;
15629bd2886SAlan Wright 
15729bd2886SAlan Wright 	if (sdbuf == NULL && size == NULL)
15829bd2886SAlan Wright 		return (ERROR_INVALID_PARAMETER);
15929bd2886SAlan Wright 
16029bd2886SAlan Wright 	bzero(&sd, sizeof (smb_sd_t));
161fe1c642dSBill Krier 
162fe1c642dSBill Krier 	if (si->shr_flags & SMB_SHRF_AUTOHOME) {
163fe1c642dSBill Krier 		status = srvsvc_sd_get_autohome(si, &sd);
164fe1c642dSBill Krier 	} else {
165fe1c642dSBill Krier 		ret = srvsvc_shareacl_getpath(si, path);
166fe1c642dSBill Krier 		if (ret != 0)
167fe1c642dSBill Krier 			return (ERROR_PATH_NOT_FOUND);
168fe1c642dSBill Krier 
169fe1c642dSBill Krier 		status = smb_sd_read(path, &sd, SMB_ALL_SECINFO);
170fe1c642dSBill Krier 		status = srvsvc_sd_status_to_error(status);
171fe1c642dSBill Krier 	}
172fe1c642dSBill Krier 
17329bd2886SAlan Wright 	if (status != ERROR_SUCCESS) {
17429bd2886SAlan Wright 		smb_sd_term(&sd);
17529bd2886SAlan Wright 		return (status);
17629bd2886SAlan Wright 	}
17729bd2886SAlan Wright 
17829bd2886SAlan Wright 	if (sdbuf == NULL) {
17929bd2886SAlan Wright 		*size = smb_sd_len(&sd, SMB_ALL_SECINFO);
18029bd2886SAlan Wright 		smb_sd_term(&sd);
18129bd2886SAlan Wright 		return (status);
18229bd2886SAlan Wright 	}
18329bd2886SAlan Wright 
18429bd2886SAlan Wright 	status = srvsvc_sd_set_relative(&sd, sdbuf);
18529bd2886SAlan Wright 
18629bd2886SAlan Wright 	smb_sd_term(&sd);
18729bd2886SAlan Wright 	return (status);
18829bd2886SAlan Wright }
18929bd2886SAlan Wright 
190fe1c642dSBill Krier static uint32_t
srvsvc_sd_get_autohome(const smb_share_t * si,smb_sd_t * sd)191fe1c642dSBill Krier srvsvc_sd_get_autohome(const smb_share_t *si, smb_sd_t *sd)
192fe1c642dSBill Krier {
193fe1c642dSBill Krier 	smb_fssd_t	fs_sd;
194fe1c642dSBill Krier 	acl_t		*acl;
195fe1c642dSBill Krier 	uint32_t	status;
196fe1c642dSBill Krier 
197fe1c642dSBill Krier 	if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0)
198fe1c642dSBill Krier 		return (ERROR_NOT_ENOUGH_MEMORY);
199fe1c642dSBill Krier 
200fe1c642dSBill Krier 	smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
201fe1c642dSBill Krier 	fs_sd.sd_uid = si->shr_uid;
202fe1c642dSBill Krier 	fs_sd.sd_gid = si->shr_gid;
203fe1c642dSBill Krier 	fs_sd.sd_zdacl = acl;
204fe1c642dSBill Krier 	fs_sd.sd_zsacl = NULL;
205fe1c642dSBill Krier 
206fe1c642dSBill Krier 	status = smb_sd_fromfs(&fs_sd, sd);
207fe1c642dSBill Krier 	status = srvsvc_sd_status_to_error(status);
208fe1c642dSBill Krier 	smb_fssd_term(&fs_sd);
209fe1c642dSBill Krier 	return (status);
210fe1c642dSBill Krier }
211fe1c642dSBill Krier 
21229bd2886SAlan Wright /*
21329bd2886SAlan Wright  * This method converts an ACE from absolute (pointer) to
21429bd2886SAlan Wright  * self relative (flat buffer) format.
21529bd2886SAlan Wright  *
21629bd2886SAlan Wright  * Returns Win32 error codes.
21729bd2886SAlan Wright  */
21829bd2886SAlan Wright static uint32_t
srvsvc_ace_set_relative(mslm_ace_t * m_ace,struct mslm_sid * m_sid,smb_ace_t * ace)21929bd2886SAlan Wright srvsvc_ace_set_relative(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
22029bd2886SAlan Wright     smb_ace_t *ace)
22129bd2886SAlan Wright {
22229bd2886SAlan Wright 	if ((m_ace == NULL) || (ace == NULL))
22329bd2886SAlan Wright 		return (ERROR_INVALID_PARAMETER);
22429bd2886SAlan Wright 
22529bd2886SAlan Wright 	bcopy(&ace->se_hdr, &m_ace->header, sizeof (mslm_ace_hdr_t));
22629bd2886SAlan Wright 	m_ace->mask = ace->se_mask;
22729bd2886SAlan Wright 
22829bd2886SAlan Wright 	if ((ace->se_sid == NULL) || (m_sid == NULL))
22929bd2886SAlan Wright 		return (ERROR_INVALID_PARAMETER);
23029bd2886SAlan Wright 	bcopy(ace->se_sid, m_sid, smb_sid_len(ace->se_sid));
23129bd2886SAlan Wright 
23229bd2886SAlan Wright 	return (ERROR_SUCCESS);
23329bd2886SAlan Wright }
23429bd2886SAlan Wright 
23529bd2886SAlan Wright /*
23629bd2886SAlan Wright  * This method converts an ACL from absolute (pointer) to
23729bd2886SAlan Wright  * self relative (flat buffer) format.
23829bd2886SAlan Wright  *
23929bd2886SAlan Wright  * Returns an initialized mslm_acl structure on success.
24029bd2886SAlan Wright  * Returns NULL on failure.
24129bd2886SAlan Wright  */
24229bd2886SAlan Wright static struct mslm_acl *
srvsvc_acl_set_relative(uint8_t * sdbuf,smb_acl_t * acl)24329bd2886SAlan Wright srvsvc_acl_set_relative(uint8_t *sdbuf, smb_acl_t *acl)
24429bd2886SAlan Wright {
24529bd2886SAlan Wright 	struct mslm_acl *m_acl;
24629bd2886SAlan Wright 
24729bd2886SAlan Wright 	if (sdbuf == NULL)
24829bd2886SAlan Wright 		return (NULL);
24929bd2886SAlan Wright 
25029bd2886SAlan Wright 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
25129bd2886SAlan Wright 	m_acl = (struct mslm_acl *)sdbuf;
25229bd2886SAlan Wright 	m_acl->revision = acl->sl_revision;
25329bd2886SAlan Wright 	m_acl->sbz1 = 0;
25429bd2886SAlan Wright 	m_acl->size = acl->sl_bsize;
25529bd2886SAlan Wright 	m_acl->sbz2 = 0;
25629bd2886SAlan Wright 	m_acl->ace_count = acl->sl_acecnt;
25729bd2886SAlan Wright 
25829bd2886SAlan Wright 	return (m_acl);
25929bd2886SAlan Wright }
26029bd2886SAlan Wright 
26129bd2886SAlan Wright /*
26229bd2886SAlan Wright  * This method converts Security Descriptor from absolute (pointer) to
26329bd2886SAlan Wright  * self relative (flat buffer) format.
26429bd2886SAlan Wright  *
26529bd2886SAlan Wright  * Returns Win32 error codes.
26629bd2886SAlan Wright  */
267f96bd5c8SAlan Wright uint32_t
srvsvc_sd_set_relative(smb_sd_t * sd,uint8_t * sdbuf)26829bd2886SAlan Wright srvsvc_sd_set_relative(smb_sd_t *sd, uint8_t *sdbuf)
26929bd2886SAlan Wright {
27029bd2886SAlan Wright 	mslm_security_descriptor_t *msd;
27129bd2886SAlan Wright 	int offset, len, i;
27229bd2886SAlan Wright 	smb_ace_t *ace;
27329bd2886SAlan Wright 	mslm_ace_t *m_ace;
27429bd2886SAlan Wright 	struct mslm_sid *m_sid;
27529bd2886SAlan Wright 	uint16_t ace_cnt;
27629bd2886SAlan Wright 	uint32_t status = ERROR_SUCCESS;
27729bd2886SAlan Wright 
27829bd2886SAlan Wright 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
27929bd2886SAlan Wright 	msd = (mslm_security_descriptor_t *)sdbuf;
28029bd2886SAlan Wright 	if (msd == NULL)
28129bd2886SAlan Wright 		return (ERROR_INVALID_SECURITY_DESCR);
28229bd2886SAlan Wright 
28329bd2886SAlan Wright 	msd->revision = sd->sd_revision;
28429bd2886SAlan Wright 	msd->sbz1 = 0;
28529bd2886SAlan Wright 	msd->control = sd->sd_control | SE_SELF_RELATIVE;
28629bd2886SAlan Wright 
28729bd2886SAlan Wright 	offset = sizeof (mslm_security_descriptor_t) - SRVSVC_SD_OFFSET_SZ;
28829bd2886SAlan Wright 	msd->offset_owner = msd->offset_group = 0;
28929bd2886SAlan Wright 	msd->offset_sacl = msd->offset_dacl = 0;
29029bd2886SAlan Wright 
29129bd2886SAlan Wright 	if (sd->sd_owner != NULL) {
29229bd2886SAlan Wright 		msd->offset_owner = offset;
29329bd2886SAlan Wright 
29429bd2886SAlan Wright 		if (sd->sd_owner == NULL)
29529bd2886SAlan Wright 			return (ERROR_NOT_ENOUGH_MEMORY);
29629bd2886SAlan Wright 
29729bd2886SAlan Wright 		len = smb_sid_len(sd->sd_owner);
29829bd2886SAlan Wright 		bcopy(sd->sd_owner, &sdbuf[offset], len);
29929bd2886SAlan Wright 		offset += len;
30029bd2886SAlan Wright 	}
30129bd2886SAlan Wright 
30229bd2886SAlan Wright 	if (sd->sd_group != NULL) {
30329bd2886SAlan Wright 		msd->offset_group = offset;
30429bd2886SAlan Wright 
30529bd2886SAlan Wright 		if (sd->sd_group == NULL)
30629bd2886SAlan Wright 			return (ERROR_NOT_ENOUGH_MEMORY);
30729bd2886SAlan Wright 
30829bd2886SAlan Wright 		len = smb_sid_len(sd->sd_group);
30929bd2886SAlan Wright 		bcopy(sd->sd_group, &sdbuf[offset], len);
31029bd2886SAlan Wright 		offset += len;
31129bd2886SAlan Wright 	}
31229bd2886SAlan Wright 
31329bd2886SAlan Wright 	if (sd->sd_sacl != NULL) {
31429bd2886SAlan Wright 		msd->offset_sacl = offset;
31529bd2886SAlan Wright 		msd->sacl = srvsvc_acl_set_relative(&sdbuf[offset],
31629bd2886SAlan Wright 		    sd->sd_sacl);
31729bd2886SAlan Wright 		if (msd->sacl == NULL)
31829bd2886SAlan Wright 			return (ERROR_INVALID_PARAMETER);
31929bd2886SAlan Wright 
32029bd2886SAlan Wright 		ace = sd->sd_sacl->sl_aces;
32129bd2886SAlan Wright 		ace_cnt = msd->sacl->ace_count;
32229bd2886SAlan Wright 		offset += SRVSVC_ACE_OFFSET;
32329bd2886SAlan Wright 
32429bd2886SAlan Wright 		for (i = 0; i < ace_cnt; i++, ace++) {
32529bd2886SAlan Wright 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
32629bd2886SAlan Wright 			m_ace = (mslm_ace_t *)&sdbuf[offset];
32729bd2886SAlan Wright 			offset += SRVSVC_SID_OFFSET;
32829bd2886SAlan Wright 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
32929bd2886SAlan Wright 			m_sid = (struct mslm_sid *)&sdbuf[offset];
33029bd2886SAlan Wright 
33129bd2886SAlan Wright 			status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
33229bd2886SAlan Wright 			if (status != ERROR_SUCCESS)
33329bd2886SAlan Wright 				return (status);
33429bd2886SAlan Wright 			offset += smb_sid_len(ace->se_sid);
33529bd2886SAlan Wright 		}
33629bd2886SAlan Wright 	}
33729bd2886SAlan Wright 
33829bd2886SAlan Wright 	if (sd->sd_dacl != NULL) {
33929bd2886SAlan Wright 		msd->offset_dacl = offset;
34029bd2886SAlan Wright 		msd->dacl = srvsvc_acl_set_relative(&sdbuf[offset],
34129bd2886SAlan Wright 		    sd->sd_dacl);
34229bd2886SAlan Wright 		if (msd->dacl == NULL)
34329bd2886SAlan Wright 			return (ERROR_INVALID_PARAMETER);
34429bd2886SAlan Wright 
34529bd2886SAlan Wright 		ace = sd->sd_dacl->sl_aces;
34629bd2886SAlan Wright 		ace_cnt = msd->dacl->ace_count;
34729bd2886SAlan Wright 		offset += SRVSVC_ACE_OFFSET;
34829bd2886SAlan Wright 
34929bd2886SAlan Wright 		for (i = 0; i < ace_cnt; i++, ace++) {
35029bd2886SAlan Wright 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
35129bd2886SAlan Wright 			m_ace = (mslm_ace_t *)&sdbuf[offset];
35229bd2886SAlan Wright 			offset += SRVSVC_SID_OFFSET;
35329bd2886SAlan Wright 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
35429bd2886SAlan Wright 			m_sid = (struct mslm_sid *)&sdbuf[offset];
35529bd2886SAlan Wright 
35629bd2886SAlan Wright 			status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
35729bd2886SAlan Wright 			if (status != ERROR_SUCCESS)
35829bd2886SAlan Wright 				return (status);
35929bd2886SAlan Wright 			offset += smb_sid_len(ace->se_sid);
36029bd2886SAlan Wright 		}
36129bd2886SAlan Wright 	}
36229bd2886SAlan Wright 
36329bd2886SAlan Wright 	return (status);
36429bd2886SAlan Wright }
36529bd2886SAlan Wright 
36629bd2886SAlan Wright /*
36729bd2886SAlan Wright  * This method converts an ACE from self relative (flat buffer) to
36829bd2886SAlan Wright  * absolute (pointer) format.
36929bd2886SAlan Wright  *
37029bd2886SAlan Wright  * Returns Win32 error codes.
37129bd2886SAlan Wright  */
37229bd2886SAlan Wright static uint32_t
srvsvc_ace_set_absolute(mslm_ace_t * m_ace,struct mslm_sid * m_sid,smb_ace_t * ace)37329bd2886SAlan Wright srvsvc_ace_set_absolute(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
37429bd2886SAlan Wright     smb_ace_t *ace)
37529bd2886SAlan Wright {
37629bd2886SAlan Wright 	int sid_size = 0;
37729bd2886SAlan Wright 	if ((m_ace == NULL) || (ace == NULL) || (m_sid == NULL))
37829bd2886SAlan Wright 		return (ERROR_INVALID_PARAMETER);
37929bd2886SAlan Wright 
38029bd2886SAlan Wright 	bzero(ace, sizeof (smb_ace_t));
38129bd2886SAlan Wright 	bcopy(&m_ace->header, &ace->se_hdr, sizeof (mslm_ace_hdr_t));
38229bd2886SAlan Wright 	ace->se_mask = m_ace->mask;
38329bd2886SAlan Wright 
38429bd2886SAlan Wright 	sid_size = smb_sid_len((smb_sid_t *)m_sid);
38529bd2886SAlan Wright 	if ((ace->se_sid = malloc(sid_size)) == NULL)
38629bd2886SAlan Wright 		return (ERROR_NOT_ENOUGH_MEMORY);
38729bd2886SAlan Wright 	bcopy(m_sid, ace->se_sid, sid_size);
38829bd2886SAlan Wright 
38929bd2886SAlan Wright 	return (ERROR_SUCCESS);
39029bd2886SAlan Wright }
39129bd2886SAlan Wright 
39229bd2886SAlan Wright /*
39329bd2886SAlan Wright  * This method converts an ACL from self relative (flat buffer) to
39429bd2886SAlan Wright  * absolute (pointer) format.
39529bd2886SAlan Wright  *
39629bd2886SAlan Wright  * Returns an initialized smb_acl_t structure on success.
39729bd2886SAlan Wright  * Returns NULL on failure.
39829bd2886SAlan Wright  */
39929bd2886SAlan Wright static smb_acl_t *
srvsvc_acl_set_absolute(uint8_t * sdbuf,int * offset)40029bd2886SAlan Wright srvsvc_acl_set_absolute(uint8_t *sdbuf, int *offset)
40129bd2886SAlan Wright {
40229bd2886SAlan Wright 	uint8_t rev;
40329bd2886SAlan Wright 	uint16_t sz, ace_cnt;
40429bd2886SAlan Wright 	smb_acl_t *acl;
40529bd2886SAlan Wright 
40629bd2886SAlan Wright 	bcopy(&sdbuf[*offset], &rev, sizeof (uint8_t));
40729bd2886SAlan Wright 	*offset += 2; /* Pad for Sbz1 */
40829bd2886SAlan Wright 	bcopy(&sdbuf[*offset], &sz, sizeof (uint16_t));
40929bd2886SAlan Wright 	*offset += 2;
41029bd2886SAlan Wright 	bcopy(&sdbuf[*offset], &ace_cnt, sizeof (uint16_t));
41129bd2886SAlan Wright 	*offset += 4; /* Pad for Sbz2 */
41229bd2886SAlan Wright 
41329bd2886SAlan Wright 	acl = smb_acl_alloc(rev, sz, ace_cnt);
41429bd2886SAlan Wright 
41529bd2886SAlan Wright 	return (acl);
41629bd2886SAlan Wright }
41729bd2886SAlan Wright 
41829bd2886SAlan Wright /*
41929bd2886SAlan Wright  * This method converts Security Descriptor from self relative (flat buffer) to
42029bd2886SAlan Wright  * absolute (pointer) format.
42129bd2886SAlan Wright  *
42229bd2886SAlan Wright  * Returns Win32 error codes.
42329bd2886SAlan Wright  */
42429bd2886SAlan Wright static uint32_t
srvsvc_sd_set_absolute(uint8_t * sdbuf,smb_sd_t * sd)42529bd2886SAlan Wright srvsvc_sd_set_absolute(uint8_t *sdbuf, smb_sd_t *sd)
42629bd2886SAlan Wright {
42729bd2886SAlan Wright 	mslm_security_descriptor_t *msd;
42829bd2886SAlan Wright 	mslm_ace_t *m_ace;
42929bd2886SAlan Wright 	struct mslm_sid *m_sid;
43029bd2886SAlan Wright 	smb_ace_t *ace;
43129bd2886SAlan Wright 	uint16_t ace_cnt;
43229bd2886SAlan Wright 	int offset, i, sid_size;
43329bd2886SAlan Wright 	uint32_t status = ERROR_SUCCESS;
43429bd2886SAlan Wright 
43529bd2886SAlan Wright 	if (sdbuf == NULL)
43629bd2886SAlan Wright 		return (ERROR_INVALID_SECURITY_DESCR);
43729bd2886SAlan Wright 
43829bd2886SAlan Wright 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
43929bd2886SAlan Wright 	msd = (mslm_security_descriptor_t *)sdbuf;
44029bd2886SAlan Wright 
44129bd2886SAlan Wright 	sd->sd_revision = msd->revision;
44229bd2886SAlan Wright 	sd->sd_control = msd->control & (~SE_SELF_RELATIVE);
44329bd2886SAlan Wright 
44429bd2886SAlan Wright 	if (msd->offset_owner != 0) {
44529bd2886SAlan Wright 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
44629bd2886SAlan Wright 		m_sid = (struct mslm_sid *)&sdbuf[msd->offset_owner];
44729bd2886SAlan Wright 		sid_size = smb_sid_len((smb_sid_t *)m_sid);
44829bd2886SAlan Wright 
44929bd2886SAlan Wright 		if ((sd->sd_owner = malloc(sid_size)) == NULL)
45029bd2886SAlan Wright 			return (ERROR_NOT_ENOUGH_MEMORY);
45129bd2886SAlan Wright 		bcopy(m_sid, sd->sd_owner, sid_size);
45229bd2886SAlan Wright 	}
45329bd2886SAlan Wright 
45429bd2886SAlan Wright 	if (msd->offset_group != 0) {
45529bd2886SAlan Wright 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
45629bd2886SAlan Wright 		m_sid = (struct mslm_sid *)&sdbuf[msd->offset_group];
45729bd2886SAlan Wright 		sid_size = smb_sid_len((smb_sid_t *)m_sid);
45829bd2886SAlan Wright 
45929bd2886SAlan Wright 		if ((sd->sd_group = malloc(sid_size)) == NULL)
46029bd2886SAlan Wright 			return (ERROR_NOT_ENOUGH_MEMORY);
46129bd2886SAlan Wright 		bcopy(m_sid, sd->sd_group, sid_size);
46229bd2886SAlan Wright 	}
46329bd2886SAlan Wright 
46429bd2886SAlan Wright 	if (msd->offset_sacl != 0) {
46529bd2886SAlan Wright 		offset = msd->offset_sacl;
46629bd2886SAlan Wright 		sd->sd_sacl = srvsvc_acl_set_absolute(sdbuf, &offset);
46729bd2886SAlan Wright 		if (sd->sd_sacl == NULL)
46829bd2886SAlan Wright 			return (ERROR_NOT_ENOUGH_MEMORY);
46929bd2886SAlan Wright 
47029bd2886SAlan Wright 		ace = sd->sd_sacl->sl_aces;
47129bd2886SAlan Wright 		ace_cnt = sd->sd_sacl->sl_acecnt;
47229bd2886SAlan Wright 
47329bd2886SAlan Wright 		for (i = 0; i < ace_cnt; i++, ace++) {
47429bd2886SAlan Wright 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
47529bd2886SAlan Wright 			m_ace = (mslm_ace_t *)&sdbuf[offset];
47629bd2886SAlan Wright 			offset += SRVSVC_SID_OFFSET;
47729bd2886SAlan Wright 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
47829bd2886SAlan Wright 			m_sid = (struct mslm_sid *)&sdbuf[offset];
47929bd2886SAlan Wright 
48029bd2886SAlan Wright 			status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
48129bd2886SAlan Wright 			if (status != ERROR_SUCCESS)
48229bd2886SAlan Wright 				return (status);
48329bd2886SAlan Wright 			offset += smb_sid_len(ace->se_sid);
48429bd2886SAlan Wright 		}
48529bd2886SAlan Wright 	}
48629bd2886SAlan Wright 
48729bd2886SAlan Wright 	if (msd->offset_dacl != 0) {
48829bd2886SAlan Wright 		offset = msd->offset_dacl;
48929bd2886SAlan Wright 		sd->sd_dacl = srvsvc_acl_set_absolute(sdbuf, &offset);
49029bd2886SAlan Wright 		if (sd->sd_dacl == NULL)
49129bd2886SAlan Wright 			return (ERROR_NOT_ENOUGH_MEMORY);
49229bd2886SAlan Wright 
49329bd2886SAlan Wright 		ace = sd->sd_dacl->sl_aces;
49429bd2886SAlan Wright 		ace_cnt = sd->sd_dacl->sl_acecnt;
49529bd2886SAlan Wright 
49629bd2886SAlan Wright 		for (i = 0; i < ace_cnt; i++, ace++) {
49729bd2886SAlan Wright 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
49829bd2886SAlan Wright 			m_ace = (mslm_ace_t *)&sdbuf[offset];
49929bd2886SAlan Wright 			offset += SRVSVC_SID_OFFSET;
50029bd2886SAlan Wright 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
50129bd2886SAlan Wright 			m_sid = (struct mslm_sid *)&sdbuf[offset];
50229bd2886SAlan Wright 
50329bd2886SAlan Wright 			status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
50429bd2886SAlan Wright 			if (status != ERROR_SUCCESS)
50529bd2886SAlan Wright 				return (status);
50629bd2886SAlan Wright 			offset += smb_sid_len(ace->se_sid);
50729bd2886SAlan Wright 		}
50829bd2886SAlan Wright 	}
50929bd2886SAlan Wright 
51029bd2886SAlan Wright 	return (status);
51129bd2886SAlan Wright }
51229bd2886SAlan Wright 
51329bd2886SAlan Wright /*
51429bd2886SAlan Wright  * This method maps NT status codes into Win 32 error codes.
51529bd2886SAlan Wright  * This method operates on status codes that are related
51629bd2886SAlan Wright  * to processing of Security Descriptor.
51729bd2886SAlan Wright  */
51829bd2886SAlan Wright static uint32_t
srvsvc_sd_status_to_error(uint32_t status)51929bd2886SAlan Wright srvsvc_sd_status_to_error(uint32_t status)
52029bd2886SAlan Wright {
52129bd2886SAlan Wright 	int i;
52229bd2886SAlan Wright 	static struct {
52329bd2886SAlan Wright 		uint32_t	nt_status;
52429bd2886SAlan Wright 		uint32_t	err_code;
52529bd2886SAlan Wright 	} errmap[] = {
52629bd2886SAlan Wright 		{ NT_STATUS_SUCCESS,		ERROR_SUCCESS },
52729bd2886SAlan Wright 		{ NT_STATUS_INVALID_ACL,	ERROR_INVALID_ACL },
52829bd2886SAlan Wright 		{ NT_STATUS_INVALID_SID,	ERROR_INVALID_SID },
52929bd2886SAlan Wright 		{ NT_STATUS_NONE_MAPPED,	ERROR_NONE_MAPPED }
53029bd2886SAlan Wright 	};
53129bd2886SAlan Wright 
53229bd2886SAlan Wright 	for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
53329bd2886SAlan Wright 		if (status == errmap[i].nt_status)
53429bd2886SAlan Wright 			return (errmap[i].err_code);
53529bd2886SAlan Wright 	}
53629bd2886SAlan Wright 
53729bd2886SAlan Wright 	return (ERROR_INTERNAL_ERROR);
53829bd2886SAlan Wright }
539