acl_common.c revision 191931
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 427#ifndef __FreeBSD__ 428acl_t * 429acl_alloc(enum acl_type type) 430{ 431 acl_t *aclp; 432 433 if (cacl_malloc((void **)&aclp, sizeof (acl_t)) != 0) 434 return (NULL); 435 436 aclp->acl_aclp = NULL; 437 aclp->acl_cnt = 0; 438 439 switch (type) { 440 case ACE_T: 441 aclp->acl_type = ACE_T; 442 aclp->acl_entry_size = sizeof (ace_t); 443 break; 444 case ACLENT_T: 445 aclp->acl_type = ACLENT_T; 446 aclp->acl_entry_size = sizeof (aclent_t); 447 break; 448 default: 449 acl_free(aclp); 450 aclp = NULL; 451 } 452 return (aclp); 453} 454 455/* 456 * Free acl_t structure 457 */ 458void 459acl_free(acl_t *aclp) 460{ 461 int acl_size; 462 463 if (aclp == NULL) 464 return; 465 466 if (aclp->acl_aclp) { 467 acl_size = aclp->acl_cnt * aclp->acl_entry_size; 468 cacl_free(aclp->acl_aclp, acl_size); 469 } 470 471 cacl_free(aclp, sizeof (acl_t)); 472} 473#endif 474 475static uint32_t 476access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow) 477{ 478 uint32_t access_mask = 0; 479 int acl_produce; 480 int synchronize_set = 0, write_owner_set = 0; 481 int delete_set = 0, write_attrs_set = 0; 482 int read_named_set = 0, write_named_set = 0; 483 484 acl_produce = (ACL_SYNCHRONIZE_SET_ALLOW | 485 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 486 ACL_WRITE_ATTRS_WRITER_SET_DENY); 487 488 if (isallow) { 489 synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW; 490 write_owner_set = ACL_WRITE_OWNER_SET_ALLOW; 491 delete_set = ACL_DELETE_SET_ALLOW; 492 if (hasreadperm) 493 read_named_set = ACL_READ_NAMED_READER_SET_ALLOW; 494 if (haswriteperm) 495 write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 496 if (isowner) 497 write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 498 else if (haswriteperm) 499 write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 500 } else { 501 502 synchronize_set = ACL_SYNCHRONIZE_SET_DENY; 503 write_owner_set = ACL_WRITE_OWNER_SET_DENY; 504 delete_set = ACL_DELETE_SET_DENY; 505 if (hasreadperm) 506 read_named_set = ACL_READ_NAMED_READER_SET_DENY; 507 if (haswriteperm) 508 write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY; 509 if (isowner) 510 write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY; 511 else if (haswriteperm) 512 write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY; 513 else 514 /* 515 * If the entity is not the owner and does not 516 * have write permissions ACE_WRITE_ATTRIBUTES will 517 * always go in the DENY ACE. 518 */ 519 access_mask |= ACE_WRITE_ATTRIBUTES; 520 } 521 522 if (acl_produce & synchronize_set) 523 access_mask |= ACE_SYNCHRONIZE; 524 if (acl_produce & write_owner_set) 525 access_mask |= ACE_WRITE_OWNER; 526 if (acl_produce & delete_set) 527 access_mask |= ACE_DELETE; 528 if (acl_produce & write_attrs_set) 529 access_mask |= ACE_WRITE_ATTRIBUTES; 530 if (acl_produce & read_named_set) 531 access_mask |= ACE_READ_NAMED_ATTRS; 532 if (acl_produce & write_named_set) 533 access_mask |= ACE_WRITE_NAMED_ATTRS; 534 535 return (access_mask); 536} 537 538/* 539 * Given an mode_t, convert it into an access_mask as used 540 * by nfsace, assuming aclent_t -> nfsace semantics. 541 */ 542static uint32_t 543mode_to_ace_access(mode_t mode, int isdir, int isowner, int isallow) 544{ 545 uint32_t access = 0; 546 int haswriteperm = 0; 547 int hasreadperm = 0; 548 549 if (isallow) { 550 haswriteperm = (mode & S_IWOTH); 551 hasreadperm = (mode & S_IROTH); 552 } else { 553 haswriteperm = !(mode & S_IWOTH); 554 hasreadperm = !(mode & S_IROTH); 555 } 556 557 /* 558 * The following call takes care of correctly setting the following 559 * mask bits in the access_mask: 560 * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE, 561 * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS 562 */ 563 access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow); 564 565 if (isallow) { 566 access |= ACE_READ_ACL | ACE_READ_ATTRIBUTES; 567 if (isowner) 568 access |= ACE_WRITE_ACL; 569 } else { 570 if (! isowner) 571 access |= ACE_WRITE_ACL; 572 } 573 574 /* read */ 575 if (mode & S_IROTH) { 576 access |= ACE_READ_DATA; 577 } 578 /* write */ 579 if (mode & S_IWOTH) { 580 access |= ACE_WRITE_DATA | 581 ACE_APPEND_DATA; 582 if (isdir) 583 access |= ACE_DELETE_CHILD; 584 } 585 /* exec */ 586 if (mode & 01) { 587 access |= ACE_EXECUTE; 588 } 589 590 return (access); 591} 592 593/* 594 * Given an nfsace (presumably an ALLOW entry), make a 595 * corresponding DENY entry at the address given. 596 */ 597static void 598ace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner) 599{ 600 (void) memcpy(deny, allow, sizeof (ace_t)); 601 602 deny->a_who = allow->a_who; 603 604 deny->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 605 deny->a_access_mask ^= ACE_POSIX_SUPPORTED_BITS; 606 if (isdir) 607 deny->a_access_mask ^= ACE_DELETE_CHILD; 608 609 deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER | 610 ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS | 611 ACE_WRITE_NAMED_ATTRS); 612 deny->a_access_mask |= access_mask_set((allow->a_access_mask & 613 ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner, 614 B_FALSE); 615} 616/* 617 * Make an initial pass over an array of aclent_t's. Gather 618 * information such as an ACL_MASK (if any), number of users, 619 * number of groups, and whether the array needs to be sorted. 620 */ 621static int 622ln_aent_preprocess(aclent_t *aclent, int n, 623 int *hasmask, mode_t *mask, 624 int *numuser, int *numgroup, int *needsort) 625{ 626 int error = 0; 627 int i; 628 int curtype = 0; 629 630 *hasmask = 0; 631 *mask = 07; 632 *needsort = 0; 633 *numuser = 0; 634 *numgroup = 0; 635 636 for (i = 0; i < n; i++) { 637 if (aclent[i].a_type < curtype) 638 *needsort = 1; 639 else if (aclent[i].a_type > curtype) 640 curtype = aclent[i].a_type; 641 if (aclent[i].a_type & USER) 642 (*numuser)++; 643 if (aclent[i].a_type & (GROUP | GROUP_OBJ)) 644 (*numgroup)++; 645 if (aclent[i].a_type & CLASS_OBJ) { 646 if (*hasmask) { 647 error = EINVAL; 648 goto out; 649 } else { 650 *hasmask = 1; 651 *mask = aclent[i].a_perm; 652 } 653 } 654 } 655 656 if ((! *hasmask) && (*numuser + *numgroup > 1)) { 657 error = EINVAL; 658 goto out; 659 } 660 661out: 662 return (error); 663} 664 665/* 666 * Convert an array of aclent_t into an array of nfsace entries, 667 * following POSIX draft -> nfsv4 conversion semantics as outlined in 668 * the IETF draft. 669 */ 670static int 671ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir) 672{ 673 int error = 0; 674 mode_t mask; 675 int numuser, numgroup, needsort; 676 int resultsize = 0; 677 int i, groupi = 0, skip; 678 ace_t *acep, *result = NULL; 679 int hasmask; 680 681 error = ln_aent_preprocess(aclent, n, &hasmask, &mask, 682 &numuser, &numgroup, &needsort); 683 if (error != 0) 684 goto out; 685 686 /* allow + deny for each aclent */ 687 resultsize = n * 2; 688 if (hasmask) { 689 /* 690 * stick extra deny on the group_obj and on each 691 * user|group for the mask (the group_obj was added 692 * into the count for numgroup) 693 */ 694 resultsize += numuser + numgroup; 695 /* ... and don't count the mask itself */ 696 resultsize -= 2; 697 } 698 699 /* sort the source if necessary */ 700 if (needsort) 701 ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls); 702 703 if (cacl_malloc((void **)&result, resultsize * sizeof (ace_t)) != 0) 704 goto out; 705 706 acep = result; 707 708 for (i = 0; i < n; i++) { 709 /* 710 * don't process CLASS_OBJ (mask); mask was grabbed in 711 * ln_aent_preprocess() 712 */ 713 if (aclent[i].a_type & CLASS_OBJ) 714 continue; 715 716 /* If we need an ACL_MASK emulator, prepend it now */ 717 if ((hasmask) && 718 (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) { 719 acep->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 720 acep->a_flags = 0; 721 if (aclent[i].a_type & GROUP_OBJ) { 722 acep->a_who = (uid_t)-1; 723 acep->a_flags |= 724 (ACE_IDENTIFIER_GROUP|ACE_GROUP); 725 } else if (aclent[i].a_type & USER) { 726 acep->a_who = aclent[i].a_id; 727 } else { 728 acep->a_who = aclent[i].a_id; 729 acep->a_flags |= ACE_IDENTIFIER_GROUP; 730 } 731 if (aclent[i].a_type & ACL_DEFAULT) { 732 acep->a_flags |= ACE_INHERIT_ONLY_ACE | 733 ACE_FILE_INHERIT_ACE | 734 ACE_DIRECTORY_INHERIT_ACE; 735 } 736 /* 737 * Set the access mask for the prepended deny 738 * ace. To do this, we invert the mask (found 739 * in ln_aent_preprocess()) then convert it to an 740 * DENY ace access_mask. 741 */ 742 acep->a_access_mask = mode_to_ace_access((mask ^ 07), 743 isdir, 0, 0); 744 acep += 1; 745 } 746 747 /* handle a_perm -> access_mask */ 748 acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm, 749 isdir, aclent[i].a_type & USER_OBJ, 1); 750 751 /* emulate a default aclent */ 752 if (aclent[i].a_type & ACL_DEFAULT) { 753 acep->a_flags |= ACE_INHERIT_ONLY_ACE | 754 ACE_FILE_INHERIT_ACE | 755 ACE_DIRECTORY_INHERIT_ACE; 756 } 757 758 /* 759 * handle a_perm and a_id 760 * 761 * this must be done last, since it involves the 762 * corresponding deny aces, which are handled 763 * differently for each different a_type. 764 */ 765 if (aclent[i].a_type & USER_OBJ) { 766 acep->a_who = (uid_t)-1; 767 acep->a_flags |= ACE_OWNER; 768 ace_make_deny(acep, acep + 1, isdir, B_TRUE); 769 acep += 2; 770 } else if (aclent[i].a_type & USER) { 771 acep->a_who = aclent[i].a_id; 772 ace_make_deny(acep, acep + 1, isdir, B_FALSE); 773 acep += 2; 774 } else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) { 775 if (aclent[i].a_type & GROUP_OBJ) { 776 acep->a_who = (uid_t)-1; 777 acep->a_flags |= ACE_GROUP; 778 } else { 779 acep->a_who = aclent[i].a_id; 780 } 781 acep->a_flags |= ACE_IDENTIFIER_GROUP; 782 /* 783 * Set the corresponding deny for the group ace. 784 * 785 * The deny aces go after all of the groups, unlike 786 * everything else, where they immediately follow 787 * the allow ace. 788 * 789 * We calculate "skip", the number of slots to 790 * skip ahead for the deny ace, here. 791 * 792 * The pattern is: 793 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3 794 * thus, skip is 795 * (2 * numgroup) - 1 - groupi 796 * (2 * numgroup) to account for MD + A 797 * - 1 to account for the fact that we're on the 798 * access (A), not the mask (MD) 799 * - groupi to account for the fact that we have 800 * passed up groupi number of MD's. 801 */ 802 skip = (2 * numgroup) - 1 - groupi; 803 ace_make_deny(acep, acep + skip, isdir, B_FALSE); 804 /* 805 * If we just did the last group, skip acep past 806 * all of the denies; else, just move ahead one. 807 */ 808 if (++groupi >= numgroup) 809 acep += numgroup + 1; 810 else 811 acep += 1; 812 } else if (aclent[i].a_type & OTHER_OBJ) { 813 acep->a_who = (uid_t)-1; 814 acep->a_flags |= ACE_EVERYONE; 815 ace_make_deny(acep, acep + 1, isdir, B_FALSE); 816 acep += 2; 817 } else { 818 error = EINVAL; 819 goto out; 820 } 821 } 822 823 *acepp = result; 824 *rescount = resultsize; 825 826out: 827 if (error != 0) { 828 if ((result != NULL) && (resultsize > 0)) { 829 cacl_free(result, resultsize * sizeof (ace_t)); 830 } 831 } 832 833 return (error); 834} 835 836static int 837convert_aent_to_ace(aclent_t *aclentp, int aclcnt, int isdir, 838 ace_t **retacep, int *retacecnt) 839{ 840 ace_t *acep; 841 ace_t *dfacep; 842 int acecnt = 0; 843 int dfacecnt = 0; 844 int dfaclstart = 0; 845 int dfaclcnt = 0; 846 aclent_t *aclp; 847 int i; 848 int error; 849 int acesz, dfacesz; 850 851 ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls); 852 853 for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) { 854 if (aclp->a_type & ACL_DEFAULT) 855 break; 856 } 857 858 if (i < aclcnt) { 859 dfaclstart = i; 860 dfaclcnt = aclcnt - i; 861 } 862 863 if (dfaclcnt && isdir == 0) { 864 return (EINVAL); 865 } 866 867 error = ln_aent_to_ace(aclentp, i, &acep, &acecnt, isdir); 868 if (error) 869 return (error); 870 871 if (dfaclcnt) { 872 error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt, 873 &dfacep, &dfacecnt, isdir); 874 if (error) { 875 if (acep) { 876 cacl_free(acep, acecnt * sizeof (ace_t)); 877 } 878 return (error); 879 } 880 } 881 882 if (dfacecnt != 0) { 883 acesz = sizeof (ace_t) * acecnt; 884 dfacesz = sizeof (ace_t) * dfacecnt; 885 acep = cacl_realloc(acep, acesz, acesz + dfacesz); 886 if (acep == NULL) 887 return (ENOMEM); 888 if (dfaclcnt) { 889 (void) memcpy(acep + acecnt, dfacep, dfacesz); 890 } 891 } 892 if (dfaclcnt) 893 cacl_free(dfacep, dfacecnt * sizeof (ace_t)); 894 895 *retacecnt = acecnt + dfacecnt; 896 *retacep = acep; 897 return (0); 898} 899 900static int 901ace_mask_to_mode(uint32_t mask, o_mode_t *modep, int isdir) 902{ 903 int error = 0; 904 o_mode_t mode = 0; 905 uint32_t bits, wantbits; 906 907 /* read */ 908 if (mask & ACE_READ_DATA) 909 mode |= S_IROTH; 910 911 /* write */ 912 wantbits = (ACE_WRITE_DATA | ACE_APPEND_DATA); 913 if (isdir) 914 wantbits |= ACE_DELETE_CHILD; 915 bits = mask & wantbits; 916 if (bits != 0) { 917 if (bits != wantbits) { 918 error = ENOTSUP; 919 goto out; 920 } 921 mode |= S_IWOTH; 922 } 923 924 /* exec */ 925 if (mask & ACE_EXECUTE) { 926 mode |= S_IXOTH; 927 } 928 929 *modep = mode; 930 931out: 932 return (error); 933} 934 935static void 936acevals_init(acevals_t *vals, uid_t key) 937{ 938 bzero(vals, sizeof (*vals)); 939 vals->allowed = ACE_MASK_UNDEFINED; 940 vals->denied = ACE_MASK_UNDEFINED; 941 vals->mask = ACE_MASK_UNDEFINED; 942 vals->key = key; 943} 944 945static void 946ace_list_init(ace_list_t *al, int dfacl_flag) 947{ 948 acevals_init(&al->user_obj, 0); 949 acevals_init(&al->group_obj, 0); 950 acevals_init(&al->other_obj, 0); 951 al->numusers = 0; 952 al->numgroups = 0; 953 al->acl_mask = 0; 954 al->hasmask = 0; 955 al->state = ace_unused; 956 al->seen = 0; 957 al->dfacl_flag = dfacl_flag; 958} 959 960/* 961 * Find or create an acevals holder for a given id and avl tree. 962 * 963 * Note that only one thread will ever touch these avl trees, so 964 * there is no need for locking. 965 */ 966static acevals_t * 967acevals_find(ace_t *ace, avl_tree_t *avl, int *num) 968{ 969 acevals_t key, *rc; 970 avl_index_t where; 971 972 key.key = ace->a_who; 973 rc = avl_find(avl, &key, &where); 974 if (rc != NULL) 975 return (rc); 976 977 /* this memory is freed by ln_ace_to_aent()->ace_list_free() */ 978 if (cacl_malloc((void **)&rc, sizeof (acevals_t)) != 0) 979 return (NULL); 980 981 acevals_init(rc, ace->a_who); 982 avl_insert(avl, rc, where); 983 (*num)++; 984 985 return (rc); 986} 987 988static int 989access_mask_check(ace_t *acep, int mask_bit, int isowner) 990{ 991 int set_deny, err_deny; 992 int set_allow, err_allow; 993 int acl_consume; 994 int haswriteperm, hasreadperm; 995 996 if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) { 997 haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 0 : 1; 998 hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 0 : 1; 999 } else { 1000 haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 1 : 0; 1001 hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 1 : 0; 1002 } 1003 1004 acl_consume = (ACL_SYNCHRONIZE_ERR_DENY | 1005 ACL_DELETE_ERR_DENY | 1006 ACL_WRITE_OWNER_ERR_DENY | 1007 ACL_WRITE_OWNER_ERR_ALLOW | 1008 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 1009 ACL_WRITE_ATTRS_OWNER_ERR_DENY | 1010 ACL_WRITE_ATTRS_WRITER_SET_DENY | 1011 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW | 1012 ACL_WRITE_NAMED_WRITER_ERR_DENY | 1013 ACL_READ_NAMED_READER_ERR_DENY); 1014 1015 if (mask_bit == ACE_SYNCHRONIZE) { 1016 set_deny = ACL_SYNCHRONIZE_SET_DENY; 1017 err_deny = ACL_SYNCHRONIZE_ERR_DENY; 1018 set_allow = ACL_SYNCHRONIZE_SET_ALLOW; 1019 err_allow = ACL_SYNCHRONIZE_ERR_ALLOW; 1020 } else if (mask_bit == ACE_WRITE_OWNER) { 1021 set_deny = ACL_WRITE_OWNER_SET_DENY; 1022 err_deny = ACL_WRITE_OWNER_ERR_DENY; 1023 set_allow = ACL_WRITE_OWNER_SET_ALLOW; 1024 err_allow = ACL_WRITE_OWNER_ERR_ALLOW; 1025 } else if (mask_bit == ACE_DELETE) { 1026 set_deny = ACL_DELETE_SET_DENY; 1027 err_deny = ACL_DELETE_ERR_DENY; 1028 set_allow = ACL_DELETE_SET_ALLOW; 1029 err_allow = ACL_DELETE_ERR_ALLOW; 1030 } else if (mask_bit == ACE_WRITE_ATTRIBUTES) { 1031 if (isowner) { 1032 set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY; 1033 err_deny = ACL_WRITE_ATTRS_OWNER_ERR_DENY; 1034 set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 1035 err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW; 1036 } else if (haswriteperm) { 1037 set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY; 1038 err_deny = ACL_WRITE_ATTRS_WRITER_ERR_DENY; 1039 set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 1040 err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW; 1041 } else { 1042 if ((acep->a_access_mask & mask_bit) && 1043 (acep->a_type & ACE_ACCESS_ALLOWED_ACE_TYPE)) { 1044 return (ENOTSUP); 1045 } 1046 return (0); 1047 } 1048 } else if (mask_bit == ACE_READ_NAMED_ATTRS) { 1049 if (!hasreadperm) 1050 return (0); 1051 1052 set_deny = ACL_READ_NAMED_READER_SET_DENY; 1053 err_deny = ACL_READ_NAMED_READER_ERR_DENY; 1054 set_allow = ACL_READ_NAMED_READER_SET_ALLOW; 1055 err_allow = ACL_READ_NAMED_READER_ERR_ALLOW; 1056 } else if (mask_bit == ACE_WRITE_NAMED_ATTRS) { 1057 if (!haswriteperm) 1058 return (0); 1059 1060 set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY; 1061 err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY; 1062 set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 1063 err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW; 1064 } else { 1065 return (EINVAL); 1066 } 1067 1068 if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) { 1069 if (acl_consume & set_deny) { 1070 if (!(acep->a_access_mask & mask_bit)) { 1071 return (ENOTSUP); 1072 } 1073 } else if (acl_consume & err_deny) { 1074 if (acep->a_access_mask & mask_bit) { 1075 return (ENOTSUP); 1076 } 1077 } 1078 } else { 1079 /* ACE_ACCESS_ALLOWED_ACE_TYPE */ 1080 if (acl_consume & set_allow) { 1081 if (!(acep->a_access_mask & mask_bit)) { 1082 return (ENOTSUP); 1083 } 1084 } else if (acl_consume & err_allow) { 1085 if (acep->a_access_mask & mask_bit) { 1086 return (ENOTSUP); 1087 } 1088 } 1089 } 1090 return (0); 1091} 1092 1093static int 1094ace_to_aent_legal(ace_t *acep) 1095{ 1096 int error = 0; 1097 int isowner; 1098 1099 /* only ALLOW or DENY */ 1100 if ((acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE) && 1101 (acep->a_type != ACE_ACCESS_DENIED_ACE_TYPE)) { 1102 error = ENOTSUP; 1103 goto out; 1104 } 1105 1106 /* check for invalid flags */ 1107 if (acep->a_flags & ~(ACE_VALID_FLAG_BITS)) { 1108 error = EINVAL; 1109 goto out; 1110 } 1111 1112 /* some flags are illegal */ 1113 if (acep->a_flags & (ACE_SUCCESSFUL_ACCESS_ACE_FLAG | 1114 ACE_FAILED_ACCESS_ACE_FLAG | 1115 ACE_NO_PROPAGATE_INHERIT_ACE)) { 1116 error = ENOTSUP; 1117 goto out; 1118 } 1119 1120 /* check for invalid masks */ 1121 if (acep->a_access_mask & ~(ACE_VALID_MASK_BITS)) { 1122 error = EINVAL; 1123 goto out; 1124 } 1125 1126 if ((acep->a_flags & ACE_OWNER)) { 1127 isowner = 1; 1128 } else { 1129 isowner = 0; 1130 } 1131 1132 error = access_mask_check(acep, ACE_SYNCHRONIZE, isowner); 1133 if (error) 1134 goto out; 1135 1136 error = access_mask_check(acep, ACE_WRITE_OWNER, isowner); 1137 if (error) 1138 goto out; 1139 1140 error = access_mask_check(acep, ACE_DELETE, isowner); 1141 if (error) 1142 goto out; 1143 1144 error = access_mask_check(acep, ACE_WRITE_ATTRIBUTES, isowner); 1145 if (error) 1146 goto out; 1147 1148 error = access_mask_check(acep, ACE_READ_NAMED_ATTRS, isowner); 1149 if (error) 1150 goto out; 1151 1152 error = access_mask_check(acep, ACE_WRITE_NAMED_ATTRS, isowner); 1153 if (error) 1154 goto out; 1155 1156 /* more detailed checking of masks */ 1157 if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 1158 if (! (acep->a_access_mask & ACE_READ_ATTRIBUTES)) { 1159 error = ENOTSUP; 1160 goto out; 1161 } 1162 if ((acep->a_access_mask & ACE_WRITE_DATA) && 1163 (! (acep->a_access_mask & ACE_APPEND_DATA))) { 1164 error = ENOTSUP; 1165 goto out; 1166 } 1167 if ((! (acep->a_access_mask & ACE_WRITE_DATA)) && 1168 (acep->a_access_mask & ACE_APPEND_DATA)) { 1169 error = ENOTSUP; 1170 goto out; 1171 } 1172 } 1173 1174 /* ACL enforcement */ 1175 if ((acep->a_access_mask & ACE_READ_ACL) && 1176 (acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE)) { 1177 error = ENOTSUP; 1178 goto out; 1179 } 1180 if (acep->a_access_mask & ACE_WRITE_ACL) { 1181 if ((acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) && 1182 (isowner)) { 1183 error = ENOTSUP; 1184 goto out; 1185 } 1186 if ((acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) && 1187 (! isowner)) { 1188 error = ENOTSUP; 1189 goto out; 1190 } 1191 } 1192 1193out: 1194 return (error); 1195} 1196 1197static int 1198ace_allow_to_mode(uint32_t mask, o_mode_t *modep, int isdir) 1199{ 1200 /* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */ 1201 if ((mask & (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) != 1202 (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) { 1203 return (ENOTSUP); 1204 } 1205 1206 return (ace_mask_to_mode(mask, modep, isdir)); 1207} 1208 1209static int 1210acevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list, 1211 uid_t owner, gid_t group, int isdir) 1212{ 1213 int error; 1214 uint32_t flips = ACE_POSIX_SUPPORTED_BITS; 1215 1216 if (isdir) 1217 flips |= ACE_DELETE_CHILD; 1218 if (vals->allowed != (vals->denied ^ flips)) { 1219 error = ENOTSUP; 1220 goto out; 1221 } 1222 if ((list->hasmask) && (list->acl_mask != vals->mask) && 1223 (vals->aent_type & (USER | GROUP | GROUP_OBJ))) { 1224 error = ENOTSUP; 1225 goto out; 1226 } 1227 error = ace_allow_to_mode(vals->allowed, &dest->a_perm, isdir); 1228 if (error != 0) 1229 goto out; 1230 dest->a_type = vals->aent_type; 1231 if (dest->a_type & (USER | GROUP)) { 1232 dest->a_id = vals->key; 1233 } else if (dest->a_type & USER_OBJ) { 1234 dest->a_id = owner; 1235 } else if (dest->a_type & GROUP_OBJ) { 1236 dest->a_id = group; 1237 } else if (dest->a_type & OTHER_OBJ) { 1238 dest->a_id = 0; 1239 } else { 1240 error = EINVAL; 1241 goto out; 1242 } 1243 1244out: 1245 return (error); 1246} 1247 1248 1249static int 1250ace_list_to_aent(ace_list_t *list, aclent_t **aclentp, int *aclcnt, 1251 uid_t owner, gid_t group, int isdir) 1252{ 1253 int error = 0; 1254 aclent_t *aent, *result = NULL; 1255 acevals_t *vals; 1256 int resultcount; 1257 1258 if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) != 1259 (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) { 1260 error = ENOTSUP; 1261 goto out; 1262 } 1263 if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) { 1264 error = ENOTSUP; 1265 goto out; 1266 } 1267 1268 resultcount = 3 + list->numusers + list->numgroups; 1269 /* 1270 * This must be the same condition as below, when we add the CLASS_OBJ 1271 * (aka ACL mask) 1272 */ 1273 if ((list->hasmask) || (! list->dfacl_flag)) 1274 resultcount += 1; 1275 1276 if (cacl_malloc((void **)&result, 1277 resultcount * sizeof (aclent_t)) != 0) { 1278 error = ENOMEM; 1279 goto out; 1280 } 1281 aent = result; 1282 1283 /* USER_OBJ */ 1284 if (!(list->user_obj.aent_type & USER_OBJ)) { 1285 error = EINVAL; 1286 goto out; 1287 } 1288 1289 error = acevals_to_aent(&list->user_obj, aent, list, owner, group, 1290 isdir); 1291 1292 if (error != 0) 1293 goto out; 1294 ++aent; 1295 /* USER */ 1296 vals = NULL; 1297 for (vals = avl_first(&list->user); vals != NULL; 1298 vals = AVL_NEXT(&list->user, vals)) { 1299 if (!(vals->aent_type & USER)) { 1300 error = EINVAL; 1301 goto out; 1302 } 1303 error = acevals_to_aent(vals, aent, list, owner, group, 1304 isdir); 1305 if (error != 0) 1306 goto out; 1307 ++aent; 1308 } 1309 /* GROUP_OBJ */ 1310 if (!(list->group_obj.aent_type & GROUP_OBJ)) { 1311 error = EINVAL; 1312 goto out; 1313 } 1314 error = acevals_to_aent(&list->group_obj, aent, list, owner, group, 1315 isdir); 1316 if (error != 0) 1317 goto out; 1318 ++aent; 1319 /* GROUP */ 1320 vals = NULL; 1321 for (vals = avl_first(&list->group); vals != NULL; 1322 vals = AVL_NEXT(&list->group, vals)) { 1323 if (!(vals->aent_type & GROUP)) { 1324 error = EINVAL; 1325 goto out; 1326 } 1327 error = acevals_to_aent(vals, aent, list, owner, group, 1328 isdir); 1329 if (error != 0) 1330 goto out; 1331 ++aent; 1332 } 1333 /* 1334 * CLASS_OBJ (aka ACL_MASK) 1335 * 1336 * An ACL_MASK is not fabricated if the ACL is a default ACL. 1337 * This is to follow UFS's behavior. 1338 */ 1339 if ((list->hasmask) || (! list->dfacl_flag)) { 1340 if (list->hasmask) { 1341 uint32_t flips = ACE_POSIX_SUPPORTED_BITS; 1342 if (isdir) 1343 flips |= ACE_DELETE_CHILD; 1344 error = ace_mask_to_mode(list->acl_mask ^ flips, 1345 &aent->a_perm, isdir); 1346 if (error != 0) 1347 goto out; 1348 } else { 1349 /* fabricate the ACL_MASK from the group permissions */ 1350 error = ace_mask_to_mode(list->group_obj.allowed, 1351 &aent->a_perm, isdir); 1352 if (error != 0) 1353 goto out; 1354 } 1355 aent->a_id = 0; 1356 aent->a_type = CLASS_OBJ | list->dfacl_flag; 1357 ++aent; 1358 } 1359 /* OTHER_OBJ */ 1360 if (!(list->other_obj.aent_type & OTHER_OBJ)) { 1361 error = EINVAL; 1362 goto out; 1363 } 1364 error = acevals_to_aent(&list->other_obj, aent, list, owner, group, 1365 isdir); 1366 if (error != 0) 1367 goto out; 1368 ++aent; 1369 1370 *aclentp = result; 1371 *aclcnt = resultcount; 1372 1373out: 1374 if (error != 0) { 1375 if (result != NULL) 1376 cacl_free(result, resultcount * sizeof (aclent_t)); 1377 } 1378 1379 return (error); 1380} 1381 1382 1383/* 1384 * free all data associated with an ace_list 1385 */ 1386static void 1387ace_list_free(ace_list_t *al) 1388{ 1389 acevals_t *node; 1390 void *cookie; 1391 1392 if (al == NULL) 1393 return; 1394 1395 cookie = NULL; 1396 while ((node = avl_destroy_nodes(&al->user, &cookie)) != NULL) 1397 cacl_free(node, sizeof (acevals_t)); 1398 cookie = NULL; 1399 while ((node = avl_destroy_nodes(&al->group, &cookie)) != NULL) 1400 cacl_free(node, sizeof (acevals_t)); 1401 1402 avl_destroy(&al->user); 1403 avl_destroy(&al->group); 1404 1405 /* free the container itself */ 1406 cacl_free(al, sizeof (ace_list_t)); 1407} 1408 1409static int 1410acevals_compare(const void *va, const void *vb) 1411{ 1412 const acevals_t *a = va, *b = vb; 1413 1414 if (a->key == b->key) 1415 return (0); 1416 1417 if (a->key > b->key) 1418 return (1); 1419 1420 else 1421 return (-1); 1422} 1423 1424/* 1425 * Convert a list of ace_t entries to equivalent regular and default 1426 * aclent_t lists. Return error (ENOTSUP) when conversion is not possible. 1427 */ 1428static int 1429ln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group, 1430 aclent_t **aclentp, int *aclcnt, aclent_t **dfaclentp, int *dfaclcnt, 1431 int isdir) 1432{ 1433 int error = 0; 1434 ace_t *acep; 1435 uint32_t bits; 1436 int i; 1437 ace_list_t *normacl = NULL, *dfacl = NULL, *acl; 1438 acevals_t *vals; 1439 1440 *aclentp = NULL; 1441 *aclcnt = 0; 1442 *dfaclentp = NULL; 1443 *dfaclcnt = 0; 1444 1445 /* we need at least user_obj, group_obj, and other_obj */ 1446 if (n < 6) { 1447 error = ENOTSUP; 1448 goto out; 1449 } 1450 if (ace == NULL) { 1451 error = EINVAL; 1452 goto out; 1453 } 1454 1455 error = cacl_malloc((void **)&normacl, sizeof (ace_list_t)); 1456 if (error != 0) 1457 goto out; 1458 1459 avl_create(&normacl->user, acevals_compare, sizeof (acevals_t), 1460 offsetof(acevals_t, avl)); 1461 avl_create(&normacl->group, acevals_compare, sizeof (acevals_t), 1462 offsetof(acevals_t, avl)); 1463 1464 ace_list_init(normacl, 0); 1465 1466 error = cacl_malloc((void **)&dfacl, sizeof (ace_list_t)); 1467 if (error != 0) 1468 goto out; 1469 1470 avl_create(&dfacl->user, acevals_compare, sizeof (acevals_t), 1471 offsetof(acevals_t, avl)); 1472 avl_create(&dfacl->group, acevals_compare, sizeof (acevals_t), 1473 offsetof(acevals_t, avl)); 1474 ace_list_init(dfacl, ACL_DEFAULT); 1475 1476 /* process every ace_t... */ 1477 for (i = 0; i < n; i++) { 1478 acep = &ace[i]; 1479 1480 /* rule out certain cases quickly */ 1481 error = ace_to_aent_legal(acep); 1482 if (error != 0) 1483 goto out; 1484 1485 /* 1486 * Turn off these bits in order to not have to worry about 1487 * them when doing the checks for compliments. 1488 */ 1489 acep->a_access_mask &= ~(ACE_WRITE_OWNER | ACE_DELETE | 1490 ACE_SYNCHRONIZE | ACE_WRITE_ATTRIBUTES | 1491 ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS); 1492 1493 /* see if this should be a regular or default acl */ 1494 bits = acep->a_flags & 1495 (ACE_INHERIT_ONLY_ACE | 1496 ACE_FILE_INHERIT_ACE | 1497 ACE_DIRECTORY_INHERIT_ACE); 1498 if (bits != 0) { 1499 /* all or nothing on these inherit bits */ 1500 if (bits != (ACE_INHERIT_ONLY_ACE | 1501 ACE_FILE_INHERIT_ACE | 1502 ACE_DIRECTORY_INHERIT_ACE)) { 1503 error = ENOTSUP; 1504 goto out; 1505 } 1506 acl = dfacl; 1507 } else { 1508 acl = normacl; 1509 } 1510 1511 if ((acep->a_flags & ACE_OWNER)) { 1512 if (acl->state > ace_user_obj) { 1513 error = ENOTSUP; 1514 goto out; 1515 } 1516 acl->state = ace_user_obj; 1517 acl->seen |= USER_OBJ; 1518 vals = &acl->user_obj; 1519 vals->aent_type = USER_OBJ | acl->dfacl_flag; 1520 } else if ((acep->a_flags & ACE_EVERYONE)) { 1521 acl->state = ace_other_obj; 1522 acl->seen |= OTHER_OBJ; 1523 vals = &acl->other_obj; 1524 vals->aent_type = OTHER_OBJ | acl->dfacl_flag; 1525 } else if (acep->a_flags & ACE_IDENTIFIER_GROUP) { 1526 if (acl->state > ace_group) { 1527 error = ENOTSUP; 1528 goto out; 1529 } 1530 if ((acep->a_flags & ACE_GROUP)) { 1531 acl->seen |= GROUP_OBJ; 1532 vals = &acl->group_obj; 1533 vals->aent_type = GROUP_OBJ | acl->dfacl_flag; 1534 } else { 1535 acl->seen |= GROUP; 1536 vals = acevals_find(acep, &acl->group, 1537 &acl->numgroups); 1538 if (vals == NULL) { 1539 error = ENOMEM; 1540 goto out; 1541 } 1542 vals->aent_type = GROUP | acl->dfacl_flag; 1543 } 1544 acl->state = ace_group; 1545 } else { 1546 if (acl->state > ace_user) { 1547 error = ENOTSUP; 1548 goto out; 1549 } 1550 acl->state = ace_user; 1551 acl->seen |= USER; 1552 vals = acevals_find(acep, &acl->user, 1553 &acl->numusers); 1554 if (vals == NULL) { 1555 error = ENOMEM; 1556 goto out; 1557 } 1558 vals->aent_type = USER | acl->dfacl_flag; 1559 } 1560 1561 if (!(acl->state > ace_unused)) { 1562 error = EINVAL; 1563 goto out; 1564 } 1565 1566 if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 1567 /* no more than one allowed per aclent_t */ 1568 if (vals->allowed != ACE_MASK_UNDEFINED) { 1569 error = ENOTSUP; 1570 goto out; 1571 } 1572 vals->allowed = acep->a_access_mask; 1573 } else { 1574 /* 1575 * it's a DENY; if there was a previous DENY, it 1576 * must have been an ACL_MASK. 1577 */ 1578 if (vals->denied != ACE_MASK_UNDEFINED) { 1579 /* ACL_MASK is for USER and GROUP only */ 1580 if ((acl->state != ace_user) && 1581 (acl->state != ace_group)) { 1582 error = ENOTSUP; 1583 goto out; 1584 } 1585 1586 if (! acl->hasmask) { 1587 acl->hasmask = 1; 1588 acl->acl_mask = vals->denied; 1589 /* check for mismatched ACL_MASK emulations */ 1590 } else if (acl->acl_mask != vals->denied) { 1591 error = ENOTSUP; 1592 goto out; 1593 } 1594 vals->mask = vals->denied; 1595 } 1596 vals->denied = acep->a_access_mask; 1597 } 1598 } 1599 1600 /* done collating; produce the aclent_t lists */ 1601 if (normacl->state != ace_unused) { 1602 error = ace_list_to_aent(normacl, aclentp, aclcnt, 1603 owner, group, isdir); 1604 if (error != 0) { 1605 goto out; 1606 } 1607 } 1608 if (dfacl->state != ace_unused) { 1609 error = ace_list_to_aent(dfacl, dfaclentp, dfaclcnt, 1610 owner, group, isdir); 1611 if (error != 0) { 1612 goto out; 1613 } 1614 } 1615 1616out: 1617 if (normacl != NULL) 1618 ace_list_free(normacl); 1619 if (dfacl != NULL) 1620 ace_list_free(dfacl); 1621 1622 return (error); 1623} 1624 1625static int 1626convert_ace_to_aent(ace_t *acebufp, int acecnt, int isdir, 1627 uid_t owner, gid_t group, aclent_t **retaclentp, int *retaclcnt) 1628{ 1629 int error = 0; 1630 aclent_t *aclentp, *dfaclentp; 1631 int aclcnt, dfaclcnt; 1632 int aclsz, dfaclsz; 1633 1634 error = ln_ace_to_aent(acebufp, acecnt, owner, group, 1635 &aclentp, &aclcnt, &dfaclentp, &dfaclcnt, isdir); 1636 1637 if (error) 1638 return (error); 1639 1640 1641 if (dfaclcnt != 0) { 1642 /* 1643 * Slap aclentp and dfaclentp into a single array. 1644 */ 1645 aclsz = sizeof (aclent_t) * aclcnt; 1646 dfaclsz = sizeof (aclent_t) * dfaclcnt; 1647 aclentp = cacl_realloc(aclentp, aclsz, aclsz + dfaclsz); 1648 if (aclentp != NULL) { 1649 (void) memcpy(aclentp + aclcnt, dfaclentp, dfaclsz); 1650 } else { 1651 error = ENOMEM; 1652 } 1653 } 1654 1655 if (aclentp) { 1656 *retaclentp = aclentp; 1657 *retaclcnt = aclcnt + dfaclcnt; 1658 } 1659 1660 if (dfaclentp) 1661 cacl_free(dfaclentp, dfaclsz); 1662 1663 return (error); 1664} 1665 1666 1667int 1668acl_translate(acl_t *aclp, int target_flavor, int isdir, uid_t owner, 1669 gid_t group) 1670{ 1671 int aclcnt; 1672 void *acldata; 1673 int error; 1674 1675 /* 1676 * See if we need to translate 1677 */ 1678 if ((target_flavor == _ACL_ACE_ENABLED && aclp->acl_type == ACE_T) || 1679 (target_flavor == _ACL_ACLENT_ENABLED && 1680 aclp->acl_type == ACLENT_T)) 1681 return (0); 1682 1683 if (target_flavor == -1) { 1684 error = EINVAL; 1685 goto out; 1686 } 1687 1688 if (target_flavor == _ACL_ACE_ENABLED && 1689 aclp->acl_type == ACLENT_T) { 1690 error = convert_aent_to_ace(aclp->acl_aclp, 1691 aclp->acl_cnt, isdir, (ace_t **)&acldata, &aclcnt); 1692 if (error) 1693 goto out; 1694 1695 } else if (target_flavor == _ACL_ACLENT_ENABLED && 1696 aclp->acl_type == ACE_T) { 1697 error = convert_ace_to_aent(aclp->acl_aclp, aclp->acl_cnt, 1698 isdir, owner, group, (aclent_t **)&acldata, &aclcnt); 1699 if (error) 1700 goto out; 1701 } else { 1702 error = ENOTSUP; 1703 goto out; 1704 } 1705 1706 /* 1707 * replace old acl with newly translated acl 1708 */ 1709 cacl_free(aclp->acl_aclp, aclp->acl_cnt * aclp->acl_entry_size); 1710 aclp->acl_aclp = acldata; 1711 aclp->acl_cnt = aclcnt; 1712 if (target_flavor == _ACL_ACE_ENABLED) { 1713 aclp->acl_type = ACE_T; 1714 aclp->acl_entry_size = sizeof (ace_t); 1715 } else { 1716 aclp->acl_type = ACLENT_T; 1717 aclp->acl_entry_size = sizeof (aclent_t); 1718 } 1719 return (0); 1720 1721out: 1722 1723#if !defined(_KERNEL) 1724 errno = error; 1725 return (-1); 1726#else 1727 return (error); 1728#endif 1729} 1730