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