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