xref: /netbsd-src/external/cddl/osnet/dist/common/acl/acl_common.c (revision ba2539a9805a0544ff82c0003cc02fe1eee5603d)
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 
121 typedef 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 
129 typedef 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 
138 typedef 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  */
161 void
ksort(caddr_t v,int n,int s,int (* f)())162 ksort(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  */
198 int
cmp2acls(void * a,void * b)199 cmp2acls(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*/
224 static void *
cacl_realloc(void * ptr,size_t size,size_t new_size)225 cacl_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 
239 static int
cacl_malloc(void ** ptr,size_t size)240 cacl_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*/
255 static void
cacl_free(void * ptr,size_t size)256 cacl_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)
266 acl_t *
acl_alloc(enum acl_type type)267 acl_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  */
296 void
acl_free(acl_t * aclp)297 acl_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 
312 static uint32_t
access_mask_set(int haswriteperm,int hasreadperm,int isowner,int isallow)313 access_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  */
379 static uint32_t
mode_to_ace_access(mode_t mode,boolean_t isdir,int isowner,int isallow)380 mode_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  */
434 static void
ace_make_deny(ace_t * allow,ace_t * deny,int isdir,int isowner)435 ace_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  */
458 static int
ln_aent_preprocess(aclent_t * aclent,int n,int * hasmask,mode_t * mask,int * numuser,int * numgroup,int * needsort)459 ln_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 
498 out:
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  */
507 static int
ln_aent_to_ace(aclent_t * aclent,int n,ace_t ** acepp,int * rescount,int isdir)508 ln_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 
663 out:
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 
673 static int
convert_aent_to_ace(aclent_t * aclentp,int aclcnt,boolean_t isdir,ace_t ** retacep,int * retacecnt)674 convert_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 
737 static int
ace_mask_to_mode(uint32_t mask,o_mode_t * modep,boolean_t isdir)738 ace_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 
768 out:
769 	return (error);
770 }
771 
772 static void
acevals_init(acevals_t * vals,uid_t key)773 acevals_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 
782 static void
ace_list_init(ace_list_t * al,int dfacl_flag)783 ace_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  */
803 static acevals_t *
acevals_find(ace_t * ace,avl_tree_t * avl,int * num)804 acevals_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 
825 static int
access_mask_check(ace_t * acep,int mask_bit,int isowner)826 access_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 
930 static int
ace_to_aent_legal(ace_t * acep)931 ace_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 
1030 out:
1031 	return (error);
1032 }
1033 
1034 static int
ace_allow_to_mode(uint32_t mask,o_mode_t * modep,boolean_t isdir)1035 ace_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 
1046 static int
acevals_to_aent(acevals_t * vals,aclent_t * dest,ace_list_t * list,uid_t owner,gid_t group,boolean_t isdir)1047 acevals_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 
1081 out:
1082 	return (error);
1083 }
1084 
1085 
1086 static int
ace_list_to_aent(ace_list_t * list,aclent_t ** aclentp,int * aclcnt,uid_t owner,gid_t group,boolean_t isdir)1087 ace_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 
1210 out:
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  */
1223 static void
ace_list_free(ace_list_t * al)1224 ace_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 
1246 static int
acevals_compare(const void * va,const void * vb)1247 acevals_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  */
1265 static int
ln_ace_to_aent(ace_t * ace,int n,uid_t owner,gid_t group,aclent_t ** aclentp,int * aclcnt,aclent_t ** dfaclentp,int * dfaclcnt,boolean_t isdir)1266 ln_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 
1453 out:
1454 	if (normacl != NULL)
1455 		ace_list_free(normacl);
1456 	if (dfacl != NULL)
1457 		ace_list_free(dfacl);
1458 
1459 	return (error);
1460 }
1461 
1462 static int
convert_ace_to_aent(ace_t * acebufp,int acecnt,boolean_t isdir,uid_t owner,gid_t group,aclent_t ** retaclentp,int * retaclcnt)1463 convert_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 
1504 int
acl_translate(acl_t * aclp,int target_flavor,boolean_t isdir,uid_t owner,gid_t group)1505 acl_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 
1558 out:
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 
1576 void
acl_trivial_access_masks(mode_t mode,boolean_t isdir,trivial_acl_t * masks)1577 acl_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 
1638 int
acl_trivial_create(mode_t mode,boolean_t isdir,ace_t ** acl,int * count)1639 acl_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  */
1690 int
ace_trivial_common(void * acep,int aclcnt,uint64_t (* walk)(void *,uint64_t,int aclcnt,uint16_t *,uint16_t *,uint32_t *))1691 ace_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 
1745 uint64_t
ace_walk(void * datap,uint64_t cookie,int aclcnt,uint16_t * flags,uint16_t * type,uint32_t * mask)1746 ace_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 
1761 int
ace_trivial(ace_t * acep,int aclcnt)1762 ace_trivial(ace_t *acep, int aclcnt)
1763 {
1764 	return (ace_trivial_common(acep, aclcnt, ace_walk));
1765 }
1766