xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_acl.c (revision 5331:3047ad28a67b)
1*5331Samw /*
2*5331Samw  * CDDL HEADER START
3*5331Samw  *
4*5331Samw  * The contents of this file are subject to the terms of the
5*5331Samw  * Common Development and Distribution License (the "License").
6*5331Samw  * You may not use this file except in compliance with the License.
7*5331Samw  *
8*5331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5331Samw  * or http://www.opensolaris.org/os/licensing.
10*5331Samw  * See the License for the specific language governing permissions
11*5331Samw  * and limitations under the License.
12*5331Samw  *
13*5331Samw  * When distributing Covered Code, include this CDDL HEADER in each
14*5331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5331Samw  * If applicable, add the following below this CDDL HEADER, with the
16*5331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
17*5331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5331Samw  *
19*5331Samw  * CDDL HEADER END
20*5331Samw  */
21*5331Samw /*
22*5331Samw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5331Samw  * Use is subject to license terms.
24*5331Samw  */
25*5331Samw 
26*5331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5331Samw 
28*5331Samw /*
29*5331Samw  * Platform SDK: Security
30*5331Samw  *
31*5331Samw  * ACE Inheritance Rules
32*5331Samw  *
33*5331Samw  * The system propagates inheritable ACEs to child objects according to a
34*5331Samw  * set of inheritance rules. The system places inherited ACEs in the child's
35*5331Samw  * DACL according to the preferred order of ACEs in a DACL. For Windows
36*5331Samw  * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs.
37*5331Samw  *
38*5331Samw  * The following table shows the ACEs inherited by container and noncontainer
39*5331Samw  * child objects for different combinations of inheritance flags. These
40*5331Samw  * inheritance rules work the same for both DACLs and SACLs.
41*5331Samw  *
42*5331Samw  * Parent ACE type 				Effect on Child ACL
43*5331Samw  * -----------------------		-------------------
44*5331Samw  * OBJECT_INHERIT_ACE only 		Noncontainer child objects:
45*5331Samw  *					Inherited as an effective ACE.
46*5331Samw  *					Container child objects:
47*5331Samw  *					Containers inherit an inherit-only ACE
48*5331Samw  *					unless the NO_PROPAGATE_INHERIT_ACE bit
49*5331Samw  *					flag is also set.
50*5331Samw  *
51*5331Samw  * CONTAINER_INHERIT_ACE only 		Noncontainer child objects:
52*5331Samw  *					No effect on the child object.
53*5331Samw  *					Container child objects:
54*5331Samw  *				The child object inherits an effective ACE.
55*5331Samw  *				The inherited ACE is inheritable unless the
56*5331Samw  *				NO_PROPAGATE_INHERIT_ACE bit flag is also set.
57*5331Samw  *
58*5331Samw  * CONTAINER_INHERIT_ACE and
59*5331Samw  * OBJECT_INHERIT_ACE 			Noncontainer child objects:
60*5331Samw  *					Inherited as an effective ACE.
61*5331Samw  *					Container child objects:
62*5331Samw  *				The child object inherits an effective ACE.
63*5331Samw  *				The inherited ACE is inheritable unless the
64*5331Samw  *				NO_PROPAGATE_INHERIT_ACE bit flag is also set
65*5331Samw  *
66*5331Samw  * No inheritance flags set 	No effect on child container or noncontainer
67*5331Samw  *				objects.
68*5331Samw  *
69*5331Samw  * If an inherited ACE is an effective ACE for the child object, the system
70*5331Samw  * maps any generic rights to the specific rights for the child object.
71*5331Samw  * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the
72*5331Samw  * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic
73*5331Samw  * rights or generic SIDs are left unchanged so that they can be mapped
74*5331Samw  * appropriately when the ACE is inherited by the next generation of child
75*5331Samw  * objects.
76*5331Samw  *
77*5331Samw  * For a case in which a container object inherits an ACE that is both
78*5331Samw  * effective on the container and inheritable by its descendants, the
79*5331Samw  * container may inherit two ACEs. This occurs if the inheritable ACE
80*5331Samw  * contains generic information. The container inherits an inherit-only
81*5331Samw  * ACE containing the generic information and an effective-only ACE in
82*5331Samw  * which the generic information has been mapped.
83*5331Samw  */
84*5331Samw 
85*5331Samw #include <sys/acl.h>
86*5331Samw #include <smbsrv/smb_incl.h>
87*5331Samw #include <smbsrv/ntsid.h>
88*5331Samw #include <smbsrv/smb_fsops.h>
89*5331Samw #include <smbsrv/smb_idmap.h>
90*5331Samw 
91*5331Samw #define	ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE)
92*5331Samw 
93*5331Samw #define	ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER)
94*5331Samw #define	ZACE_IS_OWNGRP(zace) \
95*5331Samw 	((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP))
96*5331Samw 
97*5331Samw #define	ZACE_IS_USER(zace) \
98*5331Samw 	(((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace)))
99*5331Samw #define	ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP)
100*5331Samw #define	ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE)
101*5331Samw 
102*5331Samw #define	ZACE_IS_PROPAGATE(zace) \
103*5331Samw 	((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0)
104*5331Samw 
105*5331Samw #define	ZACE_IS_CREATOR_OWNER(zace) \
106*5331Samw 	(ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID))
107*5331Samw 
108*5331Samw #define	ZACE_IS_CREATOR_GROUP(zace) \
109*5331Samw 	(ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID))
110*5331Samw 
111*5331Samw #define	ZACE_IS_CREATOR(zace) \
112*5331Samw 	(ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace))
113*5331Samw 
114*5331Samw static int smb_ace_isvalid(smb_ace_hdr_t *ace, int which_acl);
115*5331Samw static int smb_ace_append_generic(smb_acl_t *acl, void *generic_ace);
116*5331Samw 
117*5331Samw static int smb_ace_common_add(
118*5331Samw     smb_acl_t *acl,
119*5331Samw     uint8_t type,
120*5331Samw     uint8_t flags,
121*5331Samw     uint32_t access_mask,
122*5331Samw     nt_sid_t *sid);
123*5331Samw 
124*5331Samw static void smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir);
125*5331Samw static uint16_t smb_ace_flags_tozfs(uint8_t c_flags, int isdir);
126*5331Samw static uint8_t smb_ace_flags_fromzfs(uint16_t z_flags);
127*5331Samw static void smb_acl_init(smb_acl_t *acl, uint16_t size, uint8_t rev);
128*5331Samw 
129*5331Samw static int
130*5331Samw smb_ace_isvalid(smb_ace_hdr_t *ace, int which_acl)
131*5331Samw {
132*5331Samw 	uint16_t min_len;
133*5331Samw 	smb_ace_t *p;
134*5331Samw 
135*5331Samw 	min_len = sizeof (smb_ace_hdr_t);
136*5331Samw 
137*5331Samw 	if (ace->se_size < min_len)
138*5331Samw 		return (0);
139*5331Samw 
140*5331Samw 	if (smb_ace_is_access(ace->se_type) &&
141*5331Samw 	    (which_acl != SMB_DACL_SECINFO)) {
142*5331Samw 		return (0);
143*5331Samw 	}
144*5331Samw 
145*5331Samw 	if (smb_ace_is_audit(ace->se_type) &&
146*5331Samw 	    (which_acl != SMB_SACL_SECINFO)) {
147*5331Samw 		return (0);
148*5331Samw 	}
149*5331Samw 
150*5331Samw 	if (smb_ace_is_generic(ace->se_type)) {
151*5331Samw 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
152*5331Samw 		p = (smb_ace_t *)ace;
153*5331Samw 
154*5331Samw 		if (ace->se_size < sizeof (*p))
155*5331Samw 			return (0);	/* won't handle empty SubAuthority[] */
156*5331Samw 
157*5331Samw 		if (nt_sid_is_valid(&p->se_sid) == 0)
158*5331Samw 			return (0);
159*5331Samw 
160*5331Samw 		min_len += sizeof (p->se_mask);
161*5331Samw 		min_len += nt_sid_length(&p->se_sid);
162*5331Samw 
163*5331Samw 		if (ace->se_size < min_len)
164*5331Samw 			return (0);
165*5331Samw 	}
166*5331Samw 
167*5331Samw 	/*
168*5331Samw 	 * XXX object-specific ACE validation will be added later.
169*5331Samw 	 */
170*5331Samw 	return (1);
171*5331Samw }
172*5331Samw 
173*5331Samw int
174*5331Samw smb_acl_isvalid(smb_acl_t *acl, int which_acl)
175*5331Samw {
176*5331Samw 	uint16_t	min_len;
177*5331Samw 	unsigned char	*scan;
178*5331Samw 	unsigned char	*scan_end;
179*5331Samw 	smb_ace_hdr_t	*ace;
180*5331Samw 	uint16_t	count = 0;
181*5331Samw 
182*5331Samw 	min_len = sizeof (smb_acl_t);
183*5331Samw 
184*5331Samw 	if (acl->sl_size < min_len)
185*5331Samw 		return (0);
186*5331Samw 
187*5331Samw 	if (acl->sl_revision != ACL_REVISION) {
188*5331Samw 		/*
189*5331Samw 		 * XXX we are rejecting ACLs with object-specific ACEs for now
190*5331Samw 		 */
191*5331Samw 		return (0);
192*5331Samw 	}
193*5331Samw 
194*5331Samw 	scan = (unsigned char *) &acl[0];
195*5331Samw 	scan_end = scan + acl->sl_size;
196*5331Samw 	scan = (unsigned char *) &acl[1];	/* skip Acl header */
197*5331Samw 
198*5331Samw 	while (count < acl->sl_acecnt && scan < scan_end) {
199*5331Samw 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
200*5331Samw 		ace = (smb_ace_hdr_t *)scan;
201*5331Samw 
202*5331Samw 		if (scan + sizeof (smb_ace_hdr_t) >= scan_end)
203*5331Samw 			return (0);
204*5331Samw 
205*5331Samw 		if (scan + ace->se_size > scan_end)
206*5331Samw 			return (0);	/* overflow */
207*5331Samw 
208*5331Samw 		if (!smb_ace_isvalid(ace, which_acl))
209*5331Samw 			return (0);
210*5331Samw 
211*5331Samw 		scan += ace->se_size;
212*5331Samw 		count++;
213*5331Samw 	}
214*5331Samw 
215*5331Samw 	return (1);
216*5331Samw }
217*5331Samw 
218*5331Samw 
219*5331Samw static void
220*5331Samw smb_acl_init(smb_acl_t *acl, uint16_t size, uint8_t rev)
221*5331Samw {
222*5331Samw 	bzero(acl, size);
223*5331Samw 	acl->sl_revision = rev;
224*5331Samw 	acl->sl_size = size;
225*5331Samw }
226*5331Samw 
227*5331Samw uint16_t
228*5331Samw smb_acl_len(smb_acl_t *acl)
229*5331Samw {
230*5331Samw 	smb_ace_hdr_t *ace;
231*5331Samw 	unsigned char *scan_beg;
232*5331Samw 	unsigned char *scan_end;
233*5331Samw 	unsigned char *scan;
234*5331Samw 	uint16_t length;
235*5331Samw 	uint16_t count;
236*5331Samw 
237*5331Samw 	scan_beg = (unsigned char *) &acl[0];
238*5331Samw 	scan_end = scan_beg + acl->sl_size;
239*5331Samw 	scan = (unsigned char *) &acl[1];
240*5331Samw 	length   = sizeof (smb_acl_t);
241*5331Samw 	count    = 0;
242*5331Samw 
243*5331Samw 	while ((count < acl->sl_acecnt) && (scan < scan_end)) {
244*5331Samw 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
245*5331Samw 		ace = (smb_ace_hdr_t *)scan;
246*5331Samw 		length += ace->se_size;
247*5331Samw 		scan += ace->se_size;
248*5331Samw 		count++;
249*5331Samw 	}
250*5331Samw 
251*5331Samw 	return (length);
252*5331Samw }
253*5331Samw 
254*5331Samw /*
255*5331Samw  * Append the generic ACE to the ACL. This is used to put any
256*5331Samw  * kind of ACE on the ACL so the argument is declared as a void*. We cast it
257*5331Samw  * to an ACCESS_ALLOWED_ACE just because there is no sense of a generic ACE.
258*5331Samw  */
259*5331Samw static int
260*5331Samw smb_ace_append_generic(smb_acl_t *acl, void *generic_ace)
261*5331Samw {
262*5331Samw 	smb_ace_t *ace = (smb_ace_t *)generic_ace;
263*5331Samw 	uint16_t acl_len = smb_acl_len(acl);
264*5331Samw 	unsigned char *scan = (uchar_t *)acl;
265*5331Samw 
266*5331Samw 	if ((acl_len + ace->se_header.se_size) > acl->sl_size) {
267*5331Samw 		/* no room in the acl for this ace */
268*5331Samw 		return (0);
269*5331Samw 	}
270*5331Samw 
271*5331Samw 	/* append the ace to the acl and inc ace count */
272*5331Samw 	bcopy(ace, &scan[acl_len], ace->se_header.se_size);
273*5331Samw 	acl->sl_acecnt++;
274*5331Samw 
275*5331Samw 	return (1);
276*5331Samw }
277*5331Samw 
278*5331Samw /*
279*5331Samw  * Helper for the ACL sort routine
280*5331Samw  */
281*5331Samw typedef struct smb_ace_entry {
282*5331Samw 	smb_ace_t	*e_ace;
283*5331Samw 	list_node_t	e_node;
284*5331Samw } smb_ace_entry_t;
285*5331Samw 
286*5331Samw /*
287*5331Samw  * ACE groups within a DACL
288*5331Samw  *
289*5331Samw  * This is from lower to higher ACE order priority
290*5331Samw  */
291*5331Samw #define	SMB_AG_START		0
292*5331Samw #define	SMB_AG_ALW_INHRT	0
293*5331Samw #define	SMB_AG_DNY_INHRT	1
294*5331Samw #define	SMB_AG_ALW_DRCT		2
295*5331Samw #define	SMB_AG_DNY_DRCT		3
296*5331Samw #define	SMB_AG_NUM		4
297*5331Samw 
298*5331Samw /*
299*5331Samw  * smb_acl_do_sort
300*5331Samw  *
301*5331Samw  * Sorts the given ACL, acl, and returns the result
302*5331Samw  * in a newly allocated memory.
303*5331Samw  *
304*5331Samw  * The following is an excerpt from MSDN website.
305*5331Samw  *
306*5331Samw  * Order of ACEs in a DACL
307*5331Samw  *
308*5331Samw  * For Windows NT versions 4.0 and earlier, the preferred order of ACEs
309*5331Samw  * is simple: In a DACL, all access-denied ACEs should precede any
310*5331Samw  * access-allowed ACEs.
311*5331Samw  *
312*5331Samw  * For Windows 2000 or later, the proper order of ACEs is more complicated
313*5331Samw  * because of the introduction of object-specific ACEs and automatic
314*5331Samw  * inheritance.
315*5331Samw  *
316*5331Samw  * The following describes the preferred order:
317*5331Samw  *
318*5331Samw  * To ensure that noninherited ACEs have precedence over inherited ACEs,
319*5331Samw  * place all noninherited ACEs in a group before any inherited ACEs. This
320*5331Samw  * ordering ensures, for example, that a noninherited access-denied ACE
321*5331Samw  * is enforced regardless of any inherited ACE that allows access.
322*5331Samw  * Within the groups of noninherited ACEs and inherited ACEs, order ACEs
323*5331Samw  * according to ACE type, as the following shows:
324*5331Samw  * 	. Access-denied ACEs that apply to the object itself
325*5331Samw  * 	. Access-denied ACEs that apply to a subobject of the
326*5331Samw  *	  object, such as a property set or property
327*5331Samw  * 	. Access-allowed ACEs that apply to the object itself
328*5331Samw  * 	. Access-allowed ACEs that apply to a subobject of the object
329*5331Samw  *
330*5331Samw  * Of course, not all ACE types are required in an ACL.
331*5331Samw  */
332*5331Samw static smb_acl_t *
333*5331Samw smb_acl_do_sort(smb_acl_t *acl, list_t *ace_grps)
334*5331Samw {
335*5331Samw 	smb_acl_t *sorted_acl;
336*5331Samw 	smb_ace_entry_t *nae;
337*5331Samw 	int i;
338*5331Samw 
339*5331Samw 	sorted_acl = kmem_alloc(acl->sl_size, KM_SLEEP);
340*5331Samw 	*sorted_acl = *acl;
341*5331Samw 
342*5331Samw 	/* start with no ACE in the sorted ACL */
343*5331Samw 	sorted_acl->sl_acecnt = 0;
344*5331Samw 
345*5331Samw 	/*
346*5331Samw 	 * start with highest priority ACE group and append
347*5331Samw 	 * the ACEs to the ACL.
348*5331Samw 	 */
349*5331Samw 	for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) {
350*5331Samw 		nae = list_head(&ace_grps[i]);
351*5331Samw 		while (nae) {
352*5331Samw 			if (!smb_ace_append_generic(sorted_acl, nae->e_ace)) {
353*5331Samw 				kmem_free(sorted_acl, acl->sl_size);
354*5331Samw 				return (NULL);
355*5331Samw 			}
356*5331Samw 			nae = list_next(&ace_grps[i], nae);
357*5331Samw 		}
358*5331Samw 	}
359*5331Samw 
360*5331Samw 	return (sorted_acl);
361*5331Samw }
362*5331Samw 
363*5331Samw /*
364*5331Samw  * smb_acl_need_sort
365*5331Samw  *
366*5331Samw  * Here is the desired ACE order
367*5331Samw  *
368*5331Samw  * deny-direct, allow-direct, deny-inherited, allow-inherited
369*5331Samw  *
370*5331Samw  * If any ace has been encountered which belongs to a group
371*5331Samw  * with lower priority of the specified ace_grp then the acl
372*5331Samw  * should be sorted.
373*5331Samw  */
374*5331Samw static int
375*5331Samw smb_acl_need_sort(list_t *ace_grps, int ace_grp)
376*5331Samw {
377*5331Samw 	int i;
378*5331Samw 
379*5331Samw 	for (i = SMB_AG_START; i < ace_grp; i++)
380*5331Samw 		if (!list_is_empty(&ace_grps[i]))
381*5331Samw 			return (1);
382*5331Samw 
383*5331Samw 	return (0);
384*5331Samw }
385*5331Samw 
386*5331Samw /*
387*5331Samw  * smb_acl_sort
388*5331Samw  *
389*5331Samw  * Returns NULL upon failure.
390*5331Samw  * Returns pointer to the passed (original) acl if no sort is required.
391*5331Samw  * Returns pointer to a new acl upon successful sort in which case the
392*5331Samw  * caller is responsible for freeing the allocated memory.
393*5331Samw  */
394*5331Samw smb_acl_t *
395*5331Samw smb_acl_sort(smb_acl_t *acl)
396*5331Samw {
397*5331Samw 	smb_acl_t *sorted_acl;
398*5331Samw 	smb_ace_t *ace;
399*5331Samw 	smb_ace_entry_t *ace_list;
400*5331Samw 	int ace_list_size;
401*5331Samw 	list_t ace_grps[SMB_AG_NUM];
402*5331Samw 	int ag;
403*5331Samw 	int do_sort = 0;
404*5331Samw 	uint16_t i;
405*5331Samw 	uint8_t ace_flags;
406*5331Samw 
407*5331Samw 	ASSERT(acl);
408*5331Samw 
409*5331Samw 	if (acl->sl_acecnt == 0) {
410*5331Samw 		/*
411*5331Samw 		 * ACL with no entry is a valid ACL and it means
412*5331Samw 		 * no access for anybody.
413*5331Samw 		 */
414*5331Samw 		return (acl);
415*5331Samw 	}
416*5331Samw 
417*5331Samw 	for (i = SMB_AG_START; i < SMB_AG_NUM; i++) {
418*5331Samw 		list_create(&ace_grps[i], sizeof (smb_ace_entry_t),
419*5331Samw 		    offsetof(smb_ace_entry_t, e_node));
420*5331Samw 	}
421*5331Samw 
422*5331Samw 	/*
423*5331Samw 	 * Allocate the helper entries to group the ACEs based on
424*5331Samw 	 * the desired priorities.
425*5331Samw 	 */
426*5331Samw 	ace_list_size = sizeof (smb_ace_entry_t) * acl->sl_acecnt;
427*5331Samw 	ace_list = kmem_alloc(ace_list_size, KM_SLEEP);
428*5331Samw 
429*5331Samw 	for (i = 0; i < acl->sl_acecnt; ++i) {
430*5331Samw 		ace_list[i].e_ace = smb_ace_get(acl, i);
431*5331Samw 		ace = ace_list[i].e_ace;
432*5331Samw 		ASSERT(ace);
433*5331Samw 
434*5331Samw 		ace_flags = ace->se_header.se_flags;
435*5331Samw 
436*5331Samw 		switch (ace->se_header.se_type) {
437*5331Samw 		case ACCESS_DENIED_ACE_TYPE:
438*5331Samw 			if (ace_flags & INHERITED_ACE) {
439*5331Samw 				ag = SMB_AG_DNY_INHRT;
440*5331Samw 				do_sort |= smb_acl_need_sort(ace_grps, ag);
441*5331Samw 			} else {
442*5331Samw 				ag = SMB_AG_DNY_DRCT;
443*5331Samw 				do_sort |= smb_acl_need_sort(ace_grps, ag);
444*5331Samw 			}
445*5331Samw 			break;
446*5331Samw 
447*5331Samw 		case ACCESS_ALLOWED_ACE_TYPE:
448*5331Samw 			if (ace_flags & INHERITED_ACE) {
449*5331Samw 				ag = SMB_AG_ALW_INHRT;
450*5331Samw 			} else {
451*5331Samw 				ag = SMB_AG_ALW_DRCT;
452*5331Samw 				do_sort |= smb_acl_need_sort(ace_grps, ag);
453*5331Samw 			}
454*5331Samw 			break;
455*5331Samw 
456*5331Samw 		default:
457*5331Samw 			/*
458*5331Samw 			 * This is the lowest priority group so we put
459*5331Samw 			 * evertything unknown here.
460*5331Samw 			 */
461*5331Samw 			ag = SMB_AG_ALW_INHRT;
462*5331Samw 			break;
463*5331Samw 		}
464*5331Samw 
465*5331Samw 		/* Put the element on the appropriate list */
466*5331Samw 		list_insert_tail(&ace_grps[ag], &ace_list[i]);
467*5331Samw 	}
468*5331Samw 
469*5331Samw 	if (do_sort)
470*5331Samw 		sorted_acl = smb_acl_do_sort(acl, ace_grps);
471*5331Samw 	else
472*5331Samw 		sorted_acl = acl;
473*5331Samw 
474*5331Samw 	for (i = SMB_AG_START; i < SMB_AG_NUM; i++) {
475*5331Samw 		void *ent;
476*5331Samw 		list_t *alist = &ace_grps[i];
477*5331Samw 
478*5331Samw 		while ((ent = list_head(alist)) != NULL)
479*5331Samw 			list_remove(alist, ent);
480*5331Samw 		list_destroy(alist);
481*5331Samw 	}
482*5331Samw 
483*5331Samw 	kmem_free(ace_list, ace_list_size);
484*5331Samw 
485*5331Samw 	return (sorted_acl);
486*5331Samw }
487*5331Samw 
488*5331Samw static int
489*5331Samw smb_ace_common_add(
490*5331Samw     smb_acl_t *acl,
491*5331Samw     uint8_t type,
492*5331Samw     uint8_t flags,
493*5331Samw     uint32_t access_mask,
494*5331Samw     nt_sid_t *sid)
495*5331Samw {
496*5331Samw 	smb_ace_t *ace;
497*5331Samw 	unsigned char *scan = (unsigned char *) acl;
498*5331Samw 	uint16_t used = smb_acl_len(acl);
499*5331Samw 	uint16_t sid_len = nt_sid_length(sid);
500*5331Samw 	uint16_t size;
501*5331Samw 
502*5331Samw 	size = sizeof (ace->se_header) + sizeof (ace->se_mask) + sid_len;
503*5331Samw 
504*5331Samw 	if (size + used > acl->sl_size) {
505*5331Samw 		/* won't fit */
506*5331Samw 		return (0);
507*5331Samw 	}
508*5331Samw 
509*5331Samw 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
510*5331Samw 	ace = (smb_ace_t *)&scan[used];
511*5331Samw 
512*5331Samw 	ace->se_header.se_type  = type;
513*5331Samw 	ace->se_header.se_flags = flags;
514*5331Samw 	ace->se_header.se_size  = size;
515*5331Samw 	ace->se_mask = access_mask;
516*5331Samw 	bcopy(sid, &ace->se_sid, sid_len);
517*5331Samw 
518*5331Samw 	acl->sl_acecnt++;
519*5331Samw 
520*5331Samw 	return (1);
521*5331Samw }
522*5331Samw 
523*5331Samw smb_ace_t *
524*5331Samw smb_ace_get(smb_acl_t *acl, uint16_t idx)
525*5331Samw {
526*5331Samw 	smb_ace_t *ace;
527*5331Samw 	unsigned char *scan_beg = (unsigned char *) &acl[0];
528*5331Samw 	unsigned char *scan_end = scan_beg + acl->sl_size;
529*5331Samw 	unsigned char *scan = (unsigned char *) &acl[1];
530*5331Samw 	uint16_t count = 0;
531*5331Samw 
532*5331Samw 	if (idx >= acl->sl_acecnt)
533*5331Samw 		return (NULL);
534*5331Samw 
535*5331Samw 	while (count <= idx && scan < scan_end) {
536*5331Samw 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
537*5331Samw 		ace = (smb_ace_t *)scan;
538*5331Samw 
539*5331Samw 		if (count == idx) {
540*5331Samw 			return (ace);
541*5331Samw 		}
542*5331Samw 
543*5331Samw 		scan += ace->se_header.se_size;
544*5331Samw 		count++;
545*5331Samw 	}
546*5331Samw 
547*5331Samw 	return (NULL);
548*5331Samw }
549*5331Samw 
550*5331Samw int
551*5331Samw smb_acl_copy(uint16_t buflen, smb_acl_t *dst_acl, smb_acl_t *src_acl)
552*5331Samw {
553*5331Samw 	smb_ace_hdr_t *dst_ace;
554*5331Samw 	smb_ace_hdr_t *src_ace;
555*5331Samw 	unsigned char *scan = (unsigned char *) &src_acl[1];
556*5331Samw 	unsigned char *dest_beg = (unsigned char *) &dst_acl[0];
557*5331Samw 	unsigned char *dest_end;
558*5331Samw 	unsigned char *dest = (unsigned char *) &dst_acl[1];
559*5331Samw 	uint16_t count = 0;
560*5331Samw 	uint16_t n_bytes;
561*5331Samw 
562*5331Samw 	n_bytes = smb_acl_len(src_acl);
563*5331Samw 	if (n_bytes > buflen)
564*5331Samw 		return (0);
565*5331Samw 
566*5331Samw 	dest_end = dest_beg + n_bytes;
567*5331Samw 
568*5331Samw 	dst_acl->sl_revision = src_acl->sl_revision;
569*5331Samw 	dst_acl->sl_sbz1 = 0;
570*5331Samw 	dst_acl->sl_size = n_bytes;
571*5331Samw 	dst_acl->sl_acecnt = 0;
572*5331Samw 	dst_acl->sl_sbz2 = 0;
573*5331Samw 
574*5331Samw 	while (count < src_acl->sl_acecnt && dest < dest_end) {
575*5331Samw 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
576*5331Samw 		src_ace = (smb_ace_hdr_t *)scan;
577*5331Samw 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
578*5331Samw 		dst_ace = (smb_ace_hdr_t *)dest;
579*5331Samw 		bcopy(src_ace, dst_ace, src_ace->se_size);
580*5331Samw 		dest += dst_ace->se_size;
581*5331Samw 		dst_acl->sl_acecnt++;
582*5331Samw 		scan += src_ace->se_size;
583*5331Samw 		count++;
584*5331Samw 	}
585*5331Samw 
586*5331Samw 	/*LINTED E_PTRDIFF_OVERFLOW*/
587*5331Samw 	return (dest - dest_beg);
588*5331Samw }
589*5331Samw 
590*5331Samw /*
591*5331Samw  * smb_ace_len
592*5331Samw  *
593*5331Samw  * Returns the length of an ACE with the given SID
594*5331Samw  *
595*5331Samw  * struct smb_ace {
596*5331Samw  *	smb_ace_hdr_t se_header;
597*5331Samw  *	uint32_t se_mask;
598*5331Samw  *	nt_sid_t se_sid;
599*5331Samw  * };
600*5331Samw  */
601*5331Samw uint16_t
602*5331Samw smb_ace_len(nt_sid_t *sid)
603*5331Samw {
604*5331Samw 	ASSERT(sid);
605*5331Samw 
606*5331Samw 	return (sizeof (smb_ace_hdr_t)
607*5331Samw 	    + sizeof (uint32_t) + nt_sid_length(sid));
608*5331Samw }
609*5331Samw 
610*5331Samw /*
611*5331Samw  * smb_ace_mask_g2s
612*5331Samw  *
613*5331Samw  * Converts generic access bits in the given mask (if any)
614*5331Samw  * to file specific bits. Generic access masks shouldn't be
615*5331Samw  * stored in filesystem ACEs.
616*5331Samw  */
617*5331Samw uint32_t
618*5331Samw smb_ace_mask_g2s(DWORD mask)
619*5331Samw {
620*5331Samw 	if (mask & GENERIC_ALL) {
621*5331Samw 		mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE
622*5331Samw 		    | GENERIC_EXECUTE);
623*5331Samw 
624*5331Samw 		mask |= FILE_ALL_ACCESS;
625*5331Samw 		return (mask);
626*5331Samw 	}
627*5331Samw 
628*5331Samw 	if (mask & GENERIC_READ) {
629*5331Samw 		mask &= ~GENERIC_READ;
630*5331Samw 		mask |= FILE_GENERIC_READ;
631*5331Samw 	}
632*5331Samw 
633*5331Samw 	if (mask & GENERIC_WRITE) {
634*5331Samw 		mask &= ~GENERIC_WRITE;
635*5331Samw 		mask |= FILE_GENERIC_WRITE;
636*5331Samw 	}
637*5331Samw 
638*5331Samw 	if (mask & GENERIC_EXECUTE) {
639*5331Samw 		mask &= ~GENERIC_EXECUTE;
640*5331Samw 		mask |= FILE_GENERIC_EXECUTE;
641*5331Samw 	}
642*5331Samw 
643*5331Samw 	return (mask);
644*5331Samw }
645*5331Samw 
646*5331Samw /*
647*5331Samw  * smb_acl_getsids
648*5331Samw  *
649*5331Samw  * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs.
650*5331Samw  */
651*5331Samw static idmap_stat
652*5331Samw smb_acl_getsids(smb_idmap_batch_t *sib, acl_t *zacl, uid_t uid, gid_t gid)
653*5331Samw {
654*5331Samw 	ace_t *zace;
655*5331Samw 	idmap_stat idm_stat;
656*5331Samw 	smb_idmap_t *sim;
657*5331Samw 	uid_t id;
658*5331Samw 	int i, idtype;
659*5331Samw 
660*5331Samw 	sim = sib->sib_maps;
661*5331Samw 
662*5331Samw 	for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt;
663*5331Samw 	    zace++, i++, sim++) {
664*5331Samw 		switch (zace->a_flags & ACE_TYPE_FLAGS) {
665*5331Samw 		case ACE_OWNER:
666*5331Samw 			id = uid;
667*5331Samw 			idtype = SMB_IDMAP_USER;
668*5331Samw 			break;
669*5331Samw 
670*5331Samw 		case (ACE_GROUP | ACE_IDENTIFIER_GROUP):
671*5331Samw 			/* owning group */
672*5331Samw 			id = gid;
673*5331Samw 			idtype = SMB_IDMAP_GROUP;
674*5331Samw 			break;
675*5331Samw 
676*5331Samw 		case ACE_IDENTIFIER_GROUP:
677*5331Samw 			/* regular group */
678*5331Samw 			id = zace->a_who;
679*5331Samw 			idtype = SMB_IDMAP_GROUP;
680*5331Samw 			break;
681*5331Samw 
682*5331Samw 		case ACE_EVERYONE:
683*5331Samw 			idtype = SMB_IDMAP_EVERYONE;
684*5331Samw 			break;
685*5331Samw 
686*5331Samw 		default:
687*5331Samw 			/* user entry */
688*5331Samw 			id = zace->a_who;
689*5331Samw 			idtype = SMB_IDMAP_USER;
690*5331Samw 		}
691*5331Samw 
692*5331Samw 		idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim,
693*5331Samw 		    id, idtype);
694*5331Samw 
695*5331Samw 		if (idm_stat != IDMAP_SUCCESS) {
696*5331Samw 			return (idm_stat);
697*5331Samw 		}
698*5331Samw 	}
699*5331Samw 
700*5331Samw 	idm_stat = smb_idmap_batch_getmappings(sib);
701*5331Samw 	return (idm_stat);
702*5331Samw }
703*5331Samw 
704*5331Samw /*
705*5331Samw  * smb_acl_grow
706*5331Samw  *
707*5331Samw  * Grow the acl size by given number of bytes in 'grow'
708*5331Samw  * Returns pointer to the newly allocated memory.
709*5331Samw  */
710*5331Samw static smb_acl_t *
711*5331Samw smb_acl_grow(smb_acl_t *acl, uint16_t grow)
712*5331Samw {
713*5331Samw 	smb_acl_t *new_acl;
714*5331Samw 	uint16_t smb_aclsz;
715*5331Samw 
716*5331Samw 	ASSERT(acl);
717*5331Samw 
718*5331Samw 	smb_aclsz = acl->sl_size;
719*5331Samw 	new_acl = kmem_alloc(smb_aclsz + grow, KM_SLEEP);
720*5331Samw 	(void) memcpy(new_acl, acl, smb_aclsz);
721*5331Samw 	kmem_free(acl, smb_aclsz);
722*5331Samw 	new_acl->sl_size = smb_aclsz + grow;
723*5331Samw 
724*5331Samw 	return (new_acl);
725*5331Samw }
726*5331Samw 
727*5331Samw /*
728*5331Samw  * smb_acl_from_zfs
729*5331Samw  *
730*5331Samw  * Converts given ZFS ACL to a Windows ACL.
731*5331Samw  *
732*5331Samw  * A pointer to allocated memory for the Win ACL will be
733*5331Samw  * returned upon successful conversion.
734*5331Samw  */
735*5331Samw smb_acl_t *
736*5331Samw smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid)
737*5331Samw {
738*5331Samw 	ace_t *zace;
739*5331Samw 	int numaces;
740*5331Samw 	smb_acl_t *acl;
741*5331Samw 	uint16_t smb_aclsz;
742*5331Samw 	smb_idmap_batch_t sib;
743*5331Samw 	smb_idmap_t *sim;
744*5331Samw 	idmap_stat idm_stat;
745*5331Samw 	int status;
746*5331Samw 
747*5331Samw 	idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt,
748*5331Samw 	    SMB_IDMAP_ID2SID);
749*5331Samw 	if (idm_stat != IDMAP_SUCCESS)
750*5331Samw 		return (NULL);
751*5331Samw 
752*5331Samw 	if (smb_acl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) {
753*5331Samw 		smb_idmap_batch_destroy(&sib);
754*5331Samw 		return (NULL);
755*5331Samw 	}
756*5331Samw 
757*5331Samw 	smb_aclsz = sizeof (smb_acl_t);
758*5331Samw 
759*5331Samw 	acl = kmem_alloc(smb_aclsz, KM_SLEEP);
760*5331Samw 	smb_acl_init(acl, smb_aclsz, ACL_REVISION);
761*5331Samw 
762*5331Samw 	sim = sib.sib_maps;
763*5331Samw 	for (numaces = 0, zace = zacl->acl_aclp;
764*5331Samw 	    numaces < zacl->acl_cnt;
765*5331Samw 	    zace++, numaces++, sim++) {
766*5331Samw 		ASSERT(sim->sim_sid);
767*5331Samw 		if (sim->sim_sid == NULL) {
768*5331Samw 			kmem_free(acl, acl->sl_size);
769*5331Samw 			acl = NULL;
770*5331Samw 			break;
771*5331Samw 		}
772*5331Samw 
773*5331Samw 		/* Make room for this ACE */
774*5331Samw 		acl = smb_acl_grow(acl, smb_ace_len(sim->sim_sid));
775*5331Samw 
776*5331Samw 		status = smb_ace_common_add(acl,
777*5331Samw 		    zace->a_type,
778*5331Samw 		    smb_ace_flags_fromzfs(zace->a_flags),
779*5331Samw 		    zace->a_access_mask,
780*5331Samw 		    sim->sim_sid);
781*5331Samw 
782*5331Samw 		if (status == 0) {
783*5331Samw 			kmem_free(acl, acl->sl_size);
784*5331Samw 			acl = NULL;
785*5331Samw 			break;
786*5331Samw 		}
787*5331Samw 	}
788*5331Samw 
789*5331Samw 	smb_idmap_batch_destroy(&sib);
790*5331Samw 	return (acl);
791*5331Samw }
792*5331Samw 
793*5331Samw /*
794*5331Samw  * SID for Everyone group: S-1-1-0.
795*5331Samw  */
796*5331Samw nt_sid_t everyone_sid = {
797*5331Samw 	NT_SID_REVISION,
798*5331Samw 	1,
799*5331Samw 	NT_SECURITY_WORLD_AUTH,
800*5331Samw 	{ 0 }
801*5331Samw };
802*5331Samw 
803*5331Samw /*
804*5331Samw  * smb_acl_null_empty
805*5331Samw  *
806*5331Samw  * NULL DACL means everyone full-access
807*5331Samw  * Empty DACL means everyone full-deny
808*5331Samw  *
809*5331Samw  * ZFS ACL must have at least one entry so smb server has
810*5331Samw  * to simulate the aforementioned expected behavior by adding
811*5331Samw  * an entry in case the requested DACL is null or empty. Adding
812*5331Samw  * a everyone full-deny entry has proved to be problematic in
813*5331Samw  * tests since a deny entry takes precedence over allow entries.
814*5331Samw  * So, instead of adding a everyone full-deny, an owner ACE with
815*5331Samw  * owner implicit permissions will be set.
816*5331Samw  */
817*5331Samw acl_t *
818*5331Samw smb_acl_null_empty(int null)
819*5331Samw {
820*5331Samw 	acl_t *zacl;
821*5331Samw 	ace_t *zace;
822*5331Samw 
823*5331Samw 	zacl = smb_fsop_aclalloc(1, ACL_AUTO_INHERIT);
824*5331Samw 	zace = zacl->acl_aclp;
825*5331Samw 
826*5331Samw 	zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
827*5331Samw 	if (null) {
828*5331Samw 		zace->a_access_mask = ACE_ALL_PERMS;
829*5331Samw 		zace->a_flags = ACE_EVERYONE;
830*5331Samw 	} else {
831*5331Samw 		zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL |
832*5331Samw 		    ACE_READ_ATTRIBUTES;
833*5331Samw 		zace->a_flags = ACE_OWNER;
834*5331Samw 	}
835*5331Samw 
836*5331Samw 	return (zacl);
837*5331Samw }
838*5331Samw 
839*5331Samw /*
840*5331Samw  * smb_acl_to_zfs
841*5331Samw  *
842*5331Samw  * Converts given Windows ACL to a ZFS ACL.
843*5331Samw  *
844*5331Samw  * fs_acl will contain a pointer to the created ZFS ACL.
845*5331Samw  * The allocated memory should be freed by calling
846*5331Samw  * smb_fsop_aclfree().
847*5331Samw  *
848*5331Samw  * Since the output parameter, fs_acl, is allocated in this
849*5331Samw  * function, the caller has to make sure *fs_acl is NULL which
850*5331Samw  * means it's not pointing to any memory.
851*5331Samw  */
852*5331Samw uint32_t
853*5331Samw smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl)
854*5331Samw {
855*5331Samw 	smb_ace_t *ace;
856*5331Samw 	acl_t *zacl;
857*5331Samw 	ace_t *zace;
858*5331Samw 	smb_idmap_batch_t sib;
859*5331Samw 	smb_idmap_t *sim;
860*5331Samw 	idmap_stat idm_stat;
861*5331Samw 	int i, isdir;
862*5331Samw 
863*5331Samw 	ASSERT(fs_acl);
864*5331Samw 	ASSERT(*fs_acl == NULL);
865*5331Samw 
866*5331Samw 	if (acl && !smb_acl_isvalid(acl, which_acl))
867*5331Samw 		return (NT_STATUS_INVALID_ACL);
868*5331Samw 
869*5331Samw 	if ((acl == NULL) || (acl->sl_acecnt == 0)) {
870*5331Samw 		if (which_acl == SMB_DACL_SECINFO) {
871*5331Samw 			*fs_acl = smb_acl_null_empty(acl == NULL);
872*5331Samw 		}
873*5331Samw 
874*5331Samw 		return (NT_STATUS_SUCCESS);
875*5331Samw 	}
876*5331Samw 
877*5331Samw 	idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt,
878*5331Samw 	    SMB_IDMAP_SID2ID);
879*5331Samw 	if (idm_stat != IDMAP_SUCCESS)
880*5331Samw 		return (NT_STATUS_INTERNAL_ERROR);
881*5331Samw 
882*5331Samw 	isdir = ((flags & ACL_IS_DIR) == ACL_IS_DIR);
883*5331Samw 
884*5331Samw 	zacl = smb_fsop_aclalloc(acl->sl_acecnt, flags);
885*5331Samw 
886*5331Samw 	zace = zacl->acl_aclp;
887*5331Samw 	sim = sib.sib_maps;
888*5331Samw 
889*5331Samw 	for (i = 0; ace = smb_ace_get(acl, i); i++, zace++, sim++) {
890*5331Samw 		zace->a_type = ace->se_header.se_type & ACE_ALL_TYPES;
891*5331Samw 		zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask);
892*5331Samw 		zace->a_flags = smb_ace_flags_tozfs(ace->se_header.se_flags,
893*5331Samw 		    isdir);
894*5331Samw 
895*5331Samw 		if (nt_sid_is_equal(&ace->se_sid, &everyone_sid))
896*5331Samw 			zace->a_flags |= ACE_EVERYONE;
897*5331Samw 		else {
898*5331Samw 			sim->sim_id = &zace->a_who;
899*5331Samw 			idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim,
900*5331Samw 			    &ace->se_sid, -1);
901*5331Samw 
902*5331Samw 			if (idm_stat != IDMAP_SUCCESS) {
903*5331Samw 				smb_fsop_aclfree(zacl);
904*5331Samw 				smb_idmap_batch_destroy(&sib);
905*5331Samw 				return (NT_STATUS_INTERNAL_ERROR);
906*5331Samw 			}
907*5331Samw 		}
908*5331Samw 	}
909*5331Samw 
910*5331Samw 	idm_stat = smb_idmap_batch_getmappings(&sib);
911*5331Samw 	if (idm_stat != IDMAP_SUCCESS) {
912*5331Samw 		smb_fsop_aclfree(zacl);
913*5331Samw 		smb_idmap_batch_destroy(&sib);
914*5331Samw 		return (NT_STATUS_NONE_MAPPED);
915*5331Samw 	}
916*5331Samw 
917*5331Samw 	/*
918*5331Samw 	 * Set the ACEs group flag based on the type of ID returned.
919*5331Samw 	 */
920*5331Samw 	zace = zacl->acl_aclp;
921*5331Samw 	sim = sib.sib_maps;
922*5331Samw 	for (i = 0; i < acl->sl_acecnt; i++, zace++, sim++) {
923*5331Samw 		if (zace->a_flags & ACE_EVERYONE)
924*5331Samw 			continue;
925*5331Samw 
926*5331Samw 		if (sim->sim_idtype == SMB_IDMAP_GROUP)
927*5331Samw 			zace->a_flags |= ACE_IDENTIFIER_GROUP;
928*5331Samw 	}
929*5331Samw 
930*5331Samw 	smb_idmap_batch_destroy(&sib);
931*5331Samw 
932*5331Samw 	*fs_acl = zacl;
933*5331Samw 	return (NT_STATUS_SUCCESS);
934*5331Samw }
935*5331Samw 
936*5331Samw /*
937*5331Samw  * smb_acl_inheritable
938*5331Samw  *
939*5331Samw  * Checks to see if there are any inheritable ACEs in the
940*5331Samw  * given ZFS ACL. Returns the number of inheritable ACEs.
941*5331Samw  *
942*5331Samw  * The inherited ACL could be different based on the type of
943*5331Samw  * new object (file/dir) specified by 'is_dir'.
944*5331Samw  *
945*5331Samw  * Note that the input ACL is a ZFS ACL not Windows ACL.
946*5331Samw  *
947*5331Samw  * Any ACE except creator owner/group:
948*5331Samw  *
949*5331Samw  *  FI   DI   NP   #F  #D
950*5331Samw  * ---- ---- ---- ---- ----
951*5331Samw  *  -    -    ?    0    0
952*5331Samw  *  X    -    -    1    1
953*5331Samw  *  X    -    X    1    0
954*5331Samw  *  -    X    -    0    1
955*5331Samw  *  -    X    X    0    1
956*5331Samw  *  X    X    -    1    1
957*5331Samw  *  X    X    X    1    1
958*5331Samw  *
959*5331Samw  * Creator owner/group ACE:
960*5331Samw  *
961*5331Samw  *  FI   DI   NP   #F  #D
962*5331Samw  * ---- ---- ---- ---- ----
963*5331Samw  *  -    -    ?    0    0
964*5331Samw  *  X    -    -    1r   1c
965*5331Samw  *  X    -    X    1r   0
966*5331Samw  *  -    X    -    0    2
967*5331Samw  *  -    X    X    0    1r
968*5331Samw  *  X    X    -    1r   2
969*5331Samw  *  X    X    X    1r   1r
970*5331Samw  *
971*5331Samw  * Legend:
972*5331Samw  *
973*5331Samw  *  FI: File Inherit
974*5331Samw  *  DI: Dir Inherit
975*5331Samw  *  NP: No Propagate
976*5331Samw  *  #F: #ACE for a new file
977*5331Samw  *  #D: #ACE for a new dir
978*5331Samw  *
979*5331Samw  *   X: bit is set
980*5331Samw  *   -: bit is not set
981*5331Samw  *   ?: don't care
982*5331Samw  *
983*5331Samw  *  1r: one owner/group ACE
984*5331Samw  *  1c: one creator owner/group ACE
985*5331Samw  */
986*5331Samw static int
987*5331Samw smb_acl_inheritable(acl_t *zacl, int is_dir)
988*5331Samw {
989*5331Samw 	int numaces;
990*5331Samw 	int num_inheritable = 0;
991*5331Samw 	ace_t *zace;
992*5331Samw 
993*5331Samw 	if (zacl == NULL)
994*5331Samw 		return (0);
995*5331Samw 
996*5331Samw 	for (numaces = 0, zace = zacl->acl_aclp;
997*5331Samw 	    numaces < zacl->acl_cnt;
998*5331Samw 	    zace++, numaces++) {
999*5331Samw 		switch (zace->a_flags & ACE_FD_INHERIT_ACE) {
1000*5331Samw 		case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
1001*5331Samw 			/*
1002*5331Samw 			 * Files inherit an effective ACE.
1003*5331Samw 			 *
1004*5331Samw 			 * Dirs inherit an effective ACE.
1005*5331Samw 			 * The inherited ACE is inheritable unless the
1006*5331Samw 			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
1007*5331Samw 			 */
1008*5331Samw 			num_inheritable++;
1009*5331Samw 
1010*5331Samw 			if (is_dir && ZACE_IS_CREATOR(zace) &&
1011*5331Samw 			    (ZACE_IS_PROPAGATE(zace))) {
1012*5331Samw 				num_inheritable++;
1013*5331Samw 			}
1014*5331Samw 			break;
1015*5331Samw 
1016*5331Samw 		case ACE_FILE_INHERIT_ACE:
1017*5331Samw 			/*
1018*5331Samw 			 * Files inherit as an effective ACE.
1019*5331Samw 			 *
1020*5331Samw 			 * Dirs inherit an inherit-only ACE
1021*5331Samw 			 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
1022*5331Samw 			 * flag is also set.
1023*5331Samw 			 */
1024*5331Samw 			if (is_dir == 0)
1025*5331Samw 				num_inheritable++;
1026*5331Samw 			else if (ZACE_IS_PROPAGATE(zace))
1027*5331Samw 				num_inheritable++;
1028*5331Samw 			break;
1029*5331Samw 
1030*5331Samw 		case ACE_DIRECTORY_INHERIT_ACE:
1031*5331Samw 			/*
1032*5331Samw 			 * No effect on files
1033*5331Samw 			 *
1034*5331Samw 			 * Dirs inherit an effective ACE.
1035*5331Samw 			 * The inherited ACE is inheritable unless the
1036*5331Samw 			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
1037*5331Samw 			 */
1038*5331Samw 			if (is_dir == 0)
1039*5331Samw 				break;
1040*5331Samw 
1041*5331Samw 			num_inheritable++;
1042*5331Samw 
1043*5331Samw 			if (ZACE_IS_CREATOR(zace) &&
1044*5331Samw 			    (ZACE_IS_PROPAGATE(zace)))
1045*5331Samw 				num_inheritable++;
1046*5331Samw 			break;
1047*5331Samw 
1048*5331Samw 		default:
1049*5331Samw 			break;
1050*5331Samw 		}
1051*5331Samw 	}
1052*5331Samw 
1053*5331Samw 	return (num_inheritable);
1054*5331Samw }
1055*5331Samw 
1056*5331Samw #define	DEFAULT_DACL_ACENUM	2
1057*5331Samw /*
1058*5331Samw  * Default ACL:
1059*5331Samw  *    owner: full access
1060*5331Samw  *    SYSTEM: full access
1061*5331Samw  */
1062*5331Samw static ace_t default_dacl[DEFAULT_DACL_ACENUM] = {
1063*5331Samw 	{ (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
1064*5331Samw 	{ IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP,
1065*5331Samw 	    ACE_ACCESS_ALLOWED_ACE_TYPE }
1066*5331Samw };
1067*5331Samw 
1068*5331Samw /*
1069*5331Samw  * smb_acl_inherit
1070*5331Samw  *
1071*5331Samw  * Manufacture the inherited ACL from the given ACL considering
1072*5331Samw  * the new object type (file/dir) specified by 'is_dir'. The
1073*5331Samw  * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions.
1074*5331Samw  * This function implements Windows inheritance rules.
1075*5331Samw  *
1076*5331Samw  * Note that the in/our ACLs are ZFS ACLs not Windows ACLs
1077*5331Samw  */
1078*5331Samw acl_t *
1079*5331Samw smb_acl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid)
1080*5331Samw {
1081*5331Samw 	boolean_t use_default = B_FALSE;
1082*5331Samw 	int num_inheritable = 0;
1083*5331Samw 	int numaces;
1084*5331Samw 	ace_t *dir_zace;
1085*5331Samw 	acl_t *new_zacl;
1086*5331Samw 	ace_t *new_zace;
1087*5331Samw 
1088*5331Samw 	num_inheritable = smb_acl_inheritable(dir_zacl, is_dir);
1089*5331Samw 
1090*5331Samw 	if (num_inheritable == 0) {
1091*5331Samw 		if (which_acl == SMB_DACL_SECINFO) {
1092*5331Samw 			/* No inheritable access ACEs -> default DACL */
1093*5331Samw 			num_inheritable = DEFAULT_DACL_ACENUM;
1094*5331Samw 			use_default = B_TRUE;
1095*5331Samw 		} else {
1096*5331Samw 			return (NULL);
1097*5331Samw 		}
1098*5331Samw 	}
1099*5331Samw 
1100*5331Samw 	new_zacl = smb_fsop_aclalloc(num_inheritable, ACL_AUTO_INHERIT);
1101*5331Samw 	new_zace = new_zacl->acl_aclp;
1102*5331Samw 
1103*5331Samw 	if (use_default) {
1104*5331Samw 		bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl));
1105*5331Samw 		new_zace->a_who = owner_uid;
1106*5331Samw 		return (new_zacl);
1107*5331Samw 	}
1108*5331Samw 
1109*5331Samw 	for (numaces = 0, dir_zace = dir_zacl->acl_aclp;
1110*5331Samw 	    numaces < dir_zacl->acl_cnt;
1111*5331Samw 	    dir_zace++, numaces++) {
1112*5331Samw 		switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) {
1113*5331Samw 		case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
1114*5331Samw 			/*
1115*5331Samw 			 * Files inherit an effective ACE.
1116*5331Samw 			 *
1117*5331Samw 			 * Dirs inherit an effective ACE.
1118*5331Samw 			 * The inherited ACE is inheritable unless the
1119*5331Samw 			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
1120*5331Samw 			 */
1121*5331Samw 			smb_ace_inherit(dir_zace, new_zace, is_dir);
1122*5331Samw 			new_zace++;
1123*5331Samw 
1124*5331Samw 			if (is_dir && ZACE_IS_CREATOR(dir_zace) &&
1125*5331Samw 			    (ZACE_IS_PROPAGATE(dir_zace))) {
1126*5331Samw 				*new_zace = *dir_zace;
1127*5331Samw 				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
1128*5331Samw 				    ACE_INHERITED_ACE);
1129*5331Samw 				new_zace++;
1130*5331Samw 			}
1131*5331Samw 			break;
1132*5331Samw 
1133*5331Samw 		case ACE_FILE_INHERIT_ACE:
1134*5331Samw 			/*
1135*5331Samw 			 * Files inherit as an effective ACE.
1136*5331Samw 			 *
1137*5331Samw 			 * Dirs inherit an inherit-only ACE
1138*5331Samw 			 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
1139*5331Samw 			 * flag is also set.
1140*5331Samw 			 */
1141*5331Samw 			if (is_dir == 0) {
1142*5331Samw 				smb_ace_inherit(dir_zace, new_zace, is_dir);
1143*5331Samw 				new_zace++;
1144*5331Samw 			} else if (ZACE_IS_PROPAGATE(dir_zace)) {
1145*5331Samw 				*new_zace = *dir_zace;
1146*5331Samw 				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
1147*5331Samw 				    ACE_INHERITED_ACE);
1148*5331Samw 				new_zace++;
1149*5331Samw 			}
1150*5331Samw 			break;
1151*5331Samw 
1152*5331Samw 		case ACE_DIRECTORY_INHERIT_ACE:
1153*5331Samw 			/*
1154*5331Samw 			 * No effect on files
1155*5331Samw 			 *
1156*5331Samw 			 * Dirs inherit an effective ACE.
1157*5331Samw 			 * The inherited ACE is inheritable unless the
1158*5331Samw 			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
1159*5331Samw 			 */
1160*5331Samw 			if (is_dir == 0)
1161*5331Samw 				break;
1162*5331Samw 
1163*5331Samw 			smb_ace_inherit(dir_zace, new_zace, is_dir);
1164*5331Samw 			new_zace++;
1165*5331Samw 
1166*5331Samw 			if (ZACE_IS_CREATOR(dir_zace) &&
1167*5331Samw 			    (ZACE_IS_PROPAGATE(dir_zace))) {
1168*5331Samw 				*new_zace = *dir_zace;
1169*5331Samw 				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
1170*5331Samw 				    ACE_INHERITED_ACE);
1171*5331Samw 				new_zace++;
1172*5331Samw 			}
1173*5331Samw 
1174*5331Samw 			break;
1175*5331Samw 
1176*5331Samw 		default:
1177*5331Samw 			break;
1178*5331Samw 		}
1179*5331Samw 	}
1180*5331Samw 
1181*5331Samw 	return (new_zacl);
1182*5331Samw }
1183*5331Samw 
1184*5331Samw static void
1185*5331Samw smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir)
1186*5331Samw {
1187*5331Samw 	*zace = *dir_zace;
1188*5331Samw 	if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace)))
1189*5331Samw 		zace->a_flags &= ~ACE_INHERIT_FLAGS;
1190*5331Samw 	zace->a_flags |= ACE_INHERITED_ACE;
1191*5331Samw 
1192*5331Samw 	/*
1193*5331Samw 	 * Replace creator owner/group ACEs with
1194*5331Samw 	 * actual owner/group ACEs.
1195*5331Samw 	 */
1196*5331Samw 	if (ZACE_IS_CREATOR_OWNER(dir_zace)) {
1197*5331Samw 		zace->a_who = (uid_t)-1;
1198*5331Samw 		zace->a_flags |= ACE_OWNER;
1199*5331Samw 	} else if (ZACE_IS_CREATOR_GROUP(dir_zace)) {
1200*5331Samw 		zace->a_who = (uid_t)-1;
1201*5331Samw 		zace->a_flags |= ACE_GROUP;
1202*5331Samw 	}
1203*5331Samw }
1204*5331Samw 
1205*5331Samw static uint16_t
1206*5331Samw smb_ace_flags_tozfs(uint8_t c_flags, int isdir)
1207*5331Samw {
1208*5331Samw 	uint16_t z_flags = 0;
1209*5331Samw 
1210*5331Samw 	if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG)
1211*5331Samw 		z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
1212*5331Samw 
1213*5331Samw 	if (c_flags & FAILED_ACCESS_ACE_FLAG)
1214*5331Samw 		z_flags |= ACE_FAILED_ACCESS_ACE_FLAG;
1215*5331Samw 
1216*5331Samw 	if (c_flags & INHERITED_ACE)
1217*5331Samw 		z_flags |= ACE_INHERITED_ACE;
1218*5331Samw 
1219*5331Samw 	/*
1220*5331Samw 	 * ZFS doesn't like any inheritance flags to be set on a
1221*5331Samw 	 * file's ACE, only directories. Windows doesn't care.
1222*5331Samw 	 */
1223*5331Samw 	if (isdir)
1224*5331Samw 		z_flags |= (c_flags & ACE_INHERIT_FLAGS);
1225*5331Samw 
1226*5331Samw 	return (z_flags);
1227*5331Samw }
1228*5331Samw 
1229*5331Samw static uint8_t
1230*5331Samw smb_ace_flags_fromzfs(uint16_t z_flags)
1231*5331Samw {
1232*5331Samw 	uint8_t c_flags;
1233*5331Samw 
1234*5331Samw 	c_flags = z_flags & ACE_INHERIT_FLAGS;
1235*5331Samw 
1236*5331Samw 	if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
1237*5331Samw 		c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1238*5331Samw 
1239*5331Samw 	if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG)
1240*5331Samw 		c_flags |= FAILED_ACCESS_ACE_FLAG;
1241*5331Samw 
1242*5331Samw 	if (z_flags & ACE_INHERITED_ACE)
1243*5331Samw 		c_flags |= INHERITED_ACE;
1244*5331Samw 
1245*5331Samw 	return (c_flags);
1246*5331Samw }
1247*5331Samw 
1248*5331Samw /*
1249*5331Samw  * This is generic (ACL version 2) vs. object-specific
1250*5331Samw  * (ACL version 4) ACE types.
1251*5331Samw  */
1252*5331Samw int
1253*5331Samw smb_ace_is_generic(int type)
1254*5331Samw {
1255*5331Samw 	switch (type) {
1256*5331Samw 	case ACE_ACCESS_ALLOWED_ACE_TYPE:
1257*5331Samw 	case ACE_ACCESS_DENIED_ACE_TYPE:
1258*5331Samw 	case ACE_SYSTEM_AUDIT_ACE_TYPE:
1259*5331Samw 	case ACE_SYSTEM_ALARM_ACE_TYPE:
1260*5331Samw 	case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
1261*5331Samw 	case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
1262*5331Samw 	case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
1263*5331Samw 	case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE:
1264*5331Samw 		return (1);
1265*5331Samw 
1266*5331Samw 	default:
1267*5331Samw 		break;
1268*5331Samw 	}
1269*5331Samw 
1270*5331Samw 	return (0);
1271*5331Samw }
1272*5331Samw 
1273*5331Samw int
1274*5331Samw smb_ace_is_access(int type)
1275*5331Samw {
1276*5331Samw 	switch (type) {
1277*5331Samw 	case ACE_ACCESS_ALLOWED_ACE_TYPE:
1278*5331Samw 	case ACE_ACCESS_DENIED_ACE_TYPE:
1279*5331Samw 	case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
1280*5331Samw 	case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
1281*5331Samw 	case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:
1282*5331Samw 	case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
1283*5331Samw 	case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
1284*5331Samw 	case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
1285*5331Samw 	case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
1286*5331Samw 		return (1);
1287*5331Samw 
1288*5331Samw 	default:
1289*5331Samw 		break;
1290*5331Samw 	}
1291*5331Samw 
1292*5331Samw 	return (0);
1293*5331Samw }
1294*5331Samw 
1295*5331Samw int
1296*5331Samw smb_ace_is_audit(int type)
1297*5331Samw {
1298*5331Samw 	switch (type) {
1299*5331Samw 	case ACE_SYSTEM_AUDIT_ACE_TYPE:
1300*5331Samw 	case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
1301*5331Samw 	case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
1302*5331Samw 	case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
1303*5331Samw 		return (1);
1304*5331Samw 
1305*5331Samw 	default:
1306*5331Samw 		break;
1307*5331Samw 	}
1308*5331Samw 
1309*5331Samw 	return (0);
1310*5331Samw }
1311