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