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