1da6c28aamw/*
2da6c28aamw * CDDL HEADER START
3da6c28aamw *
4da6c28aamw * The contents of this file are subject to the terms of the
5da6c28aamw * Common Development and Distribution License (the "License").
6da6c28aamw * You may not use this file except in compliance with the License.
7da6c28aamw *
8da6c28aamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aamw * or http://www.opensolaris.org/os/licensing.
10da6c28aamw * See the License for the specific language governing permissions
11da6c28aamw * and limitations under the License.
12da6c28aamw *
13da6c28aamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aamw *
19da6c28aamw * CDDL HEADER END
20da6c28aamw */
21da6c28aamw/*
22f96bd5cAlan Wright * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23da6c28aamw * Use is subject to license terms.
24b819ceaGordon Ross *
25b819ceaGordon Ross * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
26da6c28aamw */
27da6c28aamw
289fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States#include <sys/sid.h>
29da6c28aamw#include <sys/acl.h>
3055bf511as#include <acl/acl_common.h>
316537f38as#include <smbsrv/smb_sid.h>
32da6c28aamw#include <smbsrv/smb_fsops.h>
33da6c28aamw#include <smbsrv/smb_idmap.h>
3455bf511as#include <smbsrv/smb_kproto.h>
35da6c28aamw
36da6c28aamw#define	ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE)
37da6c28aamw
38da6c28aamw#define	ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER)
39da6c28aamw#define	ZACE_IS_OWNGRP(zace) \
40da6c28aamw	((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP))
41da6c28aamw
42da6c28aamw#define	ZACE_IS_USER(zace) \
43da6c28aamw	(((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace)))
44da6c28aamw#define	ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP)
45da6c28aamw#define	ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE)
46da6c28aamw
47da6c28aamw#define	ZACE_IS_PROPAGATE(zace) \
48da6c28aamw	((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0)
49da6c28aamw
50da6c28aamw#define	ZACE_IS_CREATOR_OWNER(zace) \
51da6c28aamw	(ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID))
52da6c28aamw
53da6c28aamw#define	ZACE_IS_CREATOR_GROUP(zace) \
54da6c28aamw	(ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID))
55da6c28aamw
56da6c28aamw#define	ZACE_IS_CREATOR(zace) \
57da6c28aamw	(ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace))
58da6c28aamw
5955bf511as/*
6055bf511as * ACE groups within a DACL
6155bf511as *
6255bf511as * This is from lower to higher ACE order priority
6355bf511as */
6455bf511as#define	SMB_AG_START		0
6555bf511as#define	SMB_AG_ALW_INHRT	0
6655bf511as#define	SMB_AG_DNY_INHRT	1
6755bf511as#define	SMB_AG_ALW_DRCT		2
6855bf511as#define	SMB_AG_DNY_DRCT		3
6955bf511as#define	SMB_AG_NUM		4
70da6c28aamw
7155bf511as#define	DEFAULT_DACL_ACENUM	2
7255bf511as/*
7355bf511as * Default ACL:
7455bf511as *    owner: full access
7555bf511as *    SYSTEM: full access
7655bf511as */
77b819ceaGordon Ross#ifdef	_KERNEL
78adb064aToomas Soomestatic const ace_t default_dacl[DEFAULT_DACL_ACENUM] = {
7955bf511as	{ (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
8055bf511as	{ IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP,
8155bf511as	    ACE_ACCESS_ALLOWED_ACE_TYPE }
8255bf511as};
83b819ceaGordon Ross#endif	/* _KERNEL */
84da6c28aamw
8555bf511as/*
8655bf511as * Note:
8755bf511as *
8855bf511as * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format
8955bf511as * smb_fsacl_xxx functions work with acl_t which represents the Solaris native
9055bf511as * format
9155bf511as */
92da6c28aamw
93f96bd5cAlan Wrightstatic idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *);
94c8ec8eejose borregostatic acl_t *smb_fsacl_null_empty(boolean_t);
95b819ceaGordon Ross#ifdef	_KERNEL
9655bf511asstatic int smb_fsacl_inheritable(acl_t *, int);
979fb67eaafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic void smb_ace_inherit(ace_t *, ace_t *, int, uid_t, gid_t);
98b819ceaGordon Ross#endif	/* _KERNEL */
99b819ceaGordon Ross
10055bf511asstatic boolean_t smb_ace_isvalid(smb_ace_t *, int);
10155bf511asstatic uint16_t smb_ace_len(smb_ace_t *);
10255bf511asstatic uint32_t smb_ace_mask_g2s(uint32_t);
103c8ec8eejose borregostatic uint16_t smb_ace_flags_tozfs(uint8_t);
10455bf511asstatic uint8_t smb_ace_flags_fromzfs(uint16_t);
105f96bd5cAlan Wrightstatic boolean_t smb_ace_wellknown_update(const char *, ace_t *);
106da6c28aamw
10755bf511assmb_acl_t *
10855bf511assmb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt)
10955bf511as{
11055bf511as	smb_acl_t *acl;
11155bf511as	int size;
112da6c28aamw
11355bf511as	size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t));
11455bf511as	acl = kmem_zalloc(size, KM_SLEEP);
11555bf511as	acl->sl_revision = revision;
11655bf511as	acl->sl_bsize = bsize;
11755bf511as	acl->sl_acecnt = acecnt;
11855bf511as	acl->sl_aces = (smb_ace_t *)(acl + 1);
119da6c28aamw
12055bf511as	list_create(&acl->sl_sorted, sizeof (smb_ace_t),
12155bf511as	    offsetof(smb_ace_t, se_sln));
12255bf511as	return (acl);
123da6c28aamw}
124da6c28aamw
12555bf511asvoid
12655bf511assmb_acl_free(smb_acl_t *acl)
127da6c28aamw{
12855bf511as	int i, size;
12955bf511as	void *ace;
130da6c28aamw
13155bf511as	if (acl == NULL)
13255bf511as		return;
133da6c28aamw
1346537f38as	for (i = 0; i < acl->sl_acecnt; i++)
1356537f38as		smb_sid_free(acl->sl_aces[i].se_sid);
136da6c28aamw
13755bf511as	while ((ace = list_head(&acl->sl_sorted)) != NULL)
13855bf511as		list_remove(&acl->sl_sorted, ace);
13955bf511as	list_destroy(&acl->sl_sorted);
140da6c28aamw
14155bf511as	size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t));
14255bf511as	kmem_free(acl, size);
143da6c28aamw}
144da6c28aamw
14555bf511as/*
14655bf511as * smb_acl_len
14755bf511as *
14855bf511as * Returns the size of given ACL in bytes. Note that this
14955bf511as * is not an in-memory size, it's the ACL's size as it would
15055bf511as * appear on the wire
15155bf511as */
152da6c28aamwuint16_t
153da6c28aamwsmb_acl_len(smb_acl_t *acl)
154da6c28aamw{
155c8ec8eejose borrego	return ((acl) ? acl->sl_bsize : 0);
156da6c28aamw}
157da6c28aamw
15855bf511asboolean_t
15955bf511assmb_acl_isvalid(smb_acl_t *acl, int which_acl)
160da6c28aamw{
16155bf511as	int i;
162da6c28aamw
16355bf511as	if (acl->sl_bsize < SMB_ACL_HDRSIZE)
16455bf511as		return (B_FALSE);
16555bf511as
16655bf511as	if (acl->sl_revision != ACL_REVISION) {
16755bf511as		/*
16855bf511as		 * we are rejecting ACLs with object-specific ACEs for now
16955bf511as		 */
17055bf511as		return (B_FALSE);
171da6c28aamw	}
172da6c28aamw
17355bf511as	for (i = 0; i < acl->sl_acecnt; i++) {
17455bf511as		if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl))
17555bf511as			return (B_FALSE);
17655bf511as	}
177da6c28aamw
17855bf511as	return (B_TRUE);
179da6c28aamw}
180da6c28aamw
181da6c28aamw/*
18255bf511as * smb_acl_sort
183da6c28aamw *
18455bf511as * Sorts the given ACL in place if it needs to be sorted.
185da6c28aamw *
186da6c28aamw * The following is an excerpt from MSDN website.
187da6c28aamw *
188da6c28aamw * Order of ACEs in a DACL
189da6c28aamw *
190da6c28aamw * For Windows NT versions 4.0 and earlier, the preferred order of ACEs
191da6c28aamw * is simple: In a DACL, all access-denied ACEs should precede any
192da6c28aamw * access-allowed ACEs.
193da6c28aamw *
194da6c28aamw * For Windows 2000 or later, the proper order of ACEs is more complicated
195da6c28aamw * because of the introduction of object-specific ACEs and automatic
196da6c28aamw * inheritance.
197da6c28aamw *
198da6c28aamw * The following describes the preferred order:
199da6c28aamw *
200da6c28aamw * To ensure that noninherited ACEs have precedence over inherited ACEs,
201da6c28aamw * place all noninherited ACEs in a group before any inherited ACEs. This
202da6c28aamw * ordering ensures, for example, that a noninherited access-denied ACE
203da6c28aamw * is enforced regardless of any inherited ACE that allows access.
204da6c28aamw * Within the groups of noninherited ACEs and inherited ACEs, order ACEs
205da6c28aamw * according to ACE type, as the following shows:
206da6c28aamw * 	. Access-denied ACEs that apply to the object itself
207da6c28aamw * 	. Access-denied ACEs that apply to a subobject of the
208