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