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.
2429bd2886SAlan Wright  */
2529bd2886SAlan Wright 
2629bd2886SAlan Wright /*
2729bd2886SAlan Wright  * This module provides Security Descriptor handling functions.
2829bd2886SAlan Wright  */
2929bd2886SAlan Wright 
3029bd2886SAlan Wright #include <strings.h>
3129bd2886SAlan Wright #include <assert.h>
32*1fdeec65Sjoyce mcintosh #include <errno.h>
3329bd2886SAlan Wright #include <smbsrv/ntifs.h>
3429bd2886SAlan Wright #include <smbsrv/smb_idmap.h>
35b1352070SAlan Wright #include <smbsrv/libsmb.h>
3629bd2886SAlan Wright 
3729bd2886SAlan Wright #define	SMB_SHR_ACE_READ_PERMS	(ACE_READ_PERMS | ACE_EXECUTE | ACE_SYNCHRONIZE)
3829bd2886SAlan Wright #define	SMB_SHR_ACE_CONTROL_PERMS	(ACE_MODIFY_PERMS & (~ACE_DELETE_CHILD))
3929bd2886SAlan Wright 
409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * This mapping table is provided to map permissions set by chmod
429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * using 'read_set' and 'modify_set' to what Windows share ACL GUI
439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * expects as Read and Control, respectively.
449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
45b1352070SAlan Wright static struct {
46b1352070SAlan Wright 	int am_ace_perms;
47b1352070SAlan Wright 	int am_share_perms;
48b1352070SAlan Wright } smb_ace_map[] = {
49b1352070SAlan Wright 	{ ACE_MODIFY_PERMS,	SMB_SHR_ACE_CONTROL_PERMS },
50b1352070SAlan Wright 	{ ACE_READ_PERMS,	SMB_SHR_ACE_READ_PERMS }
51b1352070SAlan Wright };
52b1352070SAlan Wright 
53b1352070SAlan Wright #define	SMB_ACE_MASK_MAP_SIZE	(sizeof (smb_ace_map)/sizeof (smb_ace_map[0]))
54b1352070SAlan Wright 
5529bd2886SAlan Wright static void smb_sd_set_sacl(smb_sd_t *, smb_acl_t *, boolean_t, int);
5629bd2886SAlan Wright static void smb_sd_set_dacl(smb_sd_t *, smb_acl_t *, boolean_t, int);
5729bd2886SAlan Wright 
5829bd2886SAlan Wright void
smb_sd_init(smb_sd_t * sd,uint8_t revision)5929bd2886SAlan Wright smb_sd_init(smb_sd_t *sd, uint8_t revision)
6029bd2886SAlan Wright {
6129bd2886SAlan Wright 	bzero(sd, sizeof (smb_sd_t));
6229bd2886SAlan Wright 	sd->sd_revision = revision;
6329bd2886SAlan Wright }
6429bd2886SAlan Wright 
6529bd2886SAlan Wright /*
6629bd2886SAlan Wright  * smb_sd_term
6729bd2886SAlan Wright  *
6829bd2886SAlan Wright  * Free non-NULL members of 'sd' which has to be in
6929bd2886SAlan Wright  * absolute (pointer) form.
7029bd2886SAlan Wright  */
7129bd2886SAlan Wright void
smb_sd_term(smb_sd_t * sd)7229bd2886SAlan Wright smb_sd_term(smb_sd_t *sd)
7329bd2886SAlan Wright {
7429bd2886SAlan Wright 	assert(sd);
7529bd2886SAlan Wright 	assert((sd->sd_control & SE_SELF_RELATIVE) == 0);
7629bd2886SAlan Wright 
7729bd2886SAlan Wright 	smb_sid_free(sd->sd_owner);
7829bd2886SAlan Wright 	smb_sid_free(sd->sd_group);
7929bd2886SAlan Wright 	smb_acl_free(sd->sd_dacl);
8029bd2886SAlan Wright 	smb_acl_free(sd->sd_sacl);
8129bd2886SAlan Wright 
8229bd2886SAlan Wright 	bzero(sd, sizeof (smb_sd_t));
8329bd2886SAlan Wright }
8429bd2886SAlan Wright 
8529bd2886SAlan Wright uint32_t
smb_sd_len(smb_sd_t * sd,uint32_t secinfo)8629bd2886SAlan Wright smb_sd_len(smb_sd_t *sd, uint32_t secinfo)
8729bd2886SAlan Wright {
8829bd2886SAlan Wright 	uint32_t length = SMB_SD_HDRSIZE;
8929bd2886SAlan Wright 
9029bd2886SAlan Wright 	if (secinfo & SMB_OWNER_SECINFO)
9129bd2886SAlan Wright 		length += smb_sid_len(sd->sd_owner);
9229bd2886SAlan Wright 
9329bd2886SAlan Wright 	if (secinfo & SMB_GROUP_SECINFO)
9429bd2886SAlan Wright 		length += smb_sid_len(sd->sd_group);
9529bd2886SAlan Wright 
9629bd2886SAlan Wright 	if (secinfo & SMB_DACL_SECINFO)
9729bd2886SAlan Wright 		length += smb_acl_len(sd->sd_dacl);
9829bd2886SAlan Wright 
9929bd2886SAlan Wright 	if (secinfo & SMB_SACL_SECINFO)
10029bd2886SAlan Wright 		length += smb_acl_len(sd->sd_sacl);
10129bd2886SAlan Wright 
10229bd2886SAlan Wright 	return (length);
10329bd2886SAlan Wright }
10429bd2886SAlan Wright 
10529bd2886SAlan Wright /*
10629bd2886SAlan Wright  * smb_sd_get_secinfo
10729bd2886SAlan Wright  *
10829bd2886SAlan Wright  * Return the security information mask for the specified security
10929bd2886SAlan Wright  * descriptor.
11029bd2886SAlan Wright  */
11129bd2886SAlan Wright uint32_t
smb_sd_get_secinfo(smb_sd_t * sd)11229bd2886SAlan Wright smb_sd_get_secinfo(smb_sd_t *sd)
11329bd2886SAlan Wright {
11429bd2886SAlan Wright 	uint32_t sec_info = 0;
11529bd2886SAlan Wright 
11629bd2886SAlan Wright 	if (sd == NULL)
11729bd2886SAlan Wright 		return (0);
11829bd2886SAlan Wright 
11929bd2886SAlan Wright 	if (sd->sd_owner)
12029bd2886SAlan Wright 		sec_info |= SMB_OWNER_SECINFO;
12129bd2886SAlan Wright 
12229bd2886SAlan Wright 	if (sd->sd_group)
12329bd2886SAlan Wright 		sec_info |= SMB_GROUP_SECINFO;
12429bd2886SAlan Wright 
12529bd2886SAlan Wright 	if (sd->sd_dacl)
12629bd2886SAlan Wright 		sec_info |= SMB_DACL_SECINFO;
12729bd2886SAlan Wright 
12829bd2886SAlan Wright 	if (sd->sd_sacl)
12929bd2886SAlan Wright 		sec_info |= SMB_SACL_SECINFO;
13029bd2886SAlan Wright 
13129bd2886SAlan Wright 	return (sec_info);
13229bd2886SAlan Wright }
13329bd2886SAlan Wright 
13429bd2886SAlan Wright /*
13529bd2886SAlan Wright  * Adjust the Access Mask so that ZFS ACE mask and Windows ACE read mask match.
13629bd2886SAlan Wright  */
13729bd2886SAlan Wright static int
smb_sd_adjust_read_mask(int mask)13829bd2886SAlan Wright smb_sd_adjust_read_mask(int mask)
13929bd2886SAlan Wright {
140b1352070SAlan Wright 	int i;
141b1352070SAlan Wright 
142b1352070SAlan Wright 	for (i = 0; i < SMB_ACE_MASK_MAP_SIZE; ++i) {
143b1352070SAlan Wright 		if (smb_ace_map[i].am_ace_perms == mask)
144b1352070SAlan Wright 			return (smb_ace_map[i].am_share_perms);
145b1352070SAlan Wright 	}
146b1352070SAlan Wright 
1479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (mask);
14829bd2886SAlan Wright }
14929bd2886SAlan Wright 
15029bd2886SAlan Wright /*
15129bd2886SAlan Wright  * Get ZFS acl from the share path via acl_get() method.
15229bd2886SAlan Wright  */
15329bd2886SAlan Wright static uint32_t
smb_sd_read_acl(char * path,smb_fssd_t * fs_sd)15429bd2886SAlan Wright smb_sd_read_acl(char *path, smb_fssd_t *fs_sd)
15529bd2886SAlan Wright {
15629bd2886SAlan Wright 	acl_t *z_acl;
15729bd2886SAlan Wright 	ace_t *z_ace;
15829bd2886SAlan Wright 
15929bd2886SAlan Wright 	fs_sd->sd_gid = fs_sd->sd_uid = 0;
16029bd2886SAlan Wright 
161*1fdeec65Sjoyce mcintosh 	errno = 0;
162*1fdeec65Sjoyce mcintosh 	if (acl_get(path, 0, &z_acl) != 0) {
163*1fdeec65Sjoyce mcintosh 		switch (errno) {
164*1fdeec65Sjoyce mcintosh 		case EACCES:
165*1fdeec65Sjoyce mcintosh 			return (NT_STATUS_ACCESS_DENIED);
166*1fdeec65Sjoyce mcintosh 		case ENOENT:
167*1fdeec65Sjoyce mcintosh 			return (NT_STATUS_OBJECT_PATH_NOT_FOUND);
168*1fdeec65Sjoyce mcintosh 		default:
169*1fdeec65Sjoyce mcintosh 			return (NT_STATUS_INTERNAL_ERROR);
170*1fdeec65Sjoyce mcintosh 		}
171*1fdeec65Sjoyce mcintosh 	}
17229bd2886SAlan Wright 
17329bd2886SAlan Wright 	if ((z_ace = (ace_t *)z_acl->acl_aclp) == NULL)
17429bd2886SAlan Wright 		return (NT_STATUS_INVALID_ACL);
17529bd2886SAlan Wright 
1769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	for (int i = 0; i < z_acl->acl_cnt; i++, z_ace++)
1779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		z_ace->a_access_mask =
1789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    smb_sd_adjust_read_mask(z_ace->a_access_mask);
17929bd2886SAlan Wright 
18029bd2886SAlan Wright 	fs_sd->sd_zdacl = z_acl;
18129bd2886SAlan Wright 	fs_sd->sd_zsacl = NULL;
18229bd2886SAlan Wright 	return (NT_STATUS_SUCCESS);
18329bd2886SAlan Wright }
18429bd2886SAlan Wright 
18529bd2886SAlan Wright /*
18629bd2886SAlan Wright  * smb_sd_read
18729bd2886SAlan Wright  *
18829bd2886SAlan Wright  * Reads ZFS acl from filesystem using acl_get() method. Convert the ZFS acl to
18929bd2886SAlan Wright  * a Win SD and return the Win SD in absolute form.
19029bd2886SAlan Wright  *
19129bd2886SAlan Wright  * NOTE: upon successful return caller MUST free the memory allocated
19229bd2886SAlan Wright  * for the returned SD by calling smb_sd_term().
19329bd2886SAlan Wright  */
19429bd2886SAlan Wright uint32_t
smb_sd_read(char * path,smb_sd_t * sd,uint32_t secinfo)19529bd2886SAlan Wright smb_sd_read(char *path, smb_sd_t *sd, uint32_t secinfo)
19629bd2886SAlan Wright {
19729bd2886SAlan Wright 	smb_fssd_t fs_sd;
19829bd2886SAlan Wright 	uint32_t status = NT_STATUS_SUCCESS;
19929bd2886SAlan Wright 	uint32_t sd_flags;
20029bd2886SAlan Wright 	int error;
20129bd2886SAlan Wright 
20229bd2886SAlan Wright 	sd_flags = SMB_FSSD_FLAGS_DIR;
20329bd2886SAlan Wright 	smb_fssd_init(&fs_sd, secinfo, sd_flags);
20429bd2886SAlan Wright 
20529bd2886SAlan Wright 	error = smb_sd_read_acl(path, &fs_sd);
20629bd2886SAlan Wright 	if (error != NT_STATUS_SUCCESS) {
20729bd2886SAlan Wright 		smb_fssd_term(&fs_sd);
20829bd2886SAlan Wright 		return (error);
20929bd2886SAlan Wright 	}
21029bd2886SAlan Wright 
21129bd2886SAlan Wright 	status = smb_sd_fromfs(&fs_sd, sd);
21229bd2886SAlan Wright 	smb_fssd_term(&fs_sd);
21329bd2886SAlan Wright 
21429bd2886SAlan Wright 	return (status);
21529bd2886SAlan Wright }
21629bd2886SAlan Wright 
21729bd2886SAlan Wright /*
21829bd2886SAlan Wright  * Apply ZFS acl to the share path via acl_set() method.
2199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * A NULL ACL pointer here represents an error.
2209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Null or empty ACLs are handled in smb_sd_tofs().
22129bd2886SAlan Wright  */
22229bd2886SAlan Wright static uint32_t
smb_sd_write_acl(char * path,smb_fssd_t * fs_sd)22329bd2886SAlan Wright smb_sd_write_acl(char *path, smb_fssd_t *fs_sd)
22429bd2886SAlan Wright {
22529bd2886SAlan Wright 	acl_t *z_acl;
22629bd2886SAlan Wright 	ace_t *z_ace;
22729bd2886SAlan Wright 	uint32_t status = NT_STATUS_SUCCESS;
22829bd2886SAlan Wright 
2299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	z_acl = fs_sd->sd_zdacl;
2309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (z_acl == NULL)
23129bd2886SAlan Wright 		return (NT_STATUS_INVALID_ACL);
23229bd2886SAlan Wright 
2339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	z_ace = (ace_t *)z_acl->acl_aclp;
2349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (z_ace == NULL)
23529bd2886SAlan Wright 		return (NT_STATUS_INVALID_ACL);
23629bd2886SAlan Wright 
23729bd2886SAlan Wright 	fs_sd->sd_gid = fs_sd->sd_uid = 0;
23829bd2886SAlan Wright 	if (acl_set(path, z_acl) != 0)
23929bd2886SAlan Wright 		status = NT_STATUS_INTERNAL_ERROR;
24029bd2886SAlan Wright 
24129bd2886SAlan Wright 	return (status);
24229bd2886SAlan Wright }
24329bd2886SAlan Wright 
24429bd2886SAlan Wright /*
24529bd2886SAlan Wright  * smb_sd_write
24629bd2886SAlan Wright  *
24729bd2886SAlan Wright  * Takes a Win SD in absolute form, converts it to
24829bd2886SAlan Wright  * ZFS acl and applies the acl to the share path via acl_set() method.
24929bd2886SAlan Wright  */
25029bd2886SAlan Wright uint32_t
smb_sd_write(char * path,smb_sd_t * sd,uint32_t secinfo)25129bd2886SAlan Wright smb_sd_write(char *path, smb_sd_t *sd, uint32_t secinfo)
25229bd2886SAlan Wright {
25329bd2886SAlan Wright 	smb_fssd_t fs_sd;
25429bd2886SAlan Wright 	uint32_t status = NT_STATUS_SUCCESS;
25529bd2886SAlan Wright 	uint32_t sd_flags;
25629bd2886SAlan Wright 	int error;
25729bd2886SAlan Wright 
25829bd2886SAlan Wright 	sd_flags = SMB_FSSD_FLAGS_DIR;
25929bd2886SAlan Wright 	smb_fssd_init(&fs_sd, secinfo, sd_flags);
26029bd2886SAlan Wright 
26129bd2886SAlan Wright 	error = smb_sd_tofs(sd, &fs_sd);
26229bd2886SAlan Wright 	if (error != NT_STATUS_SUCCESS) {
26329bd2886SAlan Wright 		smb_fssd_term(&fs_sd);
26429bd2886SAlan Wright 		return (error);
26529bd2886SAlan Wright 	}
26629bd2886SAlan Wright 
26729bd2886SAlan Wright 	status = smb_sd_write_acl(path, &fs_sd);
26829bd2886SAlan Wright 	smb_fssd_term(&fs_sd);
26929bd2886SAlan Wright 
27029bd2886SAlan Wright 	return (status);
27129bd2886SAlan Wright }
27229bd2886SAlan Wright 
27329bd2886SAlan Wright /*
27429bd2886SAlan Wright  * smb_sd_tofs
27529bd2886SAlan Wright  *
27629bd2886SAlan Wright  * Creates a filesystem security structure based on the given
27729bd2886SAlan Wright  * Windows security descriptor.
27829bd2886SAlan Wright  */
27929bd2886SAlan Wright uint32_t
smb_sd_tofs(smb_sd_t * sd,smb_fssd_t * fs_sd)28029bd2886SAlan Wright smb_sd_tofs(smb_sd_t *sd, smb_fssd_t *fs_sd)
28129bd2886SAlan Wright {
28229bd2886SAlan Wright 	smb_sid_t *sid;
28329bd2886SAlan Wright 	uint32_t status = NT_STATUS_SUCCESS;
28429bd2886SAlan Wright 	uint16_t sd_control;
28529bd2886SAlan Wright 	idmap_stat idm_stat;
28629bd2886SAlan Wright 	int idtype;
28729bd2886SAlan Wright 	int flags = 0;
28829bd2886SAlan Wright 
28929bd2886SAlan Wright 	sd_control = sd->sd_control;
29029bd2886SAlan Wright 
29129bd2886SAlan Wright 	/*
29229bd2886SAlan Wright 	 * ZFS only has one set of flags so for now only
29329bd2886SAlan Wright 	 * Windows DACL flags are taken into account.
29429bd2886SAlan Wright 	 */
29529bd2886SAlan Wright 	if (sd_control & SE_DACL_DEFAULTED)
29629bd2886SAlan Wright 		flags |= ACL_DEFAULTED;
29729bd2886SAlan Wright 	if (sd_control & SE_DACL_AUTO_INHERITED)
29829bd2886SAlan Wright 		flags |= ACL_AUTO_INHERIT;
29929bd2886SAlan Wright 	if (sd_control & SE_DACL_PROTECTED)
30029bd2886SAlan Wright 		flags |= ACL_PROTECTED;
30129bd2886SAlan Wright 
30229bd2886SAlan Wright 	if (fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR)
30329bd2886SAlan Wright 		flags |= ACL_IS_DIR;
30429bd2886SAlan Wright 
30529bd2886SAlan Wright 	/* Owner */
30629bd2886SAlan Wright 	if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
30729bd2886SAlan Wright 		sid = sd->sd_owner;
30829bd2886SAlan Wright 		if (!smb_sid_isvalid(sid))
30929bd2886SAlan Wright 			return (NT_STATUS_INVALID_SID);
31029bd2886SAlan Wright 
31129bd2886SAlan Wright 		idtype = SMB_IDMAP_USER;
31229bd2886SAlan Wright 		idm_stat = smb_idmap_getid(sid, &fs_sd->sd_uid, &idtype);
31329bd2886SAlan Wright 		if (idm_stat != IDMAP_SUCCESS) {
31429bd2886SAlan Wright 			return (NT_STATUS_NONE_MAPPED);
31529bd2886SAlan Wright 		}
31629bd2886SAlan Wright 	}
31729bd2886SAlan Wright 
31829bd2886SAlan Wright 	/* Group */
31929bd2886SAlan Wright 	if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
32029bd2886SAlan Wright 		sid = sd->sd_group;
32129bd2886SAlan Wright 		if (!smb_sid_isvalid(sid))
32229bd2886SAlan Wright 			return (NT_STATUS_INVALID_SID);
32329bd2886SAlan Wright 
32429bd2886SAlan Wright 		idtype = SMB_IDMAP_GROUP;
32529bd2886SAlan Wright 		idm_stat = smb_idmap_getid(sid, &fs_sd->sd_gid, &idtype);
32629bd2886SAlan Wright 		if (idm_stat != IDMAP_SUCCESS) {
32729bd2886SAlan Wright 			return (NT_STATUS_NONE_MAPPED);
32829bd2886SAlan Wright 		}
32929bd2886SAlan Wright 	}
33029bd2886SAlan Wright 
33129bd2886SAlan Wright 	/* DACL */
33229bd2886SAlan Wright 	if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) {
33329bd2886SAlan Wright 		if (sd->sd_control & SE_DACL_PRESENT) {
33429bd2886SAlan Wright 			status = smb_acl_to_zfs(sd->sd_dacl, flags,
33529bd2886SAlan Wright 			    SMB_DACL_SECINFO, &fs_sd->sd_zdacl);
33629bd2886SAlan Wright 			if (status != NT_STATUS_SUCCESS)
33729bd2886SAlan Wright 				return (status);
33829bd2886SAlan Wright 		}
33929bd2886SAlan Wright 		else
34029bd2886SAlan Wright 			return (NT_STATUS_INVALID_ACL);
34129bd2886SAlan Wright 	}
34229bd2886SAlan Wright 
34329bd2886SAlan Wright 	/* SACL */
34429bd2886SAlan Wright 	if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) {
34529bd2886SAlan Wright 		if (sd->sd_control & SE_SACL_PRESENT) {
34629bd2886SAlan Wright 			status = smb_acl_to_zfs(sd->sd_sacl, flags,
34729bd2886SAlan Wright 			    SMB_SACL_SECINFO, &fs_sd->sd_zsacl);
34829bd2886SAlan Wright 			if (status != NT_STATUS_SUCCESS) {
34929bd2886SAlan Wright 				return (status);
35029bd2886SAlan Wright 			}
35129bd2886SAlan Wright 		} else {
35229bd2886SAlan Wright 			return (NT_STATUS_INVALID_ACL);
35329bd2886SAlan Wright 		}
35429bd2886SAlan Wright 	}
35529bd2886SAlan Wright 
35629bd2886SAlan Wright 	return (status);
35729bd2886SAlan Wright }
35829bd2886SAlan Wright 
35929bd2886SAlan Wright /*
36029bd2886SAlan Wright  * smb_sd_fromfs
36129bd2886SAlan Wright  *
36229bd2886SAlan Wright  * Makes an Windows style security descriptor in absolute form
36329bd2886SAlan Wright  * based on the given filesystem security information.
36429bd2886SAlan Wright  *
36529bd2886SAlan Wright  * Should call smb_sd_term() for the returned sd to free allocated
36629bd2886SAlan Wright  * members.
36729bd2886SAlan Wright  */
368fe1c642dSBill Krier uint32_t
smb_sd_fromfs(smb_fssd_t * fs_sd,smb_sd_t * sd)36929bd2886SAlan Wright smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd)
37029bd2886SAlan Wright {
37129bd2886SAlan Wright 	uint32_t status = NT_STATUS_SUCCESS;
37229bd2886SAlan Wright 	smb_acl_t *acl = NULL;
37329bd2886SAlan Wright 	smb_sid_t *sid;
37429bd2886SAlan Wright 	idmap_stat idm_stat;
37529bd2886SAlan Wright 
37629bd2886SAlan Wright 	assert(fs_sd);
37729bd2886SAlan Wright 	assert(sd);
37829bd2886SAlan Wright 
37929bd2886SAlan Wright 	smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION);
38029bd2886SAlan Wright 
38129bd2886SAlan Wright 	/* Owner */
38229bd2886SAlan Wright 	if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
38329bd2886SAlan Wright 		idm_stat = smb_idmap_getsid(fs_sd->sd_uid,
38429bd2886SAlan Wright 		    SMB_IDMAP_USER, &sid);
38529bd2886SAlan Wright 
38629bd2886SAlan Wright 		if (idm_stat != IDMAP_SUCCESS) {
38729bd2886SAlan Wright 			smb_sd_term(sd);
38829bd2886SAlan Wright 			return (NT_STATUS_NONE_MAPPED);
38929bd2886SAlan Wright 		}
39029bd2886SAlan Wright 
39129bd2886SAlan Wright 		sd->sd_owner = sid;
39229bd2886SAlan Wright 	}
39329bd2886SAlan Wright 
39429bd2886SAlan Wright 	/* Group */
39529bd2886SAlan Wright 	if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
39629bd2886SAlan Wright 		idm_stat = smb_idmap_getsid(fs_sd->sd_gid,
39729bd2886SAlan Wright 		    SMB_IDMAP_GROUP, &sid);
39829bd2886SAlan Wright 
39929bd2886SAlan Wright 		if (idm_stat != IDMAP_SUCCESS) {
40029bd2886SAlan Wright 			smb_sd_term(sd);
40129bd2886SAlan Wright 			return (NT_STATUS_NONE_MAPPED);
40229bd2886SAlan Wright 		}
40329bd2886SAlan Wright 
40429bd2886SAlan Wright 		sd->sd_group = sid;
40529bd2886SAlan Wright 	}
40629bd2886SAlan Wright 
40729bd2886SAlan Wright 	/* DACL */
40829bd2886SAlan Wright 	if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) {
40929bd2886SAlan Wright 		if (fs_sd->sd_zdacl != NULL) {
410f96bd5c8SAlan Wright 			acl = smb_acl_from_zfs(fs_sd->sd_zdacl);
41129bd2886SAlan Wright 			if (acl == NULL) {
41229bd2886SAlan Wright 				smb_sd_term(sd);
41329bd2886SAlan Wright 				return (NT_STATUS_INTERNAL_ERROR);
41429bd2886SAlan Wright 			}
41529bd2886SAlan Wright 
41629bd2886SAlan Wright 			/*
41729bd2886SAlan Wright 			 * Need to sort the ACL before send it to Windows
41829bd2886SAlan Wright 			 * clients. Winodws GUI is sensitive about the order
41929bd2886SAlan Wright 			 * of ACEs.
42029bd2886SAlan Wright 			 */
42129bd2886SAlan Wright 			smb_acl_sort(acl);
42229bd2886SAlan Wright 			smb_sd_set_dacl(sd, acl, B_TRUE,
42329bd2886SAlan Wright 			    fs_sd->sd_zdacl->acl_flags);
42429bd2886SAlan Wright 		} else {
42529bd2886SAlan Wright 			smb_sd_set_dacl(sd, NULL, B_FALSE, 0);
42629bd2886SAlan Wright 		}
42729bd2886SAlan Wright 	}
42829bd2886SAlan Wright 
42929bd2886SAlan Wright 	/* SACL */
43029bd2886SAlan Wright 	if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) {
43129bd2886SAlan Wright 		if (fs_sd->sd_zsacl != NULL) {
432f96bd5c8SAlan Wright 			acl = smb_acl_from_zfs(fs_sd->sd_zsacl);
43329bd2886SAlan Wright 			if (acl == NULL) {
43429bd2886SAlan Wright 				smb_sd_term(sd);
43529bd2886SAlan Wright 				return (NT_STATUS_INTERNAL_ERROR);
43629bd2886SAlan Wright 			}
43729bd2886SAlan Wright 
43829bd2886SAlan Wright 			smb_sd_set_sacl(sd, acl, B_TRUE,
43929bd2886SAlan Wright 			    fs_sd->sd_zsacl->acl_flags);
44029bd2886SAlan Wright 		} else {
44129bd2886SAlan Wright 			smb_sd_set_sacl(sd, NULL, B_FALSE, 0);
44229bd2886SAlan Wright 		}
44329bd2886SAlan Wright 	}
44429bd2886SAlan Wright 
44529bd2886SAlan Wright 	return (status);
44629bd2886SAlan Wright }
44729bd2886SAlan Wright 
44829bd2886SAlan Wright static void
smb_sd_set_dacl(smb_sd_t * sd,smb_acl_t * acl,boolean_t present,int flags)44929bd2886SAlan Wright smb_sd_set_dacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags)
45029bd2886SAlan Wright {
45129bd2886SAlan Wright 	assert((sd->sd_control & SE_SELF_RELATIVE) == 0);
45229bd2886SAlan Wright 
45329bd2886SAlan Wright 	sd->sd_dacl = acl;
45429bd2886SAlan Wright 
45529bd2886SAlan Wright 	if (flags & ACL_DEFAULTED)
45629bd2886SAlan Wright 		sd->sd_control |= SE_DACL_DEFAULTED;
45729bd2886SAlan Wright 	if (flags & ACL_AUTO_INHERIT)
45829bd2886SAlan Wright 		sd->sd_control |= SE_DACL_AUTO_INHERITED;
45929bd2886SAlan Wright 	if (flags & ACL_PROTECTED)
46029bd2886SAlan Wright 		sd->sd_control |= SE_DACL_PROTECTED;
46129bd2886SAlan Wright 
46229bd2886SAlan Wright 	if (present)
46329bd2886SAlan Wright 		sd->sd_control |= SE_DACL_PRESENT;
46429bd2886SAlan Wright }
46529bd2886SAlan Wright 
46629bd2886SAlan Wright static void
smb_sd_set_sacl(smb_sd_t * sd,smb_acl_t * acl,boolean_t present,int flags)46729bd2886SAlan Wright smb_sd_set_sacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags)
46829bd2886SAlan Wright {
46929bd2886SAlan Wright 	assert((sd->sd_control & SE_SELF_RELATIVE) == 0);
47029bd2886SAlan Wright 
47129bd2886SAlan Wright 	sd->sd_sacl = acl;
47229bd2886SAlan Wright 
47329bd2886SAlan Wright 	if (flags & ACL_DEFAULTED)
47429bd2886SAlan Wright 		sd->sd_control |= SE_SACL_DEFAULTED;
47529bd2886SAlan Wright 	if (flags & ACL_AUTO_INHERIT)
47629bd2886SAlan Wright 		sd->sd_control |= SE_SACL_AUTO_INHERITED;
47729bd2886SAlan Wright 	if (flags & ACL_PROTECTED)
47829bd2886SAlan Wright 		sd->sd_control |= SE_SACL_PROTECTED;
47929bd2886SAlan Wright 
48029bd2886SAlan Wright 	if (present)
48129bd2886SAlan Wright 		sd->sd_control |= SE_SACL_PRESENT;
48229bd2886SAlan Wright }
48329bd2886SAlan Wright 
48429bd2886SAlan Wright /*
48529bd2886SAlan Wright  * smb_fssd_init
48629bd2886SAlan Wright  *
48729bd2886SAlan Wright  * Initializes the given FS SD structure.
48829bd2886SAlan Wright  */
48929bd2886SAlan Wright void
smb_fssd_init(smb_fssd_t * fs_sd,uint32_t secinfo,uint32_t flags)49029bd2886SAlan Wright smb_fssd_init(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags)
49129bd2886SAlan Wright {
49229bd2886SAlan Wright 	bzero(fs_sd, sizeof (smb_fssd_t));
49329bd2886SAlan Wright 	fs_sd->sd_secinfo = secinfo;
49429bd2886SAlan Wright 	fs_sd->sd_flags = flags;
49529bd2886SAlan Wright }
49629bd2886SAlan Wright 
49729bd2886SAlan Wright /*
49829bd2886SAlan Wright  * smb_fssd_term
49929bd2886SAlan Wright  *
50029bd2886SAlan Wright  * Frees allocated memory for acl fields.
50129bd2886SAlan Wright  */
50229bd2886SAlan Wright void
smb_fssd_term(smb_fssd_t * fs_sd)50329bd2886SAlan Wright smb_fssd_term(smb_fssd_t *fs_sd)
50429bd2886SAlan Wright {
50529bd2886SAlan Wright 	assert(fs_sd);
50629bd2886SAlan Wright 
50729bd2886SAlan Wright 	acl_free(fs_sd->sd_zdacl);
50829bd2886SAlan Wright 	acl_free(fs_sd->sd_zsacl);
50929bd2886SAlan Wright 
51029bd2886SAlan Wright 	bzero(fs_sd, sizeof (smb_fssd_t));
51129bd2886SAlan Wright }
512