1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
24 */
25
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <sys/avl.h>
29#include <sys/misc.h>
30#if defined(_KERNEL)
31#include <sys/kmem.h>
32#include <sys/systm.h>
33#include <sys/sysmacros.h>
34#include <acl/acl_common.h>
35#include <sys/debug.h>
36#else
37#include <errno.h>
38#include <stdlib.h>
39#include <stddef.h>
40#include <unistd.h>
41#include <assert.h>
42#include <grp.h>
43#include <pwd.h>
44#include <acl_common.h>
45#endif
46
47#define	ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \
48    ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \
49    ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL)
50
51
52#define	ACL_SYNCHRONIZE_SET_DENY		0x0000001
53#define	ACL_SYNCHRONIZE_SET_ALLOW		0x0000002
54#define	ACL_SYNCHRONIZE_ERR_DENY		0x0000004
55#define	ACL_SYNCHRONIZE_ERR_ALLOW		0x0000008
56
57#define	ACL_WRITE_OWNER_SET_DENY		0x0000010
58#define	ACL_WRITE_OWNER_SET_ALLOW		0x0000020
59#define	ACL_WRITE_OWNER_ERR_DENY		0x0000040
60#define	ACL_WRITE_OWNER_ERR_ALLOW		0x0000080
61
62#define	ACL_DELETE_SET_DENY			0x0000100
63#define	ACL_DELETE_SET_ALLOW			0x0000200
64#define	ACL_DELETE_ERR_DENY			0x0000400
65#define	ACL_DELETE_ERR_ALLOW			0x0000800
66
67#define	ACL_WRITE_ATTRS_OWNER_SET_DENY		0x0001000
68#define	ACL_WRITE_ATTRS_OWNER_SET_ALLOW		0x0002000
69#define	ACL_WRITE_ATTRS_OWNER_ERR_DENY		0x0004000
70#define	ACL_WRITE_ATTRS_OWNER_ERR_ALLOW		0x0008000
71
72#define	ACL_WRITE_ATTRS_WRITER_SET_DENY		0x0010000
73#define	ACL_WRITE_ATTRS_WRITER_SET_ALLOW	0x0020000
74#define	ACL_WRITE_ATTRS_WRITER_ERR_DENY		0x0040000
75#define	ACL_WRITE_ATTRS_WRITER_ERR_ALLOW	0x0080000
76
77#define	ACL_WRITE_NAMED_WRITER_SET_DENY		0x0100000
78#define	ACL_WRITE_NAMED_WRITER_SET_ALLOW	0x0200000
79#define	ACL_WRITE_NAMED_WRITER_ERR_DENY		0x0400000
80#define	ACL_WRITE_NAMED_WRITER_ERR_ALLOW	0x0800000
81
82#define	ACL_READ_NAMED_READER_SET_DENY		0x1000000
83#define	ACL_READ_NAMED_READER_SET_ALLOW		0x2000000
84#define	ACL_READ_NAMED_READER_ERR_DENY		0x4000000
85#define	ACL_READ_NAMED_READER_ERR_ALLOW		0x8000000
86
87
88#define	ACE_VALID_MASK_BITS (\
89    ACE_READ_DATA | \
90    ACE_LIST_DIRECTORY | \
91    ACE_WRITE_DATA | \
92    ACE_ADD_FILE | \
93    ACE_APPEND_DATA | \
94    ACE_ADD_SUBDIRECTORY | \
95    ACE_READ_NAMED_ATTRS | \
96    ACE_WRITE_NAMED_ATTRS | \
97    ACE_EXECUTE | \
98    ACE_DELETE_CHILD | \
99    ACE_READ_ATTRIBUTES | \
100    ACE_WRITE_ATTRIBUTES | \
101    ACE_DELETE | \
102    ACE_READ_ACL | \
103    ACE_WRITE_ACL | \
104    ACE_WRITE_OWNER | \
105    ACE_SYNCHRONIZE)
106
107#define	ACE_MASK_UNDEFINED			0x80000000
108
109#define	ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \
110    ACE_DIRECTORY_INHERIT_ACE | \
111    ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \
112    ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \
113    ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE)
114
115/*
116 * ACL conversion helpers
117 */
118
119typedef enum {
120	ace_unused,
121	ace_user_obj,
122	ace_user,
123	ace_group, /* includes GROUP and GROUP_OBJ */
124	ace_other_obj
125} ace_to_aent_state_t;
126
127typedef struct acevals {
128	uid_t key;
129	avl_node_t avl;
130	uint32_t mask;
131	uint32_t allowed;
132	uint32_t denied;
133	int aent_type;
134} acevals_t;
135
136typedef struct ace_list {
137	acevals_t user_obj;
138	avl_tree_t user;
139	int numusers;
140	acevals_t group_obj;
141	avl_tree_t group;
142	int numgroups;
143	acevals_t other_obj;
144	uint32_t acl_mask;
145	int hasmask;
146	int dfacl_flag;
147	ace_to_aent_state_t state;
148	int seen; /* bitmask of all aclent_t a_type values seen */
149} ace_list_t;
150
151/*
152 * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
153 * v = Ptr to array/vector of objs
154 * n = # objs in the array
155 * s = size of each obj (must be multiples of a word size)
156 * f = ptr to function to compare two objs
157 *	returns (-1 = less than, 0 = equal, 1 = greater than
158 */
159void
160ksort(caddr_t v, int n, int s, int (*f)(void *, void *))
161{
162	int g, i, j, ii;
163	unsigned int *p1, *p2;
164	unsigned int tmp;
165
166	/* No work to do */
167	if (v == NULL || n <= 1)
168		return;
169
170	/* Sanity check on arguments */
171	ASSERT3U(((uintptr_t)v & 0x3), ==, 0);
172	ASSERT3S((s & 0x3), ==, 0);
173	ASSERT3S(s, >, 0);
174	for (g = n / 2; g > 0; g /= 2) {
175		for (i = g; i < n; i++) {
176			for (j = i - g; j >= 0 &&
177			    (*f)(v + j * s, v + (j + g) * s) == 1;
178			    j -= g) {
179				p1 = (void *)(v + j * s);
180				p2 = (void *)(v + (j + g) * s);
181				for (ii = 0; ii < s / 4; ii++) {
182					tmp = *p1;
183					*p1++ = *p2;
184					*p2++ = tmp;
185				}
186			}
187		}
188	}
189}
190
191/*
192 * Compare two acls, all fields.  Returns:
193 * -1 (less than)
194 *  0 (equal)
195 * +1 (greater than)
196 */
197int
198cmp2acls(void *a, void *b)
199{
200	aclent_t *x = (aclent_t *)a;
201	aclent_t *y = (aclent_t *)b;
202
203	/* Compare types */
204	if (x->a_type < y->a_type)
205		return (-1);
206	if (x->a_type > y->a_type)
207		return (1);
208	/* Equal types; compare id's */
209	if (x->a_id < y->a_id)
210		return (-1);
211	if (x->a_id > y->a_id)
212		return (1);
213	/* Equal ids; compare perms */
214	if (x->a_perm < y->a_perm)
215		return (-1);
216	if (x->a_perm > y->a_perm)
217		return (1);
218	/* Totally equal */
219	return (0);
220}
221
222static int
223cacl_malloc(void **ptr, size_t size)
224{
225	*ptr = kmem_zalloc(size, KM_SLEEP);
226	return (0);
227}
228
229
230#if !defined(_KERNEL)
231acl_t *
232acl_alloc(enum acl_type type)
233{
234	acl_t *aclp;
235
236	if (cacl_malloc((void **)&aclp, sizeof (acl_t)) != 0)
237		return (NULL);
238
239	aclp->acl_aclp = NULL;
240	aclp->acl_cnt = 0;
241
242	switch (type) {
243	case ACE_T:
244		aclp->acl_type = ACE_T;
245		aclp->acl_entry_size = sizeof (ace_t);
246		break;
247	case ACLENT_T:
248		aclp->acl_type = ACLENT_T;
249		aclp->acl_entry_size = sizeof (aclent_t);
250		break;
251	default:
252		acl_free(aclp);
253		aclp = NULL;
254	}
255	return (aclp);
256}
257
258/*
259 * Free acl_t structure
260 */
261void
262acl_free(acl_t *aclp)
263{
264	int acl_size;
265
266	if (aclp == NULL)
267		return;
268
269	if (aclp->acl_aclp) {
270		acl_size = aclp->acl_cnt * aclp->acl_entry_size;
271		cacl_free(aclp->acl_aclp, acl_size);
272	}
273
274	cacl_free(aclp, sizeof (acl_t));
275}
276
277static uint32_t
278access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow)
279{
280	uint32_t access_mask = 0;
281	int acl_produce;
282	int synchronize_set = 0, write_owner_set = 0;
283	int delete_set = 0, write_attrs_set = 0;
284	int read_named_set = 0, write_named_set = 0;
285
286	acl_produce = (ACL_SYNCHRONIZE_SET_ALLOW |
287	    ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
288	    ACL_WRITE_ATTRS_WRITER_SET_DENY);
289
290	if (isallow) {
291		synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW;
292		write_owner_set = ACL_WRITE_OWNER_SET_ALLOW;
293		delete_set = ACL_DELETE_SET_ALLOW;
294		if (hasreadperm)
295			read_named_set = ACL_READ_NAMED_READER_SET_ALLOW;
296		if (haswriteperm)
297			write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW;
298		if (isowner)
299			write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW;
300		else if (haswriteperm)
301			write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW;
302	} else {
303
304		synchronize_set = ACL_SYNCHRONIZE_SET_DENY;
305		write_owner_set = ACL_WRITE_OWNER_SET_DENY;
306		delete_set = ACL_DELETE_SET_DENY;
307		if (hasreadperm)
308			read_named_set = ACL_READ_NAMED_READER_SET_DENY;
309		if (haswriteperm)
310			write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY;
311		if (isowner)
312			write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY;
313		else if (haswriteperm)
314			write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY;
315		else
316			/*
317			 * If the entity is not the owner and does not
318			 * have write permissions ACE_WRITE_ATTRIBUTES will
319			 * always go in the DENY ACE.
320			 */
321			access_mask |= ACE_WRITE_ATTRIBUTES;
322	}
323
324	if (acl_produce & synchronize_set)
325		access_mask |= ACE_SYNCHRONIZE;
326	if (acl_produce & write_owner_set)
327		access_mask |= ACE_WRITE_OWNER;
328	if (acl_produce & delete_set)
329		access_mask |= ACE_DELETE;
330	if (acl_produce & write_attrs_set)
331		access_mask |= ACE_WRITE_ATTRIBUTES;
332	if (acl_produce & read_named_set)
333		access_mask |= ACE_READ_NAMED_ATTRS;
334	if (acl_produce & write_named_set)
335		access_mask |= ACE_WRITE_NAMED_ATTRS;
336
337	return (access_mask);
338}
339
340/*
341 * Given an mode_t, convert it into an access_mask as used
342 * by nfsace, assuming aclent_t -> nfsace semantics.
343 */
344static uint32_t
345mode_to_ace_access(mode_t mode, boolean_t isdir, int isowner, int isallow)
346{
347	uint32_t access = 0;
348	int haswriteperm = 0;
349	int hasreadperm = 0;
350
351	if (isallow) {
352		haswriteperm = (mode & S_IWOTH);
353		hasreadperm = (mode & S_IROTH);
354	} else {
355		haswriteperm = !(mode & S_IWOTH);
356		hasreadperm = !(mode & S_IROTH);
357	}
358
359	/*
360	 * The following call takes care of correctly setting the following
361	 * mask bits in the access_mask:
362	 * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE,
363	 * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS
364	 */
365	access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow);
366
367	if (isallow) {
368		access |= ACE_READ_ACL | ACE_READ_ATTRIBUTES;
369		if (isowner)
370			access |= ACE_WRITE_ACL;
371	} else {
372		if (! isowner)
373			access |= ACE_WRITE_ACL;
374	}
375
376	/* read */
377	if (mode & S_IROTH) {
378		access |= ACE_READ_DATA;
379	}
380	/* write */
381	if (mode & S_IWOTH) {
382		access |= ACE_WRITE_DATA |
383		    ACE_APPEND_DATA;
384		if (isdir)
385			access |= ACE_DELETE_CHILD;
386	}
387	/* exec */
388	if (mode & S_IXOTH) {
389		access |= ACE_EXECUTE;
390	}
391
392	return (access);
393}
394
395/*
396 * Given an nfsace (presumably an ALLOW entry), make a
397 * corresponding DENY entry at the address given.
398 */
399static void
400ace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner)
401{
402	(void) memcpy(deny, allow, sizeof (ace_t));
403
404	deny->a_who = allow->a_who;
405
406	deny->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
407	deny->a_access_mask ^= ACE_POSIX_SUPPORTED_BITS;
408	if (isdir)
409		deny->a_access_mask ^= ACE_DELETE_CHILD;
410
411	deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER |
412	    ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
413	    ACE_WRITE_NAMED_ATTRS);
414	deny->a_access_mask |= access_mask_set((allow->a_access_mask &
415	    ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner,
416	    B_FALSE);
417}
418/*
419 * Make an initial pass over an array of aclent_t's.  Gather
420 * information such as an ACL_MASK (if any), number of users,
421 * number of groups, and whether the array needs to be sorted.
422 */
423static int
424ln_aent_preprocess(aclent_t *aclent, int n,
425    int *hasmask, mode_t *mask,
426    int *numuser, int *numgroup, int *needsort)
427{
428	int error = 0;
429	int i;
430	int curtype = 0;
431
432	*hasmask = 0;
433	*mask = 07;
434	*needsort = 0;
435	*numuser = 0;
436	*numgroup = 0;
437
438	for (i = 0; i < n; i++) {
439		if (aclent[i].a_type < curtype)
440			*needsort = 1;
441		else if (aclent[i].a_type > curtype)
442			curtype = aclent[i].a_type;
443		if (aclent[i].a_type & USER)
444			(*numuser)++;
445		if (aclent[i].a_type & (GROUP | GROUP_OBJ))
446			(*numgroup)++;
447		if (aclent[i].a_type & CLASS_OBJ) {
448			if (*hasmask) {
449				error = EINVAL;
450				goto out;
451			} else {
452				*hasmask = 1;
453				*mask = aclent[i].a_perm;
454			}
455		}
456	}
457
458	if ((! *hasmask) && (*numuser + *numgroup > 1)) {
459		error = EINVAL;
460		goto out;
461	}
462
463out:
464	return (error);
465}
466
467/*
468 * Convert an array of aclent_t into an array of nfsace entries,
469 * following POSIX draft -> nfsv4 conversion semantics as outlined in
470 * the IETF draft.
471 */
472static int
473ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir)
474{
475	int error = 0;
476	mode_t mask;
477	int numuser, numgroup, needsort;
478	int resultsize = 0;
479	int i, groupi = 0, skip;
480	ace_t *acep, *result = NULL;
481	int hasmask;
482
483	error = ln_aent_preprocess(aclent, n, &hasmask, &mask,
484	    &numuser, &numgroup, &needsort);
485	if (error != 0)
486		goto out;
487
488	/* allow + deny for each aclent */
489	resultsize = n * 2;
490	if (hasmask) {
491		/*
492		 * stick extra deny on the group_obj and on each
493		 * user|group for the mask (the group_obj was added
494		 * into the count for numgroup)
495		 */
496		resultsize += numuser + numgroup;
497		/* ... and don't count the mask itself */
498		resultsize -= 2;
499	}
500
501	/* sort the source if necessary */
502	if (needsort)
503		ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls);
504
505	if (cacl_malloc((void **)&result, resultsize * sizeof (ace_t)) != 0)
506		goto out;
507
508	acep = result;
509
510	for (i = 0; i < n; i++) {
511		/*
512		 * don't process CLASS_OBJ (mask); mask was grabbed in
513		 * ln_aent_preprocess()
514		 */
515		if (aclent[i].a_type & CLASS_OBJ)
516			continue;
517
518		/* If we need an ACL_MASK emulator, prepend it now */
519		if ((hasmask) &&
520		    (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) {
521			acep->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
522			acep->a_flags = 0;
523			if (aclent[i].a_type & GROUP_OBJ) {
524				acep->a_who = (uid_t)-1;
525				acep->a_flags |=
526				    (ACE_IDENTIFIER_GROUP|ACE_GROUP);
527			} else if (aclent[i].a_type & USER) {
528				acep->a_who = aclent[i].a_id;
529			} else {
530				acep->a_who = aclent[i].a_id;
531				acep->a_flags |= ACE_IDENTIFIER_GROUP;
532			}
533			if (aclent[i].a_type & ACL_DEFAULT) {
534				acep->a_flags |= ACE_INHERIT_ONLY_ACE |
535				    ACE_FILE_INHERIT_ACE |
536				    ACE_DIRECTORY_INHERIT_ACE;
537			}
538			/*
539			 * Set the access mask for the prepended deny
540			 * ace.  To do this, we invert the mask (found
541			 * in ln_aent_preprocess()) then convert it to an
542			 * DENY ace access_mask.
543			 */
544			acep->a_access_mask = mode_to_ace_access((mask ^ 07),
545			    isdir, 0, 0);
546			acep += 1;
547		}
548
549		/* handle a_perm -> access_mask */
550		acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm,
551		    isdir, aclent[i].a_type & USER_OBJ, 1);
552
553		/* emulate a default aclent */
554		if (aclent[i].a_type & ACL_DEFAULT) {
555			acep->a_flags |= ACE_INHERIT_ONLY_ACE |
556			    ACE_FILE_INHERIT_ACE |
557			    ACE_DIRECTORY_INHERIT_ACE;
558		}
559
560		/*
561		 * handle a_perm and a_id
562		 *
563		 * this must be done last, since it involves the
564		 * corresponding deny aces, which are handled
565		 * differently for each different a_type.
566		 */
567		if (aclent[i].a_type & USER_OBJ) {
568			acep->a_who = (uid_t)-1;
569			acep->a_flags |= ACE_OWNER;
570			ace_make_deny(acep, acep + 1, isdir, B_TRUE);
571			acep += 2;
572		} else if (aclent[i].a_type & USER) {
573			acep->a_who = aclent[i].a_id;
574			ace_make_deny(acep, acep + 1, isdir, B_FALSE);
575			acep += 2;
576		} else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) {
577			if (aclent[i].a_type & GROUP_OBJ) {
578				acep->a_who = (uid_t)-1;
579				acep->a_flags |= ACE_GROUP;
580			} else {
581				acep->a_who = aclent[i].a_id;
582			}
583			acep->a_flags |= ACE_IDENTIFIER_GROUP;
584			/*
585			 * Set the corresponding deny for the group ace.
586			 *
587			 * The deny aces go after all of the groups, unlike
588			 * everything else, where they immediately follow
589			 * the allow ace.
590			 *
591			 * We calculate "skip", the number of slots to
592			 * skip ahead for the deny ace, here.
593			 *
594			 * The pattern is:
595			 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
596			 * thus, skip is
597			 * (2 * numgroup) - 1 - groupi
598			 * (2 * numgroup) to account for MD + A
599			 * - 1 to account for the fact that we're on the
600			 * access (A), not the mask (MD)
601			 * - groupi to account for the fact that we have
602			 * passed up groupi number of MD's.
603			 */
604			skip = (2 * numgroup) - 1 - groupi;
605			ace_make_deny(acep, acep + skip, isdir, B_FALSE);
606			/*
607			 * If we just did the last group, skip acep past
608			 * all of the denies; else, just move ahead one.
609			 */
610			if (++groupi >= numgroup)
611				acep += numgroup + 1;
612			else
613				acep += 1;
614		} else if (aclent[i].a_type & OTHER_OBJ) {
615			acep->a_who = (uid_t)-1;
616			acep->a_flags |= ACE_EVERYONE;
617			ace_make_deny(acep, acep + 1, isdir, B_FALSE);
618			acep += 2;
619		} else {
620			error = EINVAL;
621			goto out;
622		}
623	}
624
625	*acepp = result;
626	*rescount = resultsize;
627
628out:
629	if (error != 0) {
630		if ((result != NULL) && (resultsize > 0)) {
631			cacl_free(result, resultsize * sizeof (ace_t));
632		}
633	}
634
635	return (error);
636}
637
638static int
639convert_aent_to_ace(aclent_t *aclentp, int aclcnt, boolean_t isdir,
640    ace_t **retacep, int *retacecnt)
641{
642	ace_t *acep;
643	ace_t *dfacep;
644	int acecnt = 0;
645	int dfacecnt = 0;
646	int dfaclstart = 0;
647	int dfaclcnt = 0;
648	aclent_t *aclp;
649	int i;
650	int error;
651	int acesz, dfacesz;
652
653	ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls);
654
655	for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) {
656		if (aclp->a_type & ACL_DEFAULT)
657			break;
658	}
659
660	if (i < aclcnt) {
661		dfaclstart = i;
662		dfaclcnt = aclcnt - i;
663	}
664
665	if (dfaclcnt && !isdir) {
666		return (EINVAL);
667	}
668
669	error = ln_aent_to_ace(aclentp, i,  &acep, &acecnt, isdir);
670	if (error)
671		return (error);
672
673	if (dfaclcnt) {
674		error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt,
675		    &dfacep, &dfacecnt, isdir);
676		if (error) {
677			if (acep) {
678				cacl_free(acep, acecnt * sizeof (ace_t));
679			}
680			return (error);
681		}
682	}
683
684	if (dfacecnt != 0) {
685		acesz = sizeof (ace_t) * acecnt;
686		dfacesz = sizeof (ace_t) * dfacecnt;
687		acep = cacl_realloc(acep, acesz, acesz + dfacesz);
688		if (acep == NULL)
689			return (ENOMEM);
690		if (dfaclcnt) {
691			(void) memcpy(acep + acecnt, dfacep, dfacesz);
692		}
693	}
694	if (dfaclcnt)
695		cacl_free(dfacep, dfacecnt * sizeof (ace_t));
696
697	*retacecnt = acecnt + dfacecnt;
698	*retacep = acep;
699	return (0);
700}
701
702static int
703ace_mask_to_mode(uint32_t  mask, o_mode_t *modep, boolean_t isdir)
704{
705	int error = 0;
706	o_mode_t mode = 0;
707	uint32_t bits, wantbits;
708
709	/* read */
710	if (mask & ACE_READ_DATA)
711		mode |= S_IROTH;
712
713	/* write */
714	wantbits = (ACE_WRITE_DATA | ACE_APPEND_DATA);
715	if (isdir)
716		wantbits |= ACE_DELETE_CHILD;
717	bits = mask & wantbits;
718	if (bits != 0) {
719		if (bits != wantbits) {
720			error = ENOTSUP;
721			goto out;
722		}
723		mode |= S_IWOTH;
724	}
725
726	/* exec */
727	if (mask & ACE_EXECUTE) {
728		mode |= S_IXOTH;
729	}
730
731	*modep = mode;
732
733out:
734	return (error);
735}
736
737static void
738acevals_init(acevals_t *vals, uid_t key)
739{
740	memset(vals, 0, sizeof (*vals));
741	vals->allowed = ACE_MASK_UNDEFINED;
742	vals->denied = ACE_MASK_UNDEFINED;
743	vals->mask = ACE_MASK_UNDEFINED;
744	vals->key = key;
745}
746
747static void
748ace_list_init(ace_list_t *al, int dfacl_flag)
749{
750	acevals_init(&al->user_obj, 0);
751	acevals_init(&al->group_obj, 0);
752	acevals_init(&al->other_obj, 0);
753	al->numusers = 0;
754	al->numgroups = 0;
755	al->acl_mask = 0;
756	al->hasmask = 0;
757	al->state = ace_unused;
758	al->seen = 0;
759	al->dfacl_flag = dfacl_flag;
760}
761
762/*
763 * Find or create an acevals holder for a given id and avl tree.
764 *
765 * Note that only one thread will ever touch these avl trees, so
766 * there is no need for locking.
767 */
768static acevals_t *
769acevals_find(ace_t *ace, avl_tree_t *avl, int *num)
770{
771	acevals_t key, *rc;
772	avl_index_t where;
773
774	key.key = ace->a_who;
775	rc = avl_find(avl, &key, &where);
776	if (rc != NULL)
777		return (rc);
778
779	/* this memory is freed by ln_ace_to_aent()->ace_list_free() */
780	if (cacl_malloc((void **)&rc, sizeof (acevals_t)) != 0)
781		return (NULL);
782
783	acevals_init(rc, ace->a_who);
784	avl_insert(avl, rc, where);
785	(*num)++;
786
787	return (rc);
788}
789
790static int
791access_mask_check(ace_t *acep, int mask_bit, int isowner)
792{
793	int set_deny, err_deny;
794	int set_allow, err_allow;
795	int acl_consume;
796	int haswriteperm, hasreadperm;
797
798	if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) {
799		haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 0 : 1;
800		hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 0 : 1;
801	} else {
802		haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 1 : 0;
803		hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 1 : 0;
804	}
805
806	acl_consume = (ACL_SYNCHRONIZE_ERR_DENY |
807	    ACL_DELETE_ERR_DENY |
808	    ACL_WRITE_OWNER_ERR_DENY |
809	    ACL_WRITE_OWNER_ERR_ALLOW |
810	    ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
811	    ACL_WRITE_ATTRS_OWNER_ERR_DENY |
812	    ACL_WRITE_ATTRS_WRITER_SET_DENY |
813	    ACL_WRITE_ATTRS_WRITER_ERR_ALLOW |
814	    ACL_WRITE_NAMED_WRITER_ERR_DENY |
815	    ACL_READ_NAMED_READER_ERR_DENY);
816
817	if (mask_bit == ACE_SYNCHRONIZE) {
818		set_deny = ACL_SYNCHRONIZE_SET_DENY;
819		err_deny =  ACL_SYNCHRONIZE_ERR_DENY;
820		set_allow = ACL_SYNCHRONIZE_SET_ALLOW;
821		err_allow = ACL_SYNCHRONIZE_ERR_ALLOW;
822	} else if (mask_bit == ACE_WRITE_OWNER) {
823		set_deny = ACL_WRITE_OWNER_SET_DENY;
824		err_deny =  ACL_WRITE_OWNER_ERR_DENY;
825		set_allow = ACL_WRITE_OWNER_SET_ALLOW;
826		err_allow = ACL_WRITE_OWNER_ERR_ALLOW;
827	} else if (mask_bit == ACE_DELETE) {
828		set_deny = ACL_DELETE_SET_DENY;
829		err_deny =  ACL_DELETE_ERR_DENY;
830		set_allow = ACL_DELETE_SET_ALLOW;
831		err_allow = ACL_DELETE_ERR_ALLOW;
832	} else if (mask_bit == ACE_WRITE_ATTRIBUTES) {
833		if (isowner) {
834			set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY;
835			err_deny =  ACL_WRITE_ATTRS_OWNER_ERR_DENY;
836			set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW;
837			err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW;
838		} else if (haswriteperm) {
839			set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY;
840			err_deny =  ACL_WRITE_ATTRS_WRITER_ERR_DENY;
841			set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW;
842			err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW;
843		} else {
844			if ((acep->a_access_mask & mask_bit) &&
845			    (acep->a_type & ACE_ACCESS_ALLOWED_ACE_TYPE)) {
846				return (ENOTSUP);
847			}
848			return (0);
849		}
850	} else if (mask_bit == ACE_READ_NAMED_ATTRS) {
851		if (!hasreadperm)
852			return (0);
853
854		set_deny = ACL_READ_NAMED_READER_SET_DENY;
855		err_deny = ACL_READ_NAMED_READER_ERR_DENY;
856		set_allow = ACL_READ_NAMED_READER_SET_ALLOW;
857		err_allow = ACL_READ_NAMED_READER_ERR_ALLOW;
858	} else if (mask_bit == ACE_WRITE_NAMED_ATTRS) {
859		if (!haswriteperm)
860			return (0);
861
862		set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY;
863		err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY;
864		set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW;
865		err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW;
866	} else {
867		return (EINVAL);
868	}
869
870	if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) {
871		if (acl_consume & set_deny) {
872			if (!(acep->a_access_mask & mask_bit)) {
873				return (ENOTSUP);
874			}
875		} else if (acl_consume & err_deny) {
876			if (acep->a_access_mask & mask_bit) {
877				return (ENOTSUP);
878			}
879		}
880	} else {
881		/* ACE_ACCESS_ALLOWED_ACE_TYPE */
882		if (acl_consume & set_allow) {
883			if (!(acep->a_access_mask & mask_bit)) {
884				return (ENOTSUP);
885			}
886		} else if (acl_consume & err_allow) {
887			if (acep->a_access_mask & mask_bit) {
888				return (ENOTSUP);
889			}
890		}
891	}
892	return (0);
893}
894
895static int
896ace_to_aent_legal(ace_t *acep)
897{
898	int error = 0;
899	int isowner;
900
901	/* only ALLOW or DENY */
902	if ((acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE) &&
903	    (acep->a_type != ACE_ACCESS_DENIED_ACE_TYPE)) {
904		error = ENOTSUP;
905		goto out;
906	}
907
908	/* check for invalid flags */
909	if (acep->a_flags & ~(ACE_VALID_FLAG_BITS)) {
910		error = EINVAL;
911		goto out;
912	}
913
914	/* some flags are illegal */
915	if (acep->a_flags & (ACE_SUCCESSFUL_ACCESS_ACE_FLAG |
916	    ACE_FAILED_ACCESS_ACE_FLAG |
917	    ACE_NO_PROPAGATE_INHERIT_ACE)) {
918		error = ENOTSUP;
919		goto out;
920	}
921
922	/* check for invalid masks */
923	if (acep->a_access_mask & ~(ACE_VALID_MASK_BITS)) {
924		error = EINVAL;
925		goto out;
926	}
927
928	if ((acep->a_flags & ACE_OWNER)) {
929		isowner = 1;
930	} else {
931		isowner = 0;
932	}
933
934	error = access_mask_check(acep, ACE_SYNCHRONIZE, isowner);
935	if (error)
936		goto out;
937
938	error = access_mask_check(acep, ACE_WRITE_OWNER, isowner);
939	if (error)
940		goto out;
941
942	error = access_mask_check(acep, ACE_DELETE, isowner);
943	if (error)
944		goto out;
945
946	error = access_mask_check(acep, ACE_WRITE_ATTRIBUTES, isowner);
947	if (error)
948		goto out;
949
950	error = access_mask_check(acep, ACE_READ_NAMED_ATTRS, isowner);
951	if (error)
952		goto out;
953
954	error = access_mask_check(acep, ACE_WRITE_NAMED_ATTRS, isowner);
955	if (error)
956		goto out;
957
958	/* more detailed checking of masks */
959	if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
960		if (! (acep->a_access_mask & ACE_READ_ATTRIBUTES)) {
961			error = ENOTSUP;
962			goto out;
963		}
964		if ((acep->a_access_mask & ACE_WRITE_DATA) &&
965		    (! (acep->a_access_mask & ACE_APPEND_DATA))) {
966			error = ENOTSUP;
967			goto out;
968		}
969		if ((! (acep->a_access_mask & ACE_WRITE_DATA)) &&
970		    (acep->a_access_mask & ACE_APPEND_DATA)) {
971			error = ENOTSUP;
972			goto out;
973		}
974	}
975
976	/* ACL enforcement */
977	if ((acep->a_access_mask & ACE_READ_ACL) &&
978	    (acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE)) {
979		error = ENOTSUP;
980		goto out;
981	}
982	if (acep->a_access_mask & ACE_WRITE_ACL) {
983		if ((acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) &&
984		    (isowner)) {
985			error = ENOTSUP;
986			goto out;
987		}
988		if ((acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) &&
989		    (! isowner)) {
990			error = ENOTSUP;
991			goto out;
992		}
993	}
994
995out:
996	return (error);
997}
998
999static int
1000ace_allow_to_mode(uint32_t mask, o_mode_t *modep, boolean_t isdir)
1001{
1002	/* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */
1003	if ((mask & (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) !=
1004	    (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) {
1005		return (ENOTSUP);
1006	}
1007
1008	return (ace_mask_to_mode(mask, modep, isdir));
1009}
1010
1011static int
1012acevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list,
1013    uid_t owner, gid_t group, boolean_t isdir)
1014{
1015	int error;
1016	uint32_t  flips = ACE_POSIX_SUPPORTED_BITS;
1017
1018	if (isdir)
1019		flips |= ACE_DELETE_CHILD;
1020	if (vals->allowed != (vals->denied ^ flips)) {
1021		error = ENOTSUP;
1022		goto out;
1023	}
1024	if ((list->hasmask) && (list->acl_mask != vals->mask) &&
1025	    (vals->aent_type & (USER | GROUP | GROUP_OBJ))) {
1026		error = ENOTSUP;
1027		goto out;
1028	}
1029	error = ace_allow_to_mode(vals->allowed, &dest->a_perm, isdir);
1030	if (error != 0)
1031		goto out;
1032	dest->a_type = vals->aent_type;
1033	if (dest->a_type & (USER | GROUP)) {
1034		dest->a_id = vals->key;
1035	} else if (dest->a_type & USER_OBJ) {
1036		dest->a_id = owner;
1037	} else if (dest->a_type & GROUP_OBJ) {
1038		dest->a_id = group;
1039	} else if (dest->a_type & OTHER_OBJ) {
1040		dest->a_id = 0;
1041	} else {
1042		error = EINVAL;
1043		goto out;
1044	}
1045
1046out:
1047	return (error);
1048}
1049
1050
1051static int
1052ace_list_to_aent(ace_list_t *list, aclent_t **aclentp, int *aclcnt,
1053    uid_t owner, gid_t group, boolean_t isdir)
1054{
1055	int error = 0;
1056	aclent_t *aent, *result = NULL;
1057	acevals_t *vals;
1058	int resultcount;
1059
1060	if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) !=
1061	    (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) {
1062		error = ENOTSUP;
1063		goto out;
1064	}
1065	if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) {
1066		error = ENOTSUP;
1067		goto out;
1068	}
1069
1070	resultcount = 3 + list->numusers + list->numgroups;
1071	/*
1072	 * This must be the same condition as below, when we add the CLASS_OBJ
1073	 * (aka ACL mask)
1074	 */
1075	if ((list->hasmask) || (! list->dfacl_flag))
1076		resultcount += 1;
1077
1078	if (cacl_malloc((void **)&result,
1079	    resultcount * sizeof (aclent_t)) != 0) {
1080		error = ENOMEM;
1081		goto out;
1082	}
1083	aent = result;
1084
1085	/* USER_OBJ */
1086	if (!(list->user_obj.aent_type & USER_OBJ)) {
1087		error = EINVAL;
1088		goto out;
1089	}
1090
1091	error = acevals_to_aent(&list->user_obj, aent, list, owner, group,
1092	    isdir);
1093
1094	if (error != 0)
1095		goto out;
1096	++aent;
1097	/* USER */
1098	vals = NULL;
1099	for (vals = avl_first(&list->user); vals != NULL;
1100	    vals = AVL_NEXT(&list->user, vals)) {
1101		if (!(vals->aent_type & USER)) {
1102			error = EINVAL;
1103			goto out;
1104		}
1105		error = acevals_to_aent(vals, aent, list, owner, group,
1106		    isdir);
1107		if (error != 0)
1108			goto out;
1109		++aent;
1110	}
1111	/* GROUP_OBJ */
1112	if (!(list->group_obj.aent_type & GROUP_OBJ)) {
1113		error = EINVAL;
1114		goto out;
1115	}
1116	error = acevals_to_aent(&list->group_obj, aent, list, owner, group,
1117	    isdir);
1118	if (error != 0)
1119		goto out;
1120	++aent;
1121	/* GROUP */
1122	vals = NULL;
1123	for (vals = avl_first(&list->group); vals != NULL;
1124	    vals = AVL_NEXT(&list->group, vals)) {
1125		if (!(vals->aent_type & GROUP)) {
1126			error = EINVAL;
1127			goto out;
1128		}
1129		error = acevals_to_aent(vals, aent, list, owner, group,
1130		    isdir);
1131		if (error != 0)
1132			goto out;
1133		++aent;
1134	}
1135	/*
1136	 * CLASS_OBJ (aka ACL_MASK)
1137	 *
1138	 * An ACL_MASK is not fabricated if the ACL is a default ACL.
1139	 * This is to follow UFS's behavior.
1140	 */
1141	if ((list->hasmask) || (! list->dfacl_flag)) {
1142		if (list->hasmask) {
1143			uint32_t flips = ACE_POSIX_SUPPORTED_BITS;
1144			if (isdir)
1145				flips |= ACE_DELETE_CHILD;
1146			error = ace_mask_to_mode(list->acl_mask ^ flips,
1147			    &aent->a_perm, isdir);
1148			if (error != 0)
1149				goto out;
1150		} else {
1151			/* fabricate the ACL_MASK from the group permissions */
1152			error = ace_mask_to_mode(list->group_obj.allowed,
1153			    &aent->a_perm, isdir);
1154			if (error != 0)
1155				goto out;
1156		}
1157		aent->a_id = 0;
1158		aent->a_type = CLASS_OBJ | list->dfacl_flag;
1159		++aent;
1160	}
1161	/* OTHER_OBJ */
1162	if (!(list->other_obj.aent_type & OTHER_OBJ)) {
1163		error = EINVAL;
1164		goto out;
1165	}
1166	error = acevals_to_aent(&list->other_obj, aent, list, owner, group,
1167	    isdir);
1168	if (error != 0)
1169		goto out;
1170	++aent;
1171
1172	*aclentp = result;
1173	*aclcnt = resultcount;
1174
1175out:
1176	if (error != 0) {
1177		if (result != NULL)
1178			cacl_free(result, resultcount * sizeof (aclent_t));
1179	}
1180
1181	return (error);
1182}
1183
1184
1185/*
1186 * free all data associated with an ace_list
1187 */
1188static void
1189ace_list_free(ace_list_t *al)
1190{
1191	acevals_t *node;
1192	void *cookie;
1193
1194	if (al == NULL)
1195		return;
1196
1197	cookie = NULL;
1198	while ((node = avl_destroy_nodes(&al->user, &cookie)) != NULL)
1199		cacl_free(node, sizeof (acevals_t));
1200	cookie = NULL;
1201	while ((node = avl_destroy_nodes(&al->group, &cookie)) != NULL)
1202		cacl_free(node, sizeof (acevals_t));
1203
1204	avl_destroy(&al->user);
1205	avl_destroy(&al->group);
1206
1207	/* free the container itself */
1208	cacl_free(al, sizeof (ace_list_t));
1209}
1210
1211static int
1212acevals_compare(const void *va, const void *vb)
1213{
1214	const acevals_t *a = va, *b = vb;
1215
1216	if (a->key == b->key)
1217		return (0);
1218
1219	if (a->key > b->key)
1220		return (1);
1221
1222	else
1223		return (-1);
1224}
1225
1226/*
1227 * Convert a list of ace_t entries to equivalent regular and default
1228 * aclent_t lists.  Return error (ENOTSUP) when conversion is not possible.
1229 */
1230static int
1231ln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group,
1232    aclent_t **aclentp, int *aclcnt, aclent_t **dfaclentp, int *dfaclcnt,
1233    boolean_t isdir)
1234{
1235	int error = 0;
1236	ace_t *acep;
1237	uint32_t bits;
1238	int i;
1239	ace_list_t *normacl = NULL, *dfacl = NULL, *acl;
1240	acevals_t *vals;
1241
1242	*aclentp = NULL;
1243	*aclcnt = 0;
1244	*dfaclentp = NULL;
1245	*dfaclcnt = 0;
1246
1247	/* we need at least user_obj, group_obj, and other_obj */
1248	if (n < 6) {
1249		error = ENOTSUP;
1250		goto out;
1251	}
1252	if (ace == NULL) {
1253		error = EINVAL;
1254		goto out;
1255	}
1256
1257	error = cacl_malloc((void **)&normacl, sizeof (ace_list_t));
1258	if (error != 0)
1259		goto out;
1260
1261	avl_create(&normacl->user, acevals_compare, sizeof (acevals_t),
1262	    offsetof(acevals_t, avl));
1263	avl_create(&normacl->group, acevals_compare, sizeof (acevals_t),
1264	    offsetof(acevals_t, avl));
1265
1266	ace_list_init(normacl, 0);
1267
1268	error = cacl_malloc((void **)&dfacl, sizeof (ace_list_t));
1269	if (error != 0)
1270		goto out;
1271
1272	avl_create(&dfacl->user, acevals_compare, sizeof (acevals_t),
1273	    offsetof(acevals_t, avl));
1274	avl_create(&dfacl->group, acevals_compare, sizeof (acevals_t),
1275	    offsetof(acevals_t, avl));
1276	ace_list_init(dfacl, ACL_DEFAULT);
1277
1278	/* process every ace_t... */
1279	for (i = 0; i < n; i++) {
1280		acep = &ace[i];
1281
1282		/* rule out certain cases quickly */
1283		error = ace_to_aent_legal(acep);
1284		if (error != 0)
1285			goto out;
1286
1287		/*
1288		 * Turn off these bits in order to not have to worry about
1289		 * them when doing the checks for compliments.
1290		 */
1291		acep->a_access_mask &= ~(ACE_WRITE_OWNER | ACE_DELETE |
1292		    ACE_SYNCHRONIZE | ACE_WRITE_ATTRIBUTES |
1293		    ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS);
1294
1295		/* see if this should be a regular or default acl */
1296		bits = acep->a_flags &
1297		    (ACE_INHERIT_ONLY_ACE |
1298		    ACE_FILE_INHERIT_ACE |
1299		    ACE_DIRECTORY_INHERIT_ACE);
1300		if (bits != 0) {
1301			/* all or nothing on these inherit bits */
1302			if (bits != (ACE_INHERIT_ONLY_ACE |
1303			    ACE_FILE_INHERIT_ACE |
1304			    ACE_DIRECTORY_INHERIT_ACE)) {
1305				error = ENOTSUP;
1306				goto out;
1307			}
1308			acl = dfacl;
1309		} else {
1310			acl = normacl;
1311		}
1312
1313		if ((acep->a_flags & ACE_OWNER)) {
1314			if (acl->state > ace_user_obj) {
1315				error = ENOTSUP;
1316				goto out;
1317			}
1318			acl->state = ace_user_obj;
1319			acl->seen |= USER_OBJ;
1320			vals = &acl->user_obj;
1321			vals->aent_type = USER_OBJ | acl->dfacl_flag;
1322		} else if ((acep->a_flags & ACE_EVERYONE)) {
1323			acl->state = ace_other_obj;
1324			acl->seen |= OTHER_OBJ;
1325			vals = &acl->other_obj;
1326			vals->aent_type = OTHER_OBJ | acl->dfacl_flag;
1327		} else if (acep->a_flags & ACE_IDENTIFIER_GROUP) {
1328			if (acl->state > ace_group) {
1329				error = ENOTSUP;
1330				goto out;
1331			}
1332			if ((acep->a_flags & ACE_GROUP)) {
1333				acl->seen |= GROUP_OBJ;
1334				vals = &acl->group_obj;
1335				vals->aent_type = GROUP_OBJ | acl->dfacl_flag;
1336			} else {
1337				acl->seen |= GROUP;
1338				vals = acevals_find(acep, &acl->group,
1339				    &acl->numgroups);
1340				if (vals == NULL) {
1341					error = ENOMEM;
1342					goto out;
1343				}
1344				vals->aent_type = GROUP | acl->dfacl_flag;
1345			}
1346			acl->state = ace_group;
1347		} else {
1348			if (acl->state > ace_user) {
1349				error = ENOTSUP;
1350				goto out;
1351			}
1352			acl->state = ace_user;
1353			acl->seen |= USER;
1354			vals = acevals_find(acep, &acl->user,
1355			    &acl->numusers);
1356			if (vals == NULL) {
1357				error = ENOMEM;
1358				goto out;
1359			}
1360			vals->aent_type = USER | acl->dfacl_flag;
1361		}
1362
1363		if (!(acl->state > ace_unused)) {
1364			error = EINVAL;
1365			goto out;
1366		}
1367
1368		if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
1369			/* no more than one allowed per aclent_t */
1370			if (vals->allowed != ACE_MASK_UNDEFINED) {
1371				error = ENOTSUP;
1372				goto out;
1373			}
1374			vals->allowed = acep->a_access_mask;
1375		} else {
1376			/*
1377			 * it's a DENY; if there was a previous DENY, it
1378			 * must have been an ACL_MASK.
1379			 */
1380			if (vals->denied != ACE_MASK_UNDEFINED) {
1381				/* ACL_MASK is for USER and GROUP only */
1382				if ((acl->state != ace_user) &&
1383				    (acl->state != ace_group)) {
1384					error = ENOTSUP;
1385					goto out;
1386				}
1387
1388				if (! acl->hasmask) {
1389					acl->hasmask = 1;
1390					acl->acl_mask = vals->denied;
1391				/* check for mismatched ACL_MASK emulations */
1392				} else if (acl->acl_mask != vals->denied) {
1393					error = ENOTSUP;
1394					goto out;
1395				}
1396				vals->mask = vals->denied;
1397			}
1398			vals->denied = acep->a_access_mask;
1399		}
1400	}
1401
1402	/* done collating; produce the aclent_t lists */
1403	if (normacl->state != ace_unused) {
1404		error = ace_list_to_aent(normacl, aclentp, aclcnt,
1405		    owner, group, isdir);
1406		if (error != 0) {
1407			goto out;
1408		}
1409	}
1410	if (dfacl->state != ace_unused) {
1411		error = ace_list_to_aent(dfacl, dfaclentp, dfaclcnt,
1412		    owner, group, isdir);
1413		if (error != 0) {
1414			goto out;
1415		}
1416	}
1417
1418out:
1419	if (normacl != NULL)
1420		ace_list_free(normacl);
1421	if (dfacl != NULL)
1422		ace_list_free(dfacl);
1423
1424	return (error);
1425}
1426
1427static int
1428convert_ace_to_aent(ace_t *acebufp, int acecnt, boolean_t isdir,
1429    uid_t owner, gid_t group, aclent_t **retaclentp, int *retaclcnt)
1430{
1431	int error = 0;
1432	aclent_t *aclentp, *dfaclentp;
1433	int aclcnt, dfaclcnt;
1434	int aclsz, dfaclsz;
1435
1436	error = ln_ace_to_aent(acebufp, acecnt, owner, group,
1437	    &aclentp, &aclcnt, &dfaclentp, &dfaclcnt, isdir);
1438
1439	if (error)
1440		return (error);
1441
1442
1443	if (dfaclcnt != 0) {
1444		/*
1445		 * Slap aclentp and dfaclentp into a single array.
1446		 */
1447		aclsz = sizeof (aclent_t) * aclcnt;
1448		dfaclsz = sizeof (aclent_t) * dfaclcnt;
1449		aclentp = cacl_realloc(aclentp, aclsz, aclsz + dfaclsz);
1450		if (aclentp != NULL) {
1451			(void) memcpy(aclentp + aclcnt, dfaclentp, dfaclsz);
1452		} else {
1453			error = ENOMEM;
1454		}
1455	}
1456
1457	if (aclentp) {
1458		*retaclentp = aclentp;
1459		*retaclcnt = aclcnt + dfaclcnt;
1460	}
1461
1462	if (dfaclentp)
1463		cacl_free(dfaclentp, dfaclsz);
1464
1465	return (error);
1466}
1467
1468
1469int
1470acl_translate(acl_t *aclp, int target_flavor, boolean_t isdir, uid_t owner,
1471    gid_t group)
1472{
1473	int aclcnt;
1474	void *acldata;
1475	int error;
1476
1477	/*
1478	 * See if we need to translate
1479	 */
1480	if ((target_flavor == _ACL_ACE_ENABLED && aclp->acl_type == ACE_T) ||
1481	    (target_flavor == _ACL_ACLENT_ENABLED &&
1482	    aclp->acl_type == ACLENT_T))
1483		return (0);
1484
1485	if (target_flavor == -1) {
1486		error = EINVAL;
1487		goto out;
1488	}
1489
1490	if (target_flavor ==  _ACL_ACE_ENABLED &&
1491	    aclp->acl_type == ACLENT_T) {
1492		error = convert_aent_to_ace(aclp->acl_aclp,
1493		    aclp->acl_cnt, isdir, (ace_t **)&acldata, &aclcnt);
1494		if (error)
1495			goto out;
1496
1497	} else if (target_flavor == _ACL_ACLENT_ENABLED &&
1498	    aclp->acl_type == ACE_T) {
1499		error = convert_ace_to_aent(aclp->acl_aclp, aclp->acl_cnt,
1500		    isdir, owner, group, (aclent_t **)&acldata, &aclcnt);
1501		if (error)
1502			goto out;
1503	} else {
1504		error = ENOTSUP;
1505		goto out;
1506	}
1507
1508	/*
1509	 * replace old acl with newly translated acl
1510	 */
1511	cacl_free(aclp->acl_aclp, aclp->acl_cnt * aclp->acl_entry_size);
1512	aclp->acl_aclp = acldata;
1513	aclp->acl_cnt = aclcnt;
1514	if (target_flavor == _ACL_ACE_ENABLED) {
1515		aclp->acl_type = ACE_T;
1516		aclp->acl_entry_size = sizeof (ace_t);
1517	} else {
1518		aclp->acl_type = ACLENT_T;
1519		aclp->acl_entry_size = sizeof (aclent_t);
1520	}
1521	return (0);
1522
1523out:
1524
1525#if !defined(_KERNEL)
1526	errno = error;
1527	return (-1);
1528#else
1529	return (error);
1530#endif
1531}
1532#endif /* !_KERNEL */
1533
1534#define	SET_ACE(acl, index, who, mask, type, flags) { \
1535	acl[0][index].a_who = (uint32_t)who; \
1536	acl[0][index].a_type = type; \
1537	acl[0][index].a_flags = flags; \
1538	acl[0][index++].a_access_mask = mask; \
1539}
1540
1541void
1542acl_trivial_access_masks(mode_t mode, boolean_t isdir, trivial_acl_t *masks)
1543{
1544	uint32_t read_mask = ACE_READ_DATA;
1545	uint32_t write_mask = ACE_WRITE_DATA|ACE_APPEND_DATA;
1546	uint32_t execute_mask = ACE_EXECUTE;
1547
1548	(void) isdir;	/* will need this later */
1549
1550	masks->deny1 = 0;
1551	if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
1552		masks->deny1 |= read_mask;
1553	if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH)))
1554		masks->deny1 |= write_mask;
1555	if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH)))
1556		masks->deny1 |= execute_mask;
1557
1558	masks->deny2 = 0;
1559	if (!(mode & S_IRGRP) && (mode & S_IROTH))
1560		masks->deny2 |= read_mask;
1561	if (!(mode & S_IWGRP) && (mode & S_IWOTH))
1562		masks->deny2 |= write_mask;
1563	if (!(mode & S_IXGRP) && (mode & S_IXOTH))
1564		masks->deny2 |= execute_mask;
1565
1566	masks->allow0 = 0;
1567	if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH)))
1568		masks->allow0 |= read_mask;
1569	if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH)))
1570		masks->allow0 |= write_mask;
1571	if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH)))
1572		masks->allow0 |= execute_mask;
1573
1574	masks->owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL|
1575	    ACE_WRITE_NAMED_ATTRS|ACE_READ_ACL|ACE_READ_ATTRIBUTES|
1576	    ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE;
1577	if (mode & S_IRUSR)
1578		masks->owner |= read_mask;
1579	if (mode & S_IWUSR)
1580		masks->owner |= write_mask;
1581	if (mode & S_IXUSR)
1582		masks->owner |= execute_mask;
1583
1584	masks->group = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
1585	    ACE_SYNCHRONIZE;
1586	if (mode & S_IRGRP)
1587		masks->group |= read_mask;
1588	if (mode & S_IWGRP)
1589		masks->group |= write_mask;
1590	if (mode & S_IXGRP)
1591		masks->group |= execute_mask;
1592
1593	masks->everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
1594	    ACE_SYNCHRONIZE;
1595	if (mode & S_IROTH)
1596		masks->everyone |= read_mask;
1597	if (mode & S_IWOTH)
1598		masks->everyone |= write_mask;
1599	if (mode & S_IXOTH)
1600		masks->everyone |= execute_mask;
1601}
1602
1603int
1604acl_trivial_create(mode_t mode, boolean_t isdir, ace_t **acl, int *count)
1605{
1606	int		index = 0;
1607	int		error;
1608	trivial_acl_t	masks;
1609
1610	*count = 3;
1611	acl_trivial_access_masks(mode, isdir, &masks);
1612
1613	if (masks.allow0)
1614		(*count)++;
1615	if (masks.deny1)
1616		(*count)++;
1617	if (masks.deny2)
1618		(*count)++;
1619
1620	if ((error = cacl_malloc((void **)acl, *count * sizeof (ace_t))) != 0)
1621		return (error);
1622
1623	if (masks.allow0) {
1624		SET_ACE(acl, index, -1, masks.allow0,
1625		    ACE_ACCESS_ALLOWED_ACE_TYPE, ACE_OWNER);
1626	}
1627	if (masks.deny1) {
1628		SET_ACE(acl, index, -1, masks.deny1,
1629		    ACE_ACCESS_DENIED_ACE_TYPE, ACE_OWNER);
1630	}
1631	if (masks.deny2) {
1632		SET_ACE(acl, index, -1, masks.deny2,
1633		    ACE_ACCESS_DENIED_ACE_TYPE, ACE_GROUP|ACE_IDENTIFIER_GROUP);
1634	}
1635
1636	SET_ACE(acl, index, -1, masks.owner, ACE_ACCESS_ALLOWED_ACE_TYPE,
1637	    ACE_OWNER);
1638	SET_ACE(acl, index, -1, masks.group, ACE_ACCESS_ALLOWED_ACE_TYPE,
1639	    ACE_IDENTIFIER_GROUP|ACE_GROUP);
1640	SET_ACE(acl, index, -1, masks.everyone, ACE_ACCESS_ALLOWED_ACE_TYPE,
1641	    ACE_EVERYONE);
1642
1643	return (0);
1644}
1645
1646/*
1647 * ace_trivial:
1648 * determine whether an ace_t acl is trivial
1649 *
1650 * Trivialness implies that the acl is composed of only
1651 * owner, group, everyone entries.  ACL can't
1652 * have read_acl denied, and write_owner/write_acl/write_attributes
1653 * can only be owner@ entry.
1654 */
1655int
1656ace_trivial_common(void *acep, int aclcnt,
1657    uintptr_t (*walk)(void *, uintptr_t, int aclcnt,
1658    uint16_t *, uint16_t *, uint32_t *))
1659{
1660	uint16_t flags;
1661	uint32_t mask;
1662	uint16_t type;
1663	uintptr_t cookie = 0;
1664
1665	while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))) {
1666		switch (flags & ACE_TYPE_FLAGS) {
1667		case ACE_OWNER:
1668		case ACE_GROUP|ACE_IDENTIFIER_GROUP:
1669		case ACE_EVERYONE:
1670			break;
1671		default:
1672			return (1);
1673
1674		}
1675
1676		if (flags & (ACE_FILE_INHERIT_ACE|
1677		    ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
1678		    ACE_INHERIT_ONLY_ACE))
1679			return (1);
1680
1681		/*
1682		 * Special check for some special bits
1683		 *
1684		 * Don't allow anybody to deny reading basic
1685		 * attributes or a files ACL.
1686		 */
1687		if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&
1688		    (type == ACE_ACCESS_DENIED_ACE_TYPE))
1689			return (1);
1690
1691		/*
1692		 * Delete permissions are never set by default
1693		 */
1694		if (mask & (ACE_DELETE|ACE_DELETE_CHILD))
1695			return (1);
1696		/*
1697		 * only allow owner@ to have
1698		 * write_acl/write_owner/write_attributes/write_xattr/
1699		 */
1700		if (type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
1701		    (!(flags & ACE_OWNER) && (mask &
1702		    (ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES|
1703		    ACE_WRITE_NAMED_ATTRS))))
1704			return (1);
1705
1706	}
1707	return (0);
1708}
1709