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 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 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 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 */ 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 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 * 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 * 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 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 * 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 * 564 l9p_posix_acl_to_acl(acl_t sysacl) 565 { 566 } 567 #endif 568 569 #if defined(HAVE_FREEBSD_ACLS) 570 static int 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 * 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 * 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 * 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