1 /*
2 * Copyright 2016 Chris Torek <torek@ixsystems.com>
3 * All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted providing that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/acl.h>
33 #include <sys/stat.h>
34
35 #ifdef __illumos__
36 #include <sys/sysmacros.h>
37 #endif
38
39 #include "lib9p.h"
40 #include "lib9p_impl.h"
41 #include "genacl.h"
42 #include "fid.h"
43 #include "log.h"
44
45 #ifndef __illumos__
46 typedef int econvertfn(acl_entry_t, struct l9p_ace *);
47 #endif
48
49 #ifdef __FreeBSD__
50 static struct l9p_acl *l9p_new_acl(uint32_t acetype, uint32_t aceasize);
51 static struct l9p_acl *l9p_growacl(struct l9p_acl *acl, uint32_t aceasize);
52 static int l9p_count_aces(acl_t sysacl);
53 static struct l9p_acl *l9p_sysacl_to_acl(int, acl_t, econvertfn *);
54 #endif
55 static bool l9p_ingroup(gid_t tid, gid_t gid, gid_t *gids, size_t ngids);
56 static int l9p_check_aces(int32_t mask, struct l9p_acl *acl, struct stat *st,
57 uid_t uid, gid_t gid, gid_t *gids, size_t ngids);
58
59 void
l9p_acl_free(struct l9p_acl * acl)60 l9p_acl_free(struct l9p_acl *acl)
61 {
62
63 free(acl);
64 }
65
66 /*
67 * Is the given group ID tid (test-id) any of the gid's in agids?
68 */
69 static bool
l9p_ingroup(gid_t tid,gid_t gid,gid_t * gids,size_t ngids)70 l9p_ingroup(gid_t tid, gid_t gid, gid_t *gids, size_t ngids)
71 {
72 size_t i;
73
74 if (tid == gid)
75 return (true);
76 for (i = 0; i < ngids; i++)
77 if (tid == gids[i])
78 return (true);
79 return (false);
80 }
81
82 /* #define ACE_DEBUG */
83
84 /*
85 * Note that NFSv4 tests are done on a "first match" basis.
86 * That is, we check each ACE sequentially until we run out
87 * of ACEs, or find something explicitly denied (DENIED!),
88 * or have cleared out all our attempt-something bits. Once
89 * we come across an ALLOW entry for the bits we're trying,
90 * we clear those from the bits we're still looking for, in
91 * the order they appear.
92 *
93 * The result is either "definitely allowed" (we cleared
94 * all the bits), "definitely denied" (we hit a deny with
95 * some or all of the bits), or "unspecified". We
96 * represent these three states as +1 (positive = yes = allow),
97 * -1 (negative = no = denied), or 0 (no strong answer).
98 *
99 * For our caller's convenience, if we are called with a
100 * mask of 0, we return 0 (no answer).
101 */
102 static int
l9p_check_aces(int32_t mask,struct l9p_acl * acl,struct stat * st,uid_t uid,gid_t gid,gid_t * gids,size_t ngids)103 l9p_check_aces(int32_t mask, struct l9p_acl *acl, struct stat *st,
104 uid_t uid, gid_t gid, gid_t *gids, size_t ngids)
105 {
106 uint32_t i;
107 struct l9p_ace *ace;
108 #ifdef ACE_DEBUG
109 const char *acetype, *allowdeny;
110 bool show_tid;
111 #endif
112 bool match;
113 uid_t tid;
114
115 if (mask == 0)
116 return (0);
117
118 for (i = 0; mask != 0 && i < acl->acl_nace; i++) {
119 ace = &acl->acl_aces[i];
120 switch (ace->ace_type) {
121 case L9P_ACET_ACCESS_ALLOWED:
122 case L9P_ACET_ACCESS_DENIED:
123 break;
124 default:
125 /* audit, alarm - ignore */
126 continue;
127 }
128 #ifdef ACE_DEBUG
129 show_tid = false;
130 #endif
131 if (ace->ace_flags & L9P_ACEF_OWNER) {
132 #ifdef ACE_DEBUG
133 acetype = "OWNER@";
134 #endif
135 match = st->st_uid == uid;
136 } else if (ace->ace_flags & L9P_ACEF_GROUP) {
137 #ifdef ACE_DEBUG
138 acetype = "GROUP@";
139 #endif
140 match = l9p_ingroup(st->st_gid, gid, gids, ngids);
141 } else if (ace->ace_flags & L9P_ACEF_EVERYONE) {
142 #ifdef ACE_DEBUG
143 acetype = "EVERYONE@";
144 #endif
145 match = true;
146 } else {
147 if (ace->ace_idsize != sizeof(tid))
148 continue;
149 #ifdef ACE_DEBUG
150 show_tid = true;
151 #endif
152 memcpy(&tid, &ace->ace_idbytes, sizeof(tid));
153 if (ace->ace_flags & L9P_ACEF_IDENTIFIER_GROUP) {
154 #ifdef ACE_DEBUG
155 acetype = "group";
156 #endif
157 match = l9p_ingroup(tid, gid, gids, ngids);
158 } else {
159 #ifdef ACE_DEBUG
160 acetype = "user";
161 #endif
162 match = tid == uid;
163 }
164 }
165 /*
166 * If this ACE applies to us, check remaining bits.
167 * If any of those bits also apply, check the type:
168 * DENY means "stop now", ALLOW means allow these bits
169 * and keep checking.
170 */
171 #ifdef ACE_DEBUG
172 allowdeny = ace->ace_type == L9P_ACET_ACCESS_DENIED ?
173 "deny" : "allow";
174 #endif
175 if (match && (ace->ace_mask & (uint32_t)mask) != 0) {
176 #ifdef ACE_DEBUG
177 if (show_tid)
178 L9P_LOG(L9P_DEBUG,
179 "ACE: %s %s %d: mask 0x%x ace_mask 0x%x",
180 allowdeny, acetype, (int)tid,
181 (u_int)mask, (u_int)ace->ace_mask);
182 else
183 L9P_LOG(L9P_DEBUG,
184 "ACE: %s %s: mask 0x%x ace_mask 0x%x",
185 allowdeny, acetype,
186 (u_int)mask, (u_int)ace->ace_mask);
187 #endif
188 if (ace->ace_type == L9P_ACET_ACCESS_DENIED)
189 return (-1);
190 mask &= ~ace->ace_mask;
191 #ifdef ACE_DEBUG
192 L9P_LOG(L9P_DEBUG, "clear 0x%x: now mask=0x%x",
193 (u_int)ace->ace_mask, (u_int)mask);
194 #endif
195 } else {
196 #ifdef ACE_DEBUG
197 if (show_tid)
198 L9P_LOG(L9P_DEBUG,
199 "ACE: SKIP %s %s %d: "
200 "match %d mask 0x%x ace_mask 0x%x",
201 allowdeny, acetype, (int)tid,
202 (int)match, (u_int)mask,
203 (u_int)ace->ace_mask);
204 else
205 L9P_LOG(L9P_DEBUG,
206 "ACE: SKIP %s %s: "
207 "match %d mask 0x%x ace_mask 0x%x",
208 allowdeny, acetype,
209 (int)match, (u_int)mask,
210 (u_int)ace->ace_mask);
211 #endif
212 }
213 }
214
215 /* Return 1 if access definitely granted. */
216 #ifdef ACE_DEBUG
217 L9P_LOG(L9P_DEBUG, "ACE: end of ACEs, mask now 0x%x: %s",
218 mask, mask ? "no-definitive-answer" : "ALLOW");
219 #endif
220 return (mask == 0 ? 1 : 0);
221 }
222
223 /*
224 * Test against ACLs.
225 *
226 * The return value is normally 0 (access allowed) or EPERM
227 * (access denied), so it could just be a boolean....
228 *
229 * For "make new dir in dir" and "remove dir in dir", you must
230 * set the mask to test the directory permissions (not ADD_FILE but
231 * ADD_SUBDIRECTORY, and DELETE_CHILD). For "make new file in dir"
232 * you must set the opmask to test file ADD_FILE.
233 *
234 * The L9P_ACE_DELETE flag means "can delete this thing"; it's not
235 * clear whether it should override the parent directory's ACL if
236 * any. In our case it does not, but a caller may try
237 * L9P_ACE_DELETE_CHILD (separately, on its own) and then a
238 * (second, separate) L9P_ACE_DELETE, to make the permissions work
239 * as "or" instead of "and".
240 *
241 * Pass a NULL parent/pstat if they are not applicable, e.g.,
242 * for doing operations on an existing file, such as reading or
243 * writing data or attributes. Pass in a null child/cstat if
244 * that's not applicable, such as creating a new file/dir.
245 *
246 * NB: it's probably wise to allow the owner of any file to update
247 * the ACLs of that file, but we leave that test to the caller.
248 */
l9p_acl_check_access(int32_t opmask,struct l9p_acl_check_args * args)249 int l9p_acl_check_access(int32_t opmask, struct l9p_acl_check_args *args)
250 {
251 struct l9p_acl *parent, *child;
252 struct stat *pstat, *cstat;
253 int32_t pop, cop;
254 size_t ngids;
255 uid_t uid;
256 gid_t gid, *gids;
257 int panswer, canswer;
258
259 assert(opmask != 0);
260 parent = args->aca_parent;
261 pstat = args->aca_pstat;
262 child = args->aca_child;
263 cstat = args->aca_cstat;
264 uid = args->aca_uid;
265 gid = args->aca_gid;
266 gids = args->aca_groups;
267 ngids = args->aca_ngroups;
268
269 #ifdef ACE_DEBUG
270 L9P_LOG(L9P_DEBUG,
271 "l9p_acl_check_access: opmask=0x%x uid=%ld gid=%ld ngids=%zd",
272 (u_int)opmask, (long)uid, (long)gid, ngids);
273 #endif
274 /*
275 * If caller said "superuser semantics", check that first.
276 * Note that we apply them regardless of ACLs.
277 */
278 if (uid == 0 && args->aca_superuser)
279 return (0);
280
281 /*
282 * If told to ignore ACLs and use only stat-based permissions,
283 * discard any non-NULL ACL pointers.
284 *
285 * This will need some fancying up when we support POSIX ACLs.
286 */
287 if ((args->aca_aclmode & L9P_ACM_NFS_ACL) == 0)
288 parent = child = NULL;
289
290 assert(parent == NULL || parent->acl_acetype == L9P_ACLTYPE_NFSv4);
291 assert(parent == NULL || pstat != NULL);
292 assert(child == NULL || child->acl_acetype == L9P_ACLTYPE_NFSv4);
293 assert(child == NULL || cstat != NULL);
294 assert(pstat != NULL || cstat != NULL);
295
296 /*
297 * If the operation is UNLINK we should have either both ACLs
298 * or no ACLs, but we won't require that here.
299 *
300 * If a parent ACL is supplied, it's a directory by definition.
301 * Make sure we're allowed to do this there, whatever this is.
302 * If a child ACL is supplied, check it too. Note that the
303 * DELETE permission only applies in the child though, not
304 * in the parent, and the DELETE_CHILD only applies in the
305 * parent.
306 */
307 pop = cop = opmask;
308 if (parent != NULL || pstat != NULL) {
309 /*
310 * Remove child-only bits from parent op and
311 * parent-only bits from child op.
312 *
313 * L9P_ACE_DELETE is child-only.
314 *
315 * L9P_ACE_DELETE_CHILD is parent-only, and three data
316 * access bits overlap with three directory access bits.
317 * We should have child==NULL && cstat==NULL, so the
318 * three data bits should be redundant, but it's
319 * both trivial and safest to remove them anyway.
320 */
321 pop &= ~L9P_ACE_DELETE;
322 cop &= ~(L9P_ACE_DELETE_CHILD | L9P_ACE_LIST_DIRECTORY |
323 L9P_ACE_ADD_FILE | L9P_ACE_ADD_SUBDIRECTORY);
324 } else {
325 /*
326 * Remove child-only bits from parent op. We need
327 * not bother since we just found we have no parent
328 * and no pstat, and hence won't actually *use* pop.
329 *
330 * pop &= ~(L9P_ACE_READ_DATA | L9P_ACE_WRITE_DATA |
331 * L9P_ACE_APPEND_DATA);
332 */
333 }
334 panswer = 0;
335 canswer = 0;
336 if (parent != NULL)
337 panswer = l9p_check_aces(pop, parent, pstat,
338 uid, gid, gids, ngids);
339 if (child != NULL)
340 canswer = l9p_check_aces(cop, child, cstat,
341 uid, gid, gids, ngids);
342
343 if (panswer || canswer) {
344 /*
345 * Got a definitive answer from parent and/or
346 * child ACLs. We're not quite done yet though.
347 */
348 if (opmask == L9P_ACOP_UNLINK) {
349 /*
350 * For UNLINK, we can get an allow from child
351 * and deny from parent, or vice versa. It's
352 * not 100% clear how to handle the two-answer
353 * case. ZFS says that if either says "allow",
354 * we allow, and if both definitely say "deny",
355 * we deny. This makes sense, so we do that
356 * here for all cases, even "strict".
357 */
358 if (panswer > 0 || canswer > 0)
359 return (0);
360 if (panswer < 0 && canswer < 0)
361 return (EPERM);
362 /* non-definitive answer from one! move on */
363 } else {
364 /*
365 * Have at least one definitive answer, and
366 * should have only one; obey whichever
367 * one it is.
368 */
369 if (panswer)
370 return (panswer < 0 ? EPERM : 0);
371 return (canswer < 0 ? EPERM : 0);
372 }
373 }
374
375 /*
376 * No definitive answer from ACLs alone. Check for ZFS style
377 * permissions checking and an "UNLINK" operation under ACLs.
378 * If so, find write-and-execute permission on parent.
379 * Note that WRITE overlaps with ADD_FILE -- that's ZFS's
380 * way of saying "allow write to dir" -- but EXECUTE is
381 * separate from LIST_DIRECTORY, so that's at least a little
382 * bit cleaner.
383 *
384 * Note also that only a definitive yes (both bits are
385 * explicitly allowed) results in granting unlink, and
386 * a definitive no (at least one bit explicitly denied)
387 * results in EPERM. Only "no answer" moves on.
388 */
389 if ((args->aca_aclmode & L9P_ACM_ZFS_ACL) &&
390 opmask == L9P_ACOP_UNLINK && parent != NULL) {
391 panswer = l9p_check_aces(L9P_ACE_ADD_FILE | L9P_ACE_EXECUTE,
392 parent, pstat, uid, gid, gids, ngids);
393 if (panswer)
394 return (panswer < 0 ? EPERM : 0);
395 }
396
397 /*
398 * No definitive answer from ACLs.
399 *
400 * Try POSIX style rwx permissions if allowed. This should
401 * be rare, occurring mainly when caller supplied no ACLs
402 * or set the mode to suppress them.
403 *
404 * The stat to check is the parent's if we don't have a child
405 * (i.e., this is a dir op), or if the DELETE_CHILD bit is set
406 * (i.e., this is an unlink or similar). Otherwise it's the
407 * child's.
408 */
409 if (args->aca_aclmode & L9P_ACM_STAT_MODE) {
410 struct stat *st;
411 int rwx, bits;
412
413 rwx = l9p_ace_mask_to_rwx(opmask);
414 if ((st = cstat) == NULL || (opmask & L9P_ACE_DELETE_CHILD))
415 st = pstat;
416 if (uid == st->st_uid)
417 bits = (st->st_mode >> 6) & 7;
418 else if (l9p_ingroup(st->st_gid, gid, gids, ngids))
419 bits = (st->st_mode >> 3) & 7;
420 else
421 bits = st->st_mode & 7;
422 /*
423 * If all the desired bits are set, we're OK.
424 */
425 if ((rwx & bits) == rwx)
426 return (0);
427 }
428
429 /* all methods have failed, return EPERM */
430 return (EPERM);
431 }
432
433 /*
434 * Collapse fancy ACL operation mask down to simple Unix bits.
435 *
436 * Directory operations don't map that well. However, listing
437 * a directory really does require read permission, and adding
438 * or deleting files really does require write permission, so
439 * this is probably sufficient.
440 */
441 int
l9p_ace_mask_to_rwx(int32_t opmask)442 l9p_ace_mask_to_rwx(int32_t opmask)
443 {
444 int rwx = 0;
445
446 if (opmask &
447 (L9P_ACE_READ_DATA | L9P_ACE_READ_NAMED_ATTRS |
448 L9P_ACE_READ_ATTRIBUTES | L9P_ACE_READ_ACL))
449 rwx |= 4;
450 if (opmask &
451 (L9P_ACE_WRITE_DATA | L9P_ACE_APPEND_DATA |
452 L9P_ACE_ADD_FILE | L9P_ACE_ADD_SUBDIRECTORY |
453 L9P_ACE_DELETE | L9P_ACE_DELETE_CHILD |
454 L9P_ACE_WRITE_NAMED_ATTRS | L9P_ACE_WRITE_ATTRIBUTES |
455 L9P_ACE_WRITE_ACL))
456 rwx |= 2;
457 if (opmask & L9P_ACE_EXECUTE)
458 rwx |= 1;
459 return (rwx);
460 }
461
462 #if defined(__FreeBSD__) || defined(__illumos__)
463 /*
464 * Allocate new ACL holder and ACEs.
465 */
466 static struct l9p_acl *
l9p_new_acl(uint32_t acetype,uint32_t aceasize)467 l9p_new_acl(uint32_t acetype, uint32_t aceasize)
468 {
469 struct l9p_acl *ret;
470 size_t asize, size;
471
472 asize = aceasize * sizeof(struct l9p_ace);
473 size = sizeof(struct l9p_acl) + asize;
474 ret = malloc(size);
475 if (ret != NULL) {
476 ret->acl_acetype = acetype;
477 ret->acl_nace = 0;
478 ret->acl_aceasize = aceasize;
479 }
480 return (ret);
481 }
482 #endif
483
484 #ifdef __FreeBSD__
485 /*
486 * Expand ACL to accomodate more entries.
487 *
488 * Currently won't shrink, only grow, so it's a fast no-op until
489 * we hit the allocated size. After that, it's best to grow in
490 * big chunks, or this will be O(n**2).
491 */
492 static struct l9p_acl *
l9p_growacl(struct l9p_acl * acl,uint32_t aceasize)493 l9p_growacl(struct l9p_acl *acl, uint32_t aceasize)
494 {
495 struct l9p_acl *tmp;
496 size_t asize, size;
497
498 if (acl->acl_aceasize < aceasize) {
499 asize = aceasize * sizeof(struct l9p_ace);
500 size = sizeof(struct l9p_acl) + asize;
501 tmp = realloc(acl, size);
502 if (tmp == NULL)
503 free(acl);
504 acl = tmp;
505 }
506 return (acl);
507 }
508
509 /*
510 * Annoyingly, there's no POSIX-standard way to count the number
511 * of ACEs in a system ACL other than to walk through them all.
512 * This is silly, but at least 2n is still O(n), and the walk is
513 * short. (If the system ACL mysteriously grows, we'll handle
514 * that OK via growacl(), too.)
515 */
516 static int
l9p_count_aces(acl_t sysacl)517 l9p_count_aces(acl_t sysacl)
518 {
519 acl_entry_t entry;
520 uint32_t n;
521 int id;
522
523 id = ACL_FIRST_ENTRY;
524 for (n = 0; acl_get_entry(sysacl, id, &entry) == 1; n++)
525 id = ACL_NEXT_ENTRY;
526
527 return ((int)n);
528 }
529
530 /*
531 * Create ACL with ACEs from the given acl_t. We use the given
532 * convert function on each ACE.
533 */
534 static struct l9p_acl *
l9p_sysacl_to_acl(int acetype,acl_t sysacl,econvertfn * convert)535 l9p_sysacl_to_acl(int acetype, acl_t sysacl, econvertfn *convert)
536 {
537 struct l9p_acl *acl;
538 acl_entry_t entry;
539 uint32_t n;
540 int error, id;
541
542 acl = l9p_new_acl((uint32_t)acetype, (uint32_t)l9p_count_aces(sysacl));
543 if (acl == NULL)
544 return (NULL);
545 id = ACL_FIRST_ENTRY;
546 for (n = 0;;) {
547 if (acl_get_entry(sysacl, id, &entry) != 1)
548 break;
549 acl = l9p_growacl(acl, n + 1);
550 if (acl == NULL)
551 return (NULL);
552 error = (*convert)(entry, &acl->acl_aces[n]);
553 id = ACL_NEXT_ENTRY;
554 if (error == 0)
555 n++;
556 }
557 acl->acl_nace = n;
558 return (acl);
559 }
560 #endif
561
562 #if defined(HAVE_POSIX_ACLS) && 0 /* not yet */
563 struct l9p_acl *
l9p_posix_acl_to_acl(acl_t sysacl)564 l9p_posix_acl_to_acl(acl_t sysacl)
565 {
566 }
567 #endif
568
569 #if defined(HAVE_FREEBSD_ACLS)
570 static int
l9p_frombsdnfs4(acl_entry_t sysace,struct l9p_ace * ace)571 l9p_frombsdnfs4(acl_entry_t sysace, struct l9p_ace *ace)
572 {
573 acl_tag_t tag; /* e.g., USER_OBJ, GROUP, etc */
574 acl_entry_type_t entry_type; /* e.g., allow/deny */
575 acl_permset_t absdperm;
576 acl_flagset_t absdflag;
577 acl_perm_t bsdperm; /* e.g., READ_DATA */
578 acl_flag_t bsdflag; /* e.g., FILE_INHERIT_ACE */
579 uint32_t flags, mask;
580 int error;
581 uid_t uid, *aid;
582
583 error = acl_get_tag_type(sysace, &tag);
584 if (error == 0)
585 error = acl_get_entry_type_np(sysace, &entry_type);
586 if (error == 0)
587 error = acl_get_flagset_np(sysace, &absdflag);
588 if (error == 0)
589 error = acl_get_permset(sysace, &absdperm);
590 if (error)
591 return (error);
592
593 flags = 0;
594 uid = 0;
595 aid = NULL;
596
597 /* move user/group/everyone + id-is-group-id into flags */
598 switch (tag) {
599 case ACL_USER_OBJ:
600 flags |= L9P_ACEF_OWNER;
601 break;
602 case ACL_GROUP_OBJ:
603 flags |= L9P_ACEF_GROUP;
604 break;
605 case ACL_EVERYONE:
606 flags |= L9P_ACEF_EVERYONE;
607 break;
608 case ACL_GROUP:
609 flags |= L9P_ACEF_IDENTIFIER_GROUP;
610 /* FALLTHROUGH */
611 case ACL_USER:
612 aid = acl_get_qualifier(sysace); /* ugh, this malloc()s */
613 if (aid == NULL)
614 return (ENOMEM);
615 uid = *(uid_t *)aid;
616 free(aid);
617 aid = &uid;
618 break;
619 default:
620 return (EINVAL); /* can't happen */
621 }
622
623 switch (entry_type) {
624
625 case ACL_ENTRY_TYPE_ALLOW:
626 ace->ace_type = L9P_ACET_ACCESS_ALLOWED;
627 break;
628
629 case ACL_ENTRY_TYPE_DENY:
630 ace->ace_type = L9P_ACET_ACCESS_DENIED;
631 break;
632
633 case ACL_ENTRY_TYPE_AUDIT:
634 ace->ace_type = L9P_ACET_SYSTEM_AUDIT;
635 break;
636
637 case ACL_ENTRY_TYPE_ALARM:
638 ace->ace_type = L9P_ACET_SYSTEM_ALARM;
639 break;
640
641 default:
642 return (EINVAL); /* can't happen */
643 }
644
645 /* transform remaining BSD flags to internal NFS-y form */
646 bsdflag = *absdflag;
647 if (bsdflag & ACL_ENTRY_FILE_INHERIT)
648 flags |= L9P_ACEF_FILE_INHERIT_ACE;
649 if (bsdflag & ACL_ENTRY_DIRECTORY_INHERIT)
650 flags |= L9P_ACEF_DIRECTORY_INHERIT_ACE;
651 if (bsdflag & ACL_ENTRY_NO_PROPAGATE_INHERIT)
652 flags |= L9P_ACEF_NO_PROPAGATE_INHERIT_ACE;
653 if (bsdflag & ACL_ENTRY_INHERIT_ONLY)
654 flags |= L9P_ACEF_INHERIT_ONLY_ACE;
655 if (bsdflag & ACL_ENTRY_SUCCESSFUL_ACCESS)
656 flags |= L9P_ACEF_SUCCESSFUL_ACCESS_ACE_FLAG;
657 if (bsdflag & ACL_ENTRY_FAILED_ACCESS)
658 flags |= L9P_ACEF_FAILED_ACCESS_ACE_FLAG;
659 ace->ace_flags = flags;
660
661 /*
662 * Transform BSD permissions to ace_mask. Note that directory
663 * vs file bits are the same in both sets, so we don't need
664 * to worry about that, at least.
665 *
666 * There seem to be no BSD equivalents for WRITE_RETENTION
667 * and WRITE_RETENTION_HOLD.
668 */
669 mask = 0;
670 bsdperm = *absdperm;
671 if (bsdperm & ACL_READ_DATA)
672 mask |= L9P_ACE_READ_DATA;
673 if (bsdperm & ACL_WRITE_DATA)
674 mask |= L9P_ACE_WRITE_DATA;
675 if (bsdperm & ACL_APPEND_DATA)
676 mask |= L9P_ACE_APPEND_DATA;
677 if (bsdperm & ACL_READ_NAMED_ATTRS)
678 mask |= L9P_ACE_READ_NAMED_ATTRS;
679 if (bsdperm & ACL_WRITE_NAMED_ATTRS)
680 mask |= L9P_ACE_WRITE_NAMED_ATTRS;
681 if (bsdperm & ACL_EXECUTE)
682 mask |= L9P_ACE_EXECUTE;
683 if (bsdperm & ACL_DELETE_CHILD)
684 mask |= L9P_ACE_DELETE_CHILD;
685 if (bsdperm & ACL_READ_ATTRIBUTES)
686 mask |= L9P_ACE_READ_ATTRIBUTES;
687 if (bsdperm & ACL_WRITE_ATTRIBUTES)
688 mask |= L9P_ACE_WRITE_ATTRIBUTES;
689 /* L9P_ACE_WRITE_RETENTION */
690 /* L9P_ACE_WRITE_RETENTION_HOLD */
691 /* 0x00800 */
692 if (bsdperm & ACL_DELETE)
693 mask |= L9P_ACE_DELETE;
694 if (bsdperm & ACL_READ_ACL)
695 mask |= L9P_ACE_READ_ACL;
696 if (bsdperm & ACL_WRITE_ACL)
697 mask |= L9P_ACE_WRITE_ACL;
698 if (bsdperm & ACL_WRITE_OWNER)
699 mask |= L9P_ACE_WRITE_OWNER;
700 if (bsdperm & ACL_SYNCHRONIZE)
701 mask |= L9P_ACE_SYNCHRONIZE;
702 ace->ace_mask = mask;
703
704 /* fill in variable-size user or group ID bytes */
705 if (aid == NULL)
706 ace->ace_idsize = 0;
707 else {
708 ace->ace_idsize = sizeof(uid);
709 memcpy(&ace->ace_idbytes[0], aid, sizeof(uid));
710 }
711
712 return (0);
713 }
714
715 struct l9p_acl *
l9p_freebsd_nfsv4acl_to_acl(acl_t sysacl)716 l9p_freebsd_nfsv4acl_to_acl(acl_t sysacl)
717 {
718
719 return (l9p_sysacl_to_acl(L9P_ACLTYPE_NFSv4, sysacl, l9p_frombsdnfs4));
720 }
721 #endif
722
723 #if defined(HAVE_DARWIN_ACLS) && 0 /* not yet */
724 struct l9p_acl *
l9p_darwin_nfsv4acl_to_acl(acl_t sysacl)725 l9p_darwin_nfsv4acl_to_acl(acl_t sysacl)
726 {
727 }
728 #endif
729
730 #if defined(HAVE__ILLUMOS_ACLS)
731
732 static struct {
733 uint16_t ace_flag;
734 uint32_t l9_flag;
735 } ace_flag_tbl[] = {
736 { ACE_FILE_INHERIT_ACE, L9P_ACEF_FILE_INHERIT_ACE },
737 { ACE_DIRECTORY_INHERIT_ACE, L9P_ACEF_DIRECTORY_INHERIT_ACE },
738 { ACE_NO_PROPAGATE_INHERIT_ACE, L9P_ACEF_NO_PROPAGATE_INHERIT_ACE },
739 { ACE_INHERIT_ONLY_ACE, L9P_ACEF_INHERIT_ONLY_ACE },
740 { ACE_SUCCESSFUL_ACCESS_ACE_FLAG,
741 L9P_ACEF_SUCCESSFUL_ACCESS_ACE_FLAG },
742 { ACE_IDENTIFIER_GROUP, L9P_ACEF_IDENTIFIER_GROUP },
743 /* There doesn't appear to be an equivalent for ACE_INHERITED_ACE */
744 { ACE_OWNER, L9P_ACEF_OWNER },
745 { ACE_GROUP, L9P_ACEF_GROUP },
746 { ACE_EVERYONE, L9P_ACEF_EVERYONE }
747 };
748
749 struct l9p_acl *
l9p_illumos_nfsv4acl_to_acl(acl_t * sysacl)750 l9p_illumos_nfsv4acl_to_acl(acl_t *sysacl)
751 {
752 struct l9p_acl *l9acl;
753 struct l9p_ace *l9ace;
754 ace_t *ent;
755 int i, j;
756
757 /* We only support NFSv4 ACLs.. so don't try this on UFS */
758 if (sysacl->acl_type != ACE_T)
759 return (NULL);
760
761 l9acl = l9p_new_acl(L9P_ACLTYPE_NFSv4, sysacl->acl_cnt);
762 if (l9acl == NULL)
763 return (NULL);
764
765 ent = sysacl->acl_aclp;
766 l9ace = l9acl->acl_aces;
767 for (i = 0; i < sysacl->acl_cnt; i++, ent++, l9ace++) {
768 switch (ent->a_type) {
769 case ACE_ACCESS_ALLOWED_ACE_TYPE:
770 l9ace->ace_type = L9P_ACET_ACCESS_ALLOWED;
771 break;
772 case ACE_ACCESS_DENIED_ACE_TYPE:
773 l9ace->ace_type = L9P_ACET_ACCESS_DENIED;
774 break;
775 case ACE_SYSTEM_AUDIT_ACE_TYPE:
776 l9ace->ace_type = L9P_ACET_SYSTEM_AUDIT;
777 break;
778 case ACE_SYSTEM_ALARM_ACE_TYPE:
779 l9ace->ace_type = L9P_ACET_SYSTEM_ALARM;
780 break;
781 default:
782 L9P_LOG(L9P_ERROR, "invalid ACL type");
783 l9p_acl_free(l9acl);
784 return (NULL);
785 }
786
787 l9ace->ace_flags = 0;
788 for (j = 0; j < ARRAY_SIZE(ace_flag_tbl); j++) {
789 if ((ent->a_flags & ace_flag_tbl[j].ace_flag) != 0)
790 l9ace->ace_flags |= ace_flag_tbl[j].l9_flag;
791 }
792
793 /*
794 * In a bit of good fortune, the bit values for ace_t masks
795 * and l9p masks are the same (l9p does have WRITE_RETENTION
796 * and WRITE_RETENTION_HOLD which aren't used -- we're also
797 * going ace_t->l9p so they dont matter in this context).
798 */
799 l9ace->ace_mask = ent->a_access_mask;
800 l9ace->ace_idsize = sizeof (ent->a_who);
801 memcpy(l9acl->acl_aces, &ent->a_who, sizeof (ent->a_who));
802 }
803
804 return (l9acl);
805 }
806 #endif
807