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