]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/cddl/contrib/opensolaris/common/acl/acl_common.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / cddl / contrib / opensolaris / common / acl / acl_common.c
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
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
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 *
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1762 ace_trivial(ace_t *acep, int aclcnt)
1763 {
1764         return (ace_trivial_common(acep, aclcnt, ace_walk));
1765 }