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