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