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