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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * The following naming convention is used in function names. 28 * 29 * If an argument is one or more aclent_t, we use "aent". 30 * If an argument is one or more nfsace4, we use "ace4". 31 * If an argument is one or more ace_t, we use "acet". 32 * 33 * If there is an aggregate of the one above... 34 * If it's contained in a vsecattr_t, we prepend "vs_". 35 * If it's contained in an "array" (pointer) and length, we prepend "ln_". 36 * 37 * Thus, for example, suppose you have a function that converts an 38 * array of aclent_t structures into an array of nfsace4 structures, 39 * it's name would be "ln_aent_to_ace4". 40 */ 41 42 #include <sys/acl.h> 43 #include <nfs/nfs4_kprot.h> 44 #include <nfs/nfs4.h> 45 #include <nfs/rnode4.h> 46 #include <sys/cmn_err.h> 47 #include <sys/systm.h> 48 #include <sys/sdt.h> 49 50 #define ACE4_POSIX_SUPPORTED_BITS (ACE4_READ_DATA | \ 51 ACE4_WRITE_DATA | \ 52 ACE4_APPEND_DATA | \ 53 ACE4_EXECUTE | \ 54 ACE4_READ_ATTRIBUTES | \ 55 ACE4_READ_ACL | \ 56 ACE4_WRITE_ACL) 57 58 static int ace4vals_compare(const void *, const void *); 59 static int nfs4_ace4_list_construct(void *, void *, int); 60 static void nfs4_ace4_list_destroy(void *, void *); 61 static void ace4_list_free(ace4_list_t *); 62 static void ace4vals_init(ace4vals_t *, utf8string *); 63 static void ace4_list_init(ace4_list_t *, int); 64 static int ln_aent_preprocess(aclent_t *, int, 65 int *, o_mode_t *, int *, int *, int *); 66 static void ace4_make_deny(nfsace4 *, nfsace4 *, int, int, int); 67 static acemask4 mode_to_ace4_access(o_mode_t, int, int, int, int); 68 static int ln_aent_to_ace4(aclent_t *, int, nfsace4 **, int *, int, int); 69 static int ace4_mask_to_mode(acemask4, o_mode_t *, int); 70 static int ace4_allow_to_mode(acemask4, o_mode_t *, int); 71 static ace4vals_t *ace4vals_find(nfsace4 *, avl_tree_t *, int *); 72 static int ace4_to_aent_legal(nfsace4 *, int); 73 static int ace4vals_to_aent(ace4vals_t *, aclent_t *, ace4_list_t *, 74 uid_t, gid_t, int, int); 75 static int ace4_list_to_aent(ace4_list_t *, aclent_t **, int *, uid_t, gid_t, 76 int, int); 77 static int ln_ace4_to_aent(nfsace4 *ace4, int n, uid_t, gid_t, 78 aclent_t **, int *, aclent_t **, int *, int, int); 79 static int ace4_cmp(nfsace4 *, nfsace4 *); 80 static int acet_to_ace4(ace_t *, nfsace4 *, int); 81 static int ace4_to_acet(nfsace4 *, ace_t *, uid_t, gid_t, int); 82 static int validate_idmapping(utf8string *, uid_t *, int, int); 83 static int u8s_mapped_to_nobody(utf8string *, uid_t, int); 84 static void remap_id(uid_t *, int); 85 static void ace4_mask_to_acet_mask(acemask4, uint32_t *); 86 static void acet_mask_to_ace4_mask(uint32_t, acemask4 *); 87 static void ace4_flags_to_acet_flags(aceflag4, uint16_t *); 88 static void acet_flags_to_ace4_flags(uint16_t, aceflag4 *); 89 90 /* 91 * The following two functions check and set ACE4_SYNCRONIZE, ACE4_WRITE_OWNER, 92 * ACE4_DELETE and ACE4_WRITE_ATTRIBUTES. 93 */ 94 static int access_mask_check(nfsace4 *, int, int, int); 95 static acemask4 access_mask_set(int, int, int, int, int); 96 97 static int nfs4_acl_debug = 0; 98 99 #define ACL_SYNCHRONIZE_SET_DENY 0x0000001 100 #define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002 101 #define ACL_SYNCHRONIZE_ERR_DENY 0x0000004 102 #define ACL_SYNCHRONIZE_ERR_ALLOW 0x0000008 103 104 #define ACL_WRITE_OWNER_SET_DENY 0x0000010 105 #define ACL_WRITE_OWNER_SET_ALLOW 0x0000020 106 #define ACL_WRITE_OWNER_ERR_DENY 0x0000040 107 #define ACL_WRITE_OWNER_ERR_ALLOW 0x0000080 108 109 #define ACL_DELETE_SET_DENY 0x0000100 110 #define ACL_DELETE_SET_ALLOW 0x0000200 111 #define ACL_DELETE_ERR_DENY 0x0000400 112 #define ACL_DELETE_ERR_ALLOW 0x0000800 113 114 #define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000 115 #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000 116 #define ACL_WRITE_ATTRS_OWNER_ERR_DENY 0x0004000 117 #define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW 0x0008000 118 119 #define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000 120 #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000 121 #define ACL_WRITE_ATTRS_WRITER_ERR_DENY 0x0040000 122 #define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW 0x0080000 123 124 #define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000 125 #define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000 126 #define ACL_WRITE_NAMED_WRITER_ERR_DENY 0x0400000 127 #define ACL_WRITE_NAMED_WRITER_ERR_ALLOW 0x0800000 128 129 #define ACL_READ_NAMED_READER_SET_DENY 0x1000000 130 #define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000 131 #define ACL_READ_NAMED_READER_ERR_DENY 0x4000000 132 #define ACL_READ_NAMED_READER_ERR_ALLOW 0x8000000 133 134 /* 135 * What we will send the server upon setting an ACL on our client 136 */ 137 static int nfs4_acl_client_produce = 138 (ACL_SYNCHRONIZE_SET_ALLOW | 139 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 140 ACL_WRITE_ATTRS_WRITER_SET_DENY); 141 142 /* 143 * What we will accept upon getting an ACL on our client 144 */ 145 static int nfs4_acl_client_consume = 146 (ACL_WRITE_OWNER_ERR_DENY | 147 ACL_WRITE_OWNER_ERR_ALLOW | 148 ACL_WRITE_ATTRS_OWNER_ERR_DENY | 149 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 150 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW | 151 ACL_WRITE_ATTRS_WRITER_SET_DENY); 152 153 /* 154 * What we will produce as an ACL on a newly created file 155 */ 156 static int nfs4_acl_server_produce = 157 (ACL_SYNCHRONIZE_SET_ALLOW | 158 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 159 ACL_WRITE_ATTRS_WRITER_SET_DENY); 160 161 /* 162 * What we will accept upon setting an ACL on our server 163 */ 164 static int nfs4_acl_server_consume = 165 (ACL_SYNCHRONIZE_ERR_DENY | 166 ACL_DELETE_ERR_DENY | 167 ACL_WRITE_OWNER_ERR_DENY | 168 ACL_WRITE_OWNER_ERR_ALLOW | 169 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 170 ACL_WRITE_ATTRS_OWNER_ERR_DENY | 171 ACL_WRITE_ATTRS_WRITER_SET_DENY | 172 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW | 173 ACL_WRITE_NAMED_WRITER_ERR_DENY | 174 ACL_READ_NAMED_READER_ERR_DENY); 175 176 static kmem_cache_t *nfs4_ace4vals_cache = NULL; 177 static kmem_cache_t *nfs4_ace4_list_cache = NULL; 178 179 static int 180 ace4vals_compare(const void *va, const void *vb) 181 { 182 const ace4vals_t *a = va, *b = vb; 183 184 if ((a->key == NULL) && (b->key == NULL)) 185 return (0); 186 else if (a->key == NULL) 187 return (-1); 188 else if (b->key == NULL) 189 return (1); 190 191 return (utf8_compare(a->key, b->key)); 192 } 193 194 /*ARGSUSED*/ 195 static int 196 nfs4_ace4_list_construct(void *voidp, void *arg, int kmem_flags) 197 { 198 ace4_list_t *a4l = voidp; 199 200 avl_create(&a4l->user, ace4vals_compare, sizeof (ace4vals_t), 201 offsetof(ace4vals_t, avl)); 202 avl_create(&a4l->group, ace4vals_compare, sizeof (ace4vals_t), 203 offsetof(ace4vals_t, avl)); 204 return (0); 205 } 206 207 /*ARGSUSED*/ 208 static void 209 nfs4_ace4_list_destroy(void *voidp, void *arg) 210 { 211 ace4_list_t *a4l = voidp; 212 213 avl_destroy(&a4l->user); 214 avl_destroy(&a4l->group); 215 } 216 217 void 218 nfs4_acl_init(void) 219 { 220 nfs4_ace4vals_cache = kmem_cache_create("nfs4_ace4vals_cache", 221 sizeof (ace4vals_t), 0, 222 NULL, NULL, 223 NULL, NULL, 224 NULL, 225 0); 226 nfs4_ace4_list_cache = kmem_cache_create("nfs4_ace4_list_cache", 227 sizeof (ace4_list_t), 0, 228 nfs4_ace4_list_construct, nfs4_ace4_list_destroy, 229 NULL, NULL, 230 NULL, 231 0); 232 } 233 234 void 235 vs_acet_destroy(vsecattr_t *vsp) 236 { 237 if (vsp->vsa_mask != (VSA_ACE | VSA_ACECNT)) 238 return; 239 240 if ((vsp->vsa_aclentp != NULL) && 241 (vsp->vsa_aclcnt > 0) && 242 (vsp->vsa_mask & VSA_ACE) && 243 (vsp->vsa_mask & VSA_ACECNT)) 244 kmem_free(vsp->vsa_aclentp, 245 vsp->vsa_aclcnt * sizeof (ace_t)); 246 247 vsp->vsa_aclentp = NULL; 248 vsp->vsa_aclcnt = 0; 249 } 250 251 void 252 vs_ace4_destroy(vsecattr_t *vsp) 253 { 254 nfsace4 *ace4; 255 int i; 256 257 if (vsp->vsa_mask != (VSA_ACE | VSA_ACECNT)) 258 return; 259 260 if ((vsp->vsa_aclentp != NULL) && 261 (vsp->vsa_aclcnt > 0) && 262 (vsp->vsa_mask & VSA_ACE) && 263 (vsp->vsa_mask & VSA_ACECNT)) { 264 for (i = 0; i < vsp->vsa_aclcnt; i++) { 265 ace4 = (nfsace4 *)vsp->vsa_aclentp + i; 266 if ((ace4->who.utf8string_len > 0) && 267 (ace4->who.utf8string_val != NULL)) 268 kmem_free(ace4->who.utf8string_val, 269 ace4->who.utf8string_len); 270 271 ace4->who.utf8string_val = NULL; 272 ace4->who.utf8string_len = 0; 273 } 274 275 kmem_free(vsp->vsa_aclentp, 276 vsp->vsa_aclcnt * sizeof (nfsace4)); 277 } 278 279 vsp->vsa_aclentp = NULL; 280 vsp->vsa_aclcnt = 0; 281 } 282 283 void 284 vs_aent_destroy(vsecattr_t *vsp) 285 { 286 if (vsp->vsa_mask & (VSA_ACE | VSA_ACECNT)) 287 return; 288 289 if ((vsp->vsa_aclentp != NULL) && 290 (vsp->vsa_aclcnt > 0) && 291 (vsp->vsa_mask & VSA_ACL) && 292 (vsp->vsa_mask & VSA_ACLCNT)) 293 kmem_free(vsp->vsa_aclentp, 294 vsp->vsa_aclcnt * sizeof (aclent_t)); 295 if ((vsp->vsa_dfaclentp != NULL) && 296 (vsp->vsa_dfaclcnt > 0) && 297 (vsp->vsa_mask & VSA_DFACL) && 298 (vsp->vsa_mask & VSA_DFACLCNT)) 299 kmem_free(vsp->vsa_dfaclentp, 300 vsp->vsa_dfaclcnt * sizeof (aclent_t)); 301 302 vsp->vsa_aclentp = NULL; 303 vsp->vsa_aclcnt = 0; 304 305 vsp->vsa_dfaclentp = NULL; 306 vsp->vsa_aclcnt = 0; 307 } 308 309 /* 310 * free all data associated with an ace4_list 311 */ 312 static void 313 ace4_list_free(ace4_list_t *a4l) 314 { 315 ace4vals_t *node; 316 void *cookie; 317 318 if (a4l == NULL) 319 return; 320 321 /* free all nodes, but don't destroy the trees themselves */ 322 cookie = NULL; 323 while ((node = avl_destroy_nodes(&a4l->user, &cookie)) != NULL) 324 kmem_cache_free(nfs4_ace4vals_cache, node); 325 cookie = NULL; 326 while ((node = avl_destroy_nodes(&a4l->group, &cookie)) != NULL) 327 kmem_cache_free(nfs4_ace4vals_cache, node); 328 329 /* free the container itself */ 330 kmem_cache_free(nfs4_ace4_list_cache, a4l); 331 } 332 333 static void 334 ace4vals_init(ace4vals_t *vals, utf8string *key) 335 { 336 bzero(vals, sizeof (*vals)); 337 vals->allowed = ACE4_MASK_UNDEFINED; 338 vals->denied = ACE4_MASK_UNDEFINED; 339 vals->mask = ACE4_MASK_UNDEFINED; 340 vals->key = key; 341 } 342 343 static void 344 ace4_list_init(ace4_list_t *a4l, int dfacl_flag) 345 { 346 ace4vals_init(&a4l->user_obj, NULL); 347 ace4vals_init(&a4l->group_obj, NULL); 348 ace4vals_init(&a4l->other_obj, NULL); 349 a4l->numusers = 0; 350 a4l->numgroups = 0; 351 a4l->acl_mask = 0; 352 a4l->hasmask = 0; 353 a4l->state = ace4_unused; 354 a4l->seen = 0; 355 a4l->dfacl_flag = dfacl_flag; 356 } 357 358 /* 359 * Make an initial pass over an array of aclent_t's. Gather 360 * information such as an ACL_MASK (if any), number of users, 361 * number of groups, and whether the array needs to be sorted. 362 */ 363 static int 364 ln_aent_preprocess(aclent_t *aclent, int n, 365 int *hasmask, o_mode_t *mask, 366 int *numuser, int *numgroup, int *needsort) 367 { 368 int error = 0; 369 int i; 370 int curtype = 0; 371 372 *hasmask = 0; 373 *mask = 07; 374 *needsort = 0; 375 *numuser = 0; 376 *numgroup = 0; 377 378 for (i = 0; i < n; i++) { 379 if (aclent[i].a_type < curtype) 380 *needsort = 1; 381 else if (aclent[i].a_type > curtype) 382 curtype = aclent[i].a_type; 383 if (aclent[i].a_type & USER) 384 (*numuser)++; 385 if (aclent[i].a_type & (GROUP | GROUP_OBJ)) 386 (*numgroup)++; 387 if (aclent[i].a_type & CLASS_OBJ) { 388 if (*hasmask) { 389 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 390 "ln_aent_preprocess: multiple CLASS_OBJs " 391 "(masks) found")); 392 error = EINVAL; 393 goto out; 394 } else { 395 *hasmask = 1; 396 *mask = aclent[i].a_perm; 397 } 398 } 399 } 400 401 if ((! *hasmask) && (*numuser + *numgroup > 1)) { 402 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 403 "ln_aent_preprocess: no CLASS_OBJs " 404 "(masks) found")); 405 error = EINVAL; 406 goto out; 407 } 408 409 out: 410 return (error); 411 } 412 413 static acemask4 414 access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow, 415 int isserver) 416 { 417 acemask4 access_mask = 0; 418 int nfs4_acl_produce; 419 int synchronize_set = 0, write_owner_set = 0; 420 int delete_set = 0, write_attrs_set = 0; 421 int read_named_set = 0, write_named_set = 0; 422 423 if (isserver) 424 nfs4_acl_produce = nfs4_acl_server_produce; 425 else 426 nfs4_acl_produce = nfs4_acl_client_produce; 427 428 if (isallow) { 429 synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW; 430 write_owner_set = ACL_WRITE_OWNER_SET_ALLOW; 431 delete_set = ACL_DELETE_SET_ALLOW; 432 if (hasreadperm) 433 read_named_set = ACL_READ_NAMED_READER_SET_ALLOW; 434 if (haswriteperm) 435 write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 436 if (isowner) 437 write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 438 else if (haswriteperm) 439 write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 440 } else { 441 synchronize_set = ACL_SYNCHRONIZE_SET_DENY; 442 write_owner_set = ACL_WRITE_OWNER_SET_DENY; 443 delete_set = ACL_DELETE_SET_DENY; 444 if (hasreadperm) 445 read_named_set = ACL_READ_NAMED_READER_SET_DENY; 446 if (haswriteperm) 447 write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY; 448 if (isowner) 449 write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY; 450 else if (haswriteperm) 451 write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY; 452 else 453 /* 454 * If the entity is not the owner and does not 455 * have write permissions ACE4_WRITE_ATTRIBUTES will 456 * always go in the DENY ACE. 457 */ 458 access_mask |= ACE4_WRITE_ATTRIBUTES; 459 } 460 461 if (nfs4_acl_produce & synchronize_set) 462 access_mask |= ACE4_SYNCHRONIZE; 463 if (nfs4_acl_produce & write_owner_set) 464 access_mask |= ACE4_WRITE_OWNER; 465 if (nfs4_acl_produce & delete_set) 466 access_mask |= ACE4_DELETE; 467 if (nfs4_acl_produce & write_attrs_set) 468 access_mask |= ACE4_WRITE_ATTRIBUTES; 469 if (nfs4_acl_produce & read_named_set) 470 access_mask |= ACE4_READ_NAMED_ATTRS; 471 if (nfs4_acl_produce & write_named_set) 472 access_mask |= ACE4_WRITE_NAMED_ATTRS; 473 474 return (access_mask); 475 } 476 477 /* 478 * Given an nfsace4 (presumably an ALLOW entry), make a 479 * corresponding DENY entry at the address given. 480 */ 481 static void 482 ace4_make_deny(nfsace4 *allow, nfsace4 *deny, int isdir, int isowner, 483 int isserver) 484 { 485 bcopy(allow, deny, sizeof (nfsace4)); 486 487 (void) utf8_copy(&allow->who, &deny->who); 488 489 deny->type = ACE4_ACCESS_DENIED_ACE_TYPE; 490 deny->access_mask ^= ACE4_POSIX_SUPPORTED_BITS; 491 if (isdir) 492 deny->access_mask ^= ACE4_DELETE_CHILD; 493 494 deny->access_mask &= ~(ACE4_SYNCHRONIZE | ACE4_WRITE_OWNER | 495 ACE4_DELETE | ACE4_WRITE_ATTRIBUTES | ACE4_READ_NAMED_ATTRS | 496 ACE4_WRITE_NAMED_ATTRS); 497 deny->access_mask |= access_mask_set((allow->access_mask & 498 ACE4_WRITE_DATA), (allow->access_mask & ACE4_READ_DATA), isowner, 499 FALSE, isserver); 500 } 501 502 /* 503 * Given an o_mode_t, convert it into an access_mask as used 504 * by nfsace4, assuming aclent_t -> nfsace4 semantics. 505 */ 506 static acemask4 507 mode_to_ace4_access(o_mode_t mode, int isdir, int isowner, int isallow, 508 int isserver) 509 { 510 acemask4 access = 0; 511 int haswriteperm = 0; 512 int hasreadperm = 0; 513 514 if (isallow) { 515 haswriteperm = (mode & 02); 516 hasreadperm = (mode & 04); 517 } else { 518 haswriteperm = !(mode & 02); 519 hasreadperm = !(mode & 04); 520 } 521 522 /* 523 * The following call takes care of correctly setting the following 524 * mask bits in the access_mask: 525 * ACE4_SYNCHRONIZE, ACE4_WRITE_OWNER, ACE4_DELETE, 526 * ACE4_WRITE_ATTRIBUTES, ACE4_WRITE_NAMED_ATTRS, ACE4_READ_NAMED_ATTRS 527 */ 528 access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow, 529 isserver); 530 531 if (isallow) { 532 access |= ACE4_READ_ACL | ACE4_READ_ATTRIBUTES; 533 if (isowner) 534 access |= ACE4_WRITE_ACL; 535 } else { 536 if (! isowner) 537 access |= ACE4_WRITE_ACL; 538 } 539 540 /* read */ 541 if (mode & 04) { 542 access |= ACE4_READ_DATA; 543 } 544 /* write */ 545 if (mode & 02) { 546 access |= ACE4_WRITE_DATA | 547 ACE4_APPEND_DATA; 548 if (isdir) 549 access |= ACE4_DELETE_CHILD; 550 } 551 /* exec */ 552 if (mode & 01) { 553 access |= ACE4_EXECUTE; 554 } 555 556 return (access); 557 } 558 559 /* 560 * Convert an array of aclent_t into an array of nfsace4 entries, 561 * following POSIX draft -> nfsv4 conversion semantics as outlined in 562 * the IETF draft. 563 */ 564 static int 565 ln_aent_to_ace4(aclent_t *aclent, int n, nfsace4 **acepp, int *rescount, 566 int isdir, int isserver) 567 { 568 int error = 0; 569 o_mode_t mask; 570 int numuser, numgroup, needsort; 571 int resultsize = 0; 572 int i, groupi = 0, skip; 573 nfsace4 *acep, *result = NULL; 574 int hasmask; 575 576 error = ln_aent_preprocess(aclent, n, &hasmask, &mask, 577 &numuser, &numgroup, &needsort); 578 if (error != 0) 579 goto out; 580 581 /* allow + deny for each aclent */ 582 resultsize = n * 2; 583 if (hasmask) { 584 /* 585 * stick extra deny on the group_obj and on each 586 * user|group for the mask (the group_obj was added 587 * into the count for numgroup) 588 */ 589 resultsize += numuser + numgroup; 590 /* ... and don't count the mask itself */ 591 resultsize -= 2; 592 } 593 594 /* sort the source if necessary */ 595 if (needsort) 596 ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls); 597 598 result = acep = kmem_zalloc(resultsize * sizeof (nfsace4), KM_SLEEP); 599 600 for (i = 0; i < n; i++) { 601 /* 602 * don't process CLASS_OBJ (mask); mask was grabbed in 603 * ln_aent_preprocess() 604 */ 605 if (aclent[i].a_type & CLASS_OBJ) 606 continue; 607 608 /* If we need an ACL_MASK emulator, prepend it now */ 609 if ((hasmask) && 610 (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) { 611 acep->type = ACE4_ACCESS_DENIED_ACE_TYPE; 612 acep->flag = 0; 613 if (aclent[i].a_type & GROUP_OBJ) { 614 (void) str_to_utf8(ACE4_WHO_GROUP, &acep->who); 615 acep->flag |= ACE4_IDENTIFIER_GROUP; 616 error = 0; 617 } else if (aclent[i].a_type & USER) { 618 /* 619 * On the client, we do not allow an ACL with 620 * ACEs containing the UID_UNKNOWN user to be 621 * set. This is because having UID_UNKNOWN in 622 * an ACE can only come from the user having 623 * done a read-modify-write ACL manipulation 624 * (e.g. setfacl -m or chmod A+) when there 625 * was an ACE with an unmappable group already 626 * present. 627 */ 628 if (aclent[i].a_id == UID_UNKNOWN && 629 !isserver) { 630 DTRACE_PROBE( 631 nfs4clnt__err__acl__uid__unknown); 632 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 633 "ln_aent_to_ace4: UID_UNKNOWN is " 634 "not allowed in the ACL")); 635 error = EACCES; 636 goto out; 637 } 638 639 error = nfs_idmap_uid_str(aclent[i].a_id, 640 &acep->who, isserver); 641 } else { 642 /* 643 * Same rule as UID_UNKNOWN (above). 644 */ 645 if (aclent[i].a_id == GID_UNKNOWN && 646 !isserver) { 647 DTRACE_PROBE( 648 nfs4clnt__err__acl__gid__unknown); 649 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 650 "ln_aent_to_ace4: GID_UNKNOWN is " 651 "not allowed in the ACL")); 652 error = EACCES; 653 goto out; 654 } 655 656 error = nfs_idmap_gid_str(aclent[i].a_id, 657 &acep->who, isserver); 658 acep->flag |= ACE4_IDENTIFIER_GROUP; 659 } 660 if (error != 0) { 661 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 662 "ln_aent_to_ace4: idmap translate " 663 "failed with %d", error)); 664 goto out; 665 } 666 if (aclent[i].a_type & ACL_DEFAULT) { 667 acep->flag |= ACE4_INHERIT_ONLY_ACE | 668 ACE4_FILE_INHERIT_ACE | 669 ACE4_DIRECTORY_INHERIT_ACE; 670 } 671 /* 672 * Set the access mask for the prepended deny 673 * ace. To do this, we invert the mask (found 674 * in ln_aent_preprocess()) then convert it to an 675 * DENY ace access_mask. 676 */ 677 acep->access_mask = mode_to_ace4_access((mask ^ 07), 678 isdir, 0, 0, isserver); 679 acep += 1; 680 } 681 682 /* handle a_perm -> access_mask */ 683 acep->access_mask = mode_to_ace4_access(aclent[i].a_perm, 684 isdir, aclent[i].a_type & USER_OBJ, 1, isserver); 685 686 /* emulate a default aclent */ 687 if (aclent[i].a_type & ACL_DEFAULT) { 688 acep->flag |= ACE4_INHERIT_ONLY_ACE | 689 ACE4_FILE_INHERIT_ACE | 690 ACE4_DIRECTORY_INHERIT_ACE; 691 } 692 693 /* 694 * handle a_perm and a_id 695 * 696 * this must be done last, since it involves the 697 * corresponding deny aces, which are handled 698 * differently for each different a_type. 699 */ 700 if (aclent[i].a_type & USER_OBJ) { 701 (void) str_to_utf8(ACE4_WHO_OWNER, &acep->who); 702 ace4_make_deny(acep, acep + 1, isdir, TRUE, isserver); 703 acep += 2; 704 } else if (aclent[i].a_type & USER) { 705 error = nfs_idmap_uid_str(aclent[i].a_id, &acep->who, 706 isserver); 707 if (error != 0) { 708 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 709 "ln_aent_to_ace4: uid idmap failed " 710 "with error %d", error)); 711 goto out; 712 } 713 ace4_make_deny(acep, acep + 1, isdir, FALSE, isserver); 714 acep += 2; 715 } else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) { 716 if (aclent[i].a_type & GROUP_OBJ) { 717 (void) str_to_utf8(ACE4_WHO_GROUP, &acep->who); 718 error = 0; 719 } else { 720 error = nfs_idmap_gid_str(aclent[i].a_id, 721 &acep->who, isserver); 722 } 723 if (error != 0) { 724 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 725 "ln_aent_to_ace4: gid idmap failed " 726 "with error %d", error)); 727 goto out; 728 } 729 acep->flag |= ACE4_IDENTIFIER_GROUP; 730 /* 731 * Set the corresponding deny for the group ace. 732 * 733 * The deny aces go after all of the groups, unlike 734 * everything else, where they immediately follow 735 * the allow ace. 736 * 737 * We calculate "skip", the number of slots to 738 * skip ahead for the deny ace, here. 739 * 740 * The pattern is: 741 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3 742 * thus, skip is 743 * (2 * numgroup) - 1 - groupi 744 * (2 * numgroup) to account for MD + A 745 * - 1 to account for the fact that we're on the 746 * access (A), not the mask (MD) 747 * - groupi to account for the fact that we have 748 * passed up groupi number of MD's. 749 */ 750 skip = (2 * numgroup) - 1 - groupi; 751 ace4_make_deny(acep, acep + skip, isdir, FALSE, 752 isserver); 753 /* 754 * If we just did the last group, skip acep past 755 * all of the denies; else, just move ahead one. 756 */ 757 if (++groupi >= numgroup) 758 acep += numgroup + 1; 759 else 760 acep += 1; 761 } else if (aclent[i].a_type & OTHER_OBJ) { 762 (void) str_to_utf8(ACE4_WHO_EVERYONE, &acep->who); 763 ace4_make_deny(acep, acep + 1, isdir, FALSE, isserver); 764 acep += 2; 765 } else { 766 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 767 "ln_aent_to_ace4: aclent_t with invalid type: %x", 768 aclent[i].a_type)); 769 error = EINVAL; 770 goto out; 771 } 772 } 773 774 *acepp = result; 775 *rescount = resultsize; 776 777 out: 778 779 if (error != 0) { 780 if ((result != NULL) && (resultsize > 0)) { 781 /* free any embedded "who" strings */ 782 for (i = 0; i < resultsize; i++) { 783 acep = result + i; 784 if ((acep->who.utf8string_len > 0) && 785 (acep->who.utf8string_val != NULL)) { 786 kmem_free(acep->who.utf8string_val, 787 acep->who.utf8string_len); 788 } 789 } 790 791 /* free the nfsace4 block */ 792 kmem_free(result, resultsize * sizeof (nfsace4)); 793 } 794 } 795 796 return (error); 797 } 798 799 /* 800 * Convert a POSIX draft ACL (in a vsecattr_t) to an NFSv4 ACL, following 801 * the semantics of the IETF draft, draft-ietf-nfsv4-acl-mapping-01.txt. 802 */ 803 int 804 vs_aent_to_ace4(vsecattr_t *aclentacl, vsecattr_t *vs_ace4, 805 int isdir, int isserver) 806 { 807 int error = 0; 808 nfsace4 *acebuf = NULL; 809 int acecnt = 0; 810 nfsace4 *dfacebuf = NULL; 811 int dfacecnt = 0; 812 813 /* initialize vs_ace4 in case we can't complete our work */ 814 vs_ace4->vsa_mask = 0; 815 vs_ace4->vsa_aclentp = NULL; 816 vs_ace4->vsa_aclcnt = 0; 817 vs_ace4->vsa_dfaclentp = NULL; 818 vs_ace4->vsa_dfaclcnt = 0; 819 vs_ace4->vsa_aclentsz = 0; 820 821 if (! (aclentacl->vsa_mask & (VSA_ACL | VSA_ACLCNT | 822 VSA_DFACL | VSA_DFACLCNT))) { 823 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 824 "vs_aent_to_ace4: vsa_mask lacking proper mask")); 825 error = EINVAL; 826 goto out; 827 } 828 829 if ((aclentacl->vsa_aclcnt < 3) && 830 (aclentacl->vsa_mask & (VSA_ACL | VSA_ACLCNT))) { 831 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 832 "vs_aent_to_ace4: too small vsa_aclcnt, %d", 833 aclentacl->vsa_aclcnt)); 834 error = EINVAL; 835 goto out; 836 } 837 838 if ((aclentacl->vsa_dfaclcnt != 0) && (aclentacl->vsa_dfaclcnt < 3) && 839 (aclentacl->vsa_mask & (VSA_DFACL | VSA_DFACLCNT))) { 840 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 841 "vs_aent_to_ace4: too small vsa_dfaclcnt, %d", 842 aclentacl->vsa_dfaclcnt)); 843 error = EINVAL; 844 goto out; 845 } 846 847 if (aclentacl->vsa_aclcnt > 0) { 848 error = ln_aent_to_ace4(aclentacl->vsa_aclentp, 849 aclentacl->vsa_aclcnt, &acebuf, &acecnt, isdir, isserver); 850 if (error != 0) 851 goto out; 852 } 853 if (aclentacl->vsa_dfaclcnt > 0) { 854 error = ln_aent_to_ace4(aclentacl->vsa_dfaclentp, 855 aclentacl->vsa_dfaclcnt, &dfacebuf, &dfacecnt, isdir, 856 isserver); 857 if (error != 0) 858 goto out; 859 } 860 861 vs_ace4->vsa_aclcnt = acecnt + dfacecnt; 862 /* on error, this is freed by vs_ace4_destroy() */ 863 if (vs_ace4->vsa_aclcnt > 0) 864 vs_ace4->vsa_aclentp = kmem_zalloc(vs_ace4->vsa_aclcnt * 865 sizeof (nfsace4), KM_SLEEP); 866 /* 867 * When we bcopy the nfsace4's, the result (in vsa_aclentp) 868 * will have its "who.utf8string_val" pointer pointing to the 869 * allocated strings. Thus, when we free acebuf and dbacebuf, 870 * we don't need to free these strings. 871 */ 872 if (acecnt > 0) 873 bcopy(acebuf, vs_ace4->vsa_aclentp, acecnt * sizeof (nfsace4)); 874 if (dfacecnt > 0) 875 bcopy(dfacebuf, (nfsace4 *) vs_ace4->vsa_aclentp + acecnt, 876 dfacecnt * sizeof (nfsace4)); 877 vs_ace4->vsa_mask = VSA_ACE | VSA_ACECNT; 878 879 out: 880 if (error != 0) 881 vs_ace4_destroy(vs_ace4); 882 883 if (acebuf != NULL) 884 kmem_free(acebuf, acecnt * sizeof (nfsace4)); 885 if (dfacebuf != NULL) 886 kmem_free(dfacebuf, dfacecnt * sizeof (nfsace4)); 887 888 return (error); 889 } 890 891 static int 892 ace4_mask_to_mode(acemask4 mask, o_mode_t *modep, int isdir) 893 { 894 int error = 0; 895 o_mode_t mode = 0; 896 acemask4 bits, wantbits; 897 898 /* read */ 899 if (mask & ACE4_READ_DATA) 900 mode |= 04; 901 902 /* write */ 903 wantbits = (ACE4_WRITE_DATA | 904 ACE4_APPEND_DATA); 905 if (isdir) 906 wantbits |= ACE4_DELETE_CHILD; 907 bits = mask & wantbits; 908 if (bits != 0) { 909 if (bits != wantbits) { 910 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 911 "ace4_mask_to_mode: bad subset of write flags " 912 "%x", bits)); 913 error = ENOTSUP; 914 goto out; 915 } 916 mode |= 02; 917 } 918 919 /* exec */ 920 if (mask & ACE4_EXECUTE) { 921 mode |= 01; 922 } 923 924 *modep = mode; 925 926 out: 927 return (error); 928 } 929 930 static int 931 ace4_allow_to_mode(acemask4 mask, o_mode_t *modep, int isdir) 932 { 933 /* ACE4_READ_ACL and ACE4_READ_ATTRIBUTES must both be set */ 934 if ((mask & (ACE4_READ_ACL | ACE4_READ_ATTRIBUTES)) != 935 (ACE4_READ_ACL | ACE4_READ_ATTRIBUTES)) { 936 return (ENOTSUP); 937 } 938 939 return (ace4_mask_to_mode(mask, modep, isdir)); 940 } 941 942 /* 943 * Find or create an ace4vals holder for a given id and avl tree. 944 * 945 * Note that only one thread will ever touch these avl trees, so 946 * there is no need for locking. 947 */ 948 static ace4vals_t * 949 ace4vals_find(nfsace4 *ace4, avl_tree_t *avl, int *num) 950 { 951 ace4vals_t key, *rc; 952 avl_index_t where; 953 954 key.key = &ace4->who; 955 rc = avl_find(avl, &key, &where); 956 if (rc != NULL) 957 return (rc); 958 959 /* this memory is freed by ln_ace4_to_aent()->ace4_list_free() */ 960 rc = kmem_cache_alloc(nfs4_ace4vals_cache, KM_SLEEP); 961 ace4vals_init(rc, &ace4->who); 962 avl_insert(avl, rc, where); 963 (*num)++; 964 965 return (rc); 966 } 967 968 static int 969 access_mask_check(nfsace4 *ace4p, int mask_bit, int isserver, int isowner) 970 { 971 int set_deny, err_deny; 972 int set_allow, err_allow; 973 int nfs4_acl_consume; 974 int haswriteperm, hasreadperm; 975 976 if (ace4p->type == ACE4_ACCESS_DENIED_ACE_TYPE) { 977 haswriteperm = (ace4p->access_mask & ACE4_WRITE_DATA) ? 0 : 1; 978 hasreadperm = (ace4p->access_mask & ACE4_READ_DATA) ? 0 : 1; 979 } else { 980 haswriteperm = (ace4p->access_mask & ACE4_WRITE_DATA) ? 1 : 0; 981 hasreadperm = (ace4p->access_mask & ACE4_READ_DATA) ? 1 : 0; 982 } 983 984 if (isserver) 985 nfs4_acl_consume = nfs4_acl_server_consume; 986 else 987 nfs4_acl_consume = nfs4_acl_client_consume; 988 989 if (mask_bit == ACE4_SYNCHRONIZE) { 990 set_deny = ACL_SYNCHRONIZE_SET_DENY; 991 err_deny = ACL_SYNCHRONIZE_ERR_DENY; 992 set_allow = ACL_SYNCHRONIZE_SET_ALLOW; 993 err_allow = ACL_SYNCHRONIZE_ERR_ALLOW; 994 } else if (mask_bit == ACE4_WRITE_OWNER) { 995 set_deny = ACL_WRITE_OWNER_SET_DENY; 996 err_deny = ACL_WRITE_OWNER_ERR_DENY; 997 set_allow = ACL_WRITE_OWNER_SET_ALLOW; 998 err_allow = ACL_WRITE_OWNER_ERR_ALLOW; 999 } else if (mask_bit == ACE4_DELETE) { 1000 set_deny = ACL_DELETE_SET_DENY; 1001 err_deny = ACL_DELETE_ERR_DENY; 1002 set_allow = ACL_DELETE_SET_ALLOW; 1003 err_allow = ACL_DELETE_ERR_ALLOW; 1004 } else if (mask_bit == ACE4_WRITE_ATTRIBUTES) { 1005 if (isowner) { 1006 set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY; 1007 err_deny = ACL_WRITE_ATTRS_OWNER_ERR_DENY; 1008 set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 1009 err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW; 1010 } else if (haswriteperm) { 1011 set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY; 1012 err_deny = ACL_WRITE_ATTRS_WRITER_ERR_DENY; 1013 set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 1014 err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW; 1015 } else { 1016 if ((ace4p->access_mask & mask_bit) && 1017 (ace4p->type & ACE4_ACCESS_ALLOWED_ACE_TYPE)) { 1018 return (ENOTSUP); 1019 } 1020 return (0); 1021 } 1022 } else if (mask_bit == ACE4_READ_NAMED_ATTRS) { 1023 if (!hasreadperm) 1024 return (0); 1025 1026 set_deny = ACL_READ_NAMED_READER_SET_DENY; 1027 err_deny = ACL_READ_NAMED_READER_ERR_DENY; 1028 set_allow = ACL_READ_NAMED_READER_SET_ALLOW; 1029 err_allow = ACL_READ_NAMED_READER_ERR_ALLOW; 1030 } else if (mask_bit == ACE4_WRITE_NAMED_ATTRS) { 1031 if (!haswriteperm) 1032 return (0); 1033 1034 set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY; 1035 err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY; 1036 set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 1037 err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW; 1038 } else 1039 return (EINVAL); 1040 1041 if (ace4p->type == ACE4_ACCESS_DENIED_ACE_TYPE) { 1042 if (nfs4_acl_consume & set_deny) { 1043 if (!(ace4p->access_mask & mask_bit)) { 1044 return (ENOTSUP); 1045 } 1046 } else if (nfs4_acl_consume & err_deny) { 1047 if (ace4p->access_mask & mask_bit) { 1048 return (ENOTSUP); 1049 } 1050 } 1051 } else { 1052 /* ACE4_ACCESS_ALLOWED_ACE_TYPE */ 1053 if (nfs4_acl_consume & set_allow) { 1054 if (!(ace4p->access_mask & mask_bit)) { 1055 return (ENOTSUP); 1056 } 1057 } else if (nfs4_acl_consume & err_allow) { 1058 if (ace4p->access_mask & mask_bit) { 1059 return (ENOTSUP); 1060 } 1061 } 1062 } 1063 return (0); 1064 } 1065 1066 static int 1067 ace4_to_aent_legal(nfsace4 *ace4p, int isserver) 1068 { 1069 int error = 0; 1070 int isowner; 1071 1072 /* check for NULL who string */ 1073 if (ace4p->who.utf8string_val == NULL) { 1074 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1075 "ace4_to_aent_legal: NULL who string")); 1076 error = EINVAL; 1077 goto out; 1078 } 1079 1080 /* only ALLOW or DENY */ 1081 if ((ace4p->type != ACE4_ACCESS_ALLOWED_ACE_TYPE) && 1082 (ace4p->type != ACE4_ACCESS_DENIED_ACE_TYPE)) { 1083 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1084 "ace4_to_aent_legal: neither allow nor deny")); 1085 error = ENOTSUP; 1086 goto out; 1087 } 1088 1089 /* check for invalid flags */ 1090 if (ace4p->flag & ~(ACE4_VALID_FLAG_BITS)) { 1091 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1092 "ace4_to_aent_legal: invalid flags: %x", ace4p->flag)); 1093 error = EINVAL; 1094 goto out; 1095 } 1096 1097 /* some flags are illegal */ 1098 if (ace4p->flag & (ACE4_SUCCESSFUL_ACCESS_ACE_FLAG | 1099 ACE4_FAILED_ACCESS_ACE_FLAG | 1100 ACE4_NO_PROPAGATE_INHERIT_ACE)) { 1101 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1102 "ace4_to_aent_legal: illegal flags: %x", ace4p->flag)); 1103 error = ENOTSUP; 1104 goto out; 1105 } 1106 1107 /* check for invalid masks */ 1108 if (ace4p->access_mask & ~(ACE4_VALID_MASK_BITS)) { 1109 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1110 "ace4_to_aent_legal: invalid mask: %x", 1111 ace4p->access_mask)); 1112 error = EINVAL; 1113 goto out; 1114 } 1115 1116 if ((ace4p->who.utf8string_len == 6) && 1117 (bcmp(ACE4_WHO_OWNER, ace4p->who.utf8string_val, 6) == 0)) { 1118 isowner = 1; 1119 } else { 1120 isowner = 0; 1121 } 1122 1123 error = access_mask_check(ace4p, ACE4_SYNCHRONIZE, isserver, isowner); 1124 if (error) 1125 goto out; 1126 1127 error = access_mask_check(ace4p, ACE4_WRITE_OWNER, isserver, isowner); 1128 if (error) 1129 goto out; 1130 1131 error = access_mask_check(ace4p, ACE4_DELETE, isserver, isowner); 1132 if (error) 1133 goto out; 1134 1135 error = access_mask_check(ace4p, ACE4_WRITE_ATTRIBUTES, isserver, 1136 isowner); 1137 if (error) 1138 goto out; 1139 1140 error = access_mask_check(ace4p, ACE4_READ_NAMED_ATTRS, isserver, 1141 isowner); 1142 if (error) 1143 goto out; 1144 1145 error = access_mask_check(ace4p, ACE4_WRITE_NAMED_ATTRS, isserver, 1146 isowner); 1147 if (error) 1148 goto out; 1149 1150 /* more detailed checking of masks */ 1151 if (ace4p->type == ACE4_ACCESS_ALLOWED_ACE_TYPE) { 1152 if (! (ace4p->access_mask & ACE4_READ_ATTRIBUTES)) { 1153 error = ENOTSUP; 1154 goto out; 1155 } 1156 if ((ace4p->access_mask & ACE4_WRITE_DATA) && 1157 (! (ace4p->access_mask & ACE4_APPEND_DATA))) { 1158 error = ENOTSUP; 1159 goto out; 1160 } 1161 if ((! (ace4p->access_mask & ACE4_WRITE_DATA)) && 1162 (ace4p->access_mask & ACE4_APPEND_DATA)) { 1163 error = ENOTSUP; 1164 goto out; 1165 } 1166 } 1167 1168 /* ACL enforcement */ 1169 if ((ace4p->access_mask & ACE4_READ_ACL) && 1170 (ace4p->type != ACE4_ACCESS_ALLOWED_ACE_TYPE)) { 1171 error = ENOTSUP; 1172 goto out; 1173 } 1174 if (ace4p->access_mask & ACE4_WRITE_ACL) { 1175 if ((ace4p->type == ACE4_ACCESS_DENIED_ACE_TYPE) && 1176 (isowner)) { 1177 error = ENOTSUP; 1178 goto out; 1179 } 1180 if ((ace4p->type == ACE4_ACCESS_ALLOWED_ACE_TYPE) && 1181 (! isowner)) { 1182 error = ENOTSUP; 1183 goto out; 1184 } 1185 } 1186 1187 out: 1188 return (error); 1189 } 1190 1191 static int 1192 ace4vals_to_aent(ace4vals_t *vals, aclent_t *dest, ace4_list_t *list, 1193 uid_t owner, gid_t group, int isdir, int isserver) 1194 { 1195 int error; 1196 acemask4 flips = ACE4_POSIX_SUPPORTED_BITS; 1197 1198 if (isdir) 1199 flips |= ACE4_DELETE_CHILD; 1200 if (vals->allowed != (vals->denied ^ flips)) { 1201 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1202 "ace4vals_to_aent: mis-matched allow/deny pair: %x/%x", 1203 vals->allowed, vals->denied)); 1204 error = ENOTSUP; 1205 goto out; 1206 } 1207 if ((list->hasmask) && (list->acl_mask != vals->mask) && 1208 (vals->aent_type & (USER | GROUP | GROUP_OBJ))) { 1209 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1210 "ace4vals_to_aent: entry is missing mask")); 1211 error = ENOTSUP; 1212 goto out; 1213 } 1214 error = ace4_allow_to_mode(vals->allowed, &dest->a_perm, isdir); 1215 if (error != 0) 1216 goto out; 1217 dest->a_type = vals->aent_type; 1218 if (dest->a_type & (USER | GROUP)) { 1219 if (dest->a_type & USER) 1220 error = nfs_idmap_str_uid(vals->key, &dest->a_id, 1221 isserver); 1222 else 1223 error = nfs_idmap_str_gid(vals->key, &dest->a_id, 1224 isserver); 1225 if (error != 0) { 1226 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1227 "ace4vals_to_aent: idmap failed with %d", error)); 1228 if (isserver && (error == EPERM)) 1229 error = NFS4ERR_BADOWNER; 1230 goto out; 1231 } 1232 1233 error = validate_idmapping(vals->key, &dest->a_id, 1234 (dest->a_type & USER ? 1 : 0), isserver); 1235 if (error != 0) { 1236 goto out; 1237 } 1238 } else if (dest->a_type & USER_OBJ) { 1239 dest->a_id = owner; 1240 } else if (dest->a_type & GROUP_OBJ) { 1241 dest->a_id = group; 1242 } else if (dest->a_type & OTHER_OBJ) { 1243 dest->a_id = 0; 1244 } else { 1245 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1246 "ace4vals_to_aent: dest->a_type invalid: %x " 1247 "(internal error)", dest->a_type)); 1248 error = EINVAL; 1249 goto out; 1250 } 1251 1252 out: 1253 return (error); 1254 } 1255 1256 static int 1257 ace4_list_to_aent(ace4_list_t *list, aclent_t **aclentp, int *aclcnt, 1258 uid_t owner, gid_t group, int isdir, int isserver) 1259 { 1260 int error = 0; 1261 aclent_t *aent, *result = NULL; 1262 ace4vals_t *vals; 1263 int resultcount; 1264 1265 if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) != 1266 (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) { 1267 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1268 "ace4_list_to_aent: required aclent_t entites missing")); 1269 error = ENOTSUP; 1270 goto out; 1271 } 1272 if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) { 1273 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1274 "ace4_list_to_aent: CLASS_OBJ (mask) missing")); 1275 error = ENOTSUP; 1276 goto out; 1277 } 1278 1279 resultcount = 3 + list->numusers + list->numgroups; 1280 /* 1281 * This must be the same condition as below, when we add the CLASS_OBJ 1282 * (aka ACL mask) 1283 */ 1284 if ((list->hasmask) || (! list->dfacl_flag)) 1285 resultcount += 1; 1286 1287 result = aent = kmem_alloc(resultcount * sizeof (aclent_t), KM_SLEEP); 1288 1289 /* USER_OBJ */ 1290 ASSERT(list->user_obj.aent_type & USER_OBJ); 1291 error = ace4vals_to_aent(&list->user_obj, aent, list, owner, group, 1292 isdir, isserver); 1293 1294 if (error != 0) 1295 goto out; 1296 ++aent; 1297 /* USER */ 1298 vals = NULL; 1299 for (vals = avl_first(&list->user); vals != NULL; 1300 vals = AVL_NEXT(&list->user, vals)) { 1301 ASSERT(vals->aent_type & USER); 1302 error = ace4vals_to_aent(vals, aent, list, owner, group, 1303 isdir, isserver); 1304 if (error != 0) 1305 goto out; 1306 ++aent; 1307 } 1308 /* GROUP_OBJ */ 1309 ASSERT(list->group_obj.aent_type & GROUP_OBJ); 1310 error = ace4vals_to_aent(&list->group_obj, aent, list, owner, group, 1311 isdir, isserver); 1312 if (error != 0) 1313 goto out; 1314 ++aent; 1315 /* GROUP */ 1316 vals = NULL; 1317 for (vals = avl_first(&list->group); vals != NULL; 1318 vals = AVL_NEXT(&list->group, vals)) { 1319 ASSERT(vals->aent_type & GROUP); 1320 error = ace4vals_to_aent(vals, aent, list, owner, group, 1321 isdir, isserver); 1322 if (error != 0) 1323 goto out; 1324 ++aent; 1325 } 1326 /* 1327 * CLASS_OBJ (aka ACL_MASK) 1328 * 1329 * An ACL_MASK is not fabricated if the ACL is a default ACL. 1330 * This is to follow UFS's behavior. 1331 */ 1332 if ((list->hasmask) || (! list->dfacl_flag)) { 1333 if (list->hasmask) { 1334 acemask4 flips = ACE4_POSIX_SUPPORTED_BITS; 1335 if (isdir) 1336 flips |= ACE4_DELETE_CHILD; 1337 error = ace4_mask_to_mode(list->acl_mask ^ flips, 1338 &aent->a_perm, isdir); 1339 if (error != 0) 1340 goto out; 1341 } else { 1342 /* fabricate the ACL_MASK from the group permissions */ 1343 error = ace4_mask_to_mode(list->group_obj.allowed, 1344 &aent->a_perm, isdir); 1345 if (error != 0) 1346 goto out; 1347 } 1348 aent->a_id = 0; 1349 aent->a_type = CLASS_OBJ | list->dfacl_flag; 1350 ++aent; 1351 } 1352 /* OTHER_OBJ */ 1353 ASSERT(list->other_obj.aent_type & OTHER_OBJ); 1354 error = ace4vals_to_aent(&list->other_obj, aent, list, owner, group, 1355 isdir, isserver); 1356 if (error != 0) 1357 goto out; 1358 ++aent; 1359 1360 *aclentp = result; 1361 *aclcnt = resultcount; 1362 1363 out: 1364 if (error != 0) { 1365 if (result != NULL) 1366 kmem_free(result, resultcount * sizeof (aclent_t)); 1367 } 1368 1369 return (error); 1370 } 1371 1372 /* 1373 * Convert a list of nfsace4 entries to equivalent regular and default 1374 * aclent_t lists. Return error (ENOTSUP) when conversion is not possible. 1375 */ 1376 static int 1377 ln_ace4_to_aent(nfsace4 *ace4, int n, 1378 uid_t owner, gid_t group, 1379 aclent_t **aclentp, int *aclcnt, 1380 aclent_t **dfaclentp, int *dfaclcnt, 1381 int isdir, int isserver) 1382 { 1383 int error = 0; 1384 nfsace4 *ace4p; 1385 acemask4 bits; 1386 int i; 1387 ace4_list_t *normacl = NULL, *dfacl = NULL, *acl; 1388 ace4vals_t *vals; 1389 1390 *aclentp = NULL; 1391 *aclcnt = 0; 1392 *dfaclentp = NULL; 1393 *dfaclcnt = 0; 1394 1395 /* we need at least user_obj, group_obj, and other_obj */ 1396 if (n < 6) { 1397 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1398 "ln_ace4_to_aent: too few nfsace4 entries: %d", n)); 1399 error = ENOTSUP; 1400 goto out; 1401 } 1402 if (ace4 == NULL) { 1403 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1404 "ln_ace4_to_aent: NULL source")); 1405 error = EINVAL; 1406 goto out; 1407 } 1408 1409 normacl = kmem_cache_alloc(nfs4_ace4_list_cache, KM_SLEEP); 1410 ace4_list_init(normacl, 0); 1411 dfacl = kmem_cache_alloc(nfs4_ace4_list_cache, KM_SLEEP); 1412 ace4_list_init(dfacl, ACL_DEFAULT); 1413 1414 /* process every nfsace4... */ 1415 for (i = 0; i < n; i++) { 1416 ace4p = &ace4[i]; 1417 1418 /* rule out certain cases quickly */ 1419 error = ace4_to_aent_legal(ace4p, isserver); 1420 if (error != 0) 1421 goto out; 1422 1423 /* 1424 * Turn off these bits in order to not have to worry about 1425 * them when doing the checks for compliments. 1426 */ 1427 ace4p->access_mask &= ~(ACE4_WRITE_OWNER | ACE4_DELETE | 1428 ACE4_SYNCHRONIZE | ACE4_WRITE_ATTRIBUTES | 1429 ACE4_READ_NAMED_ATTRS | ACE4_WRITE_NAMED_ATTRS); 1430 1431 /* see if this should be a regular or default acl */ 1432 bits = ace4p->flag & 1433 (ACE4_INHERIT_ONLY_ACE | 1434 ACE4_FILE_INHERIT_ACE | 1435 ACE4_DIRECTORY_INHERIT_ACE); 1436 if (bits != 0) { 1437 /* all or nothing on these inherit bits */ 1438 if (bits != (ACE4_INHERIT_ONLY_ACE | 1439 ACE4_FILE_INHERIT_ACE | 1440 ACE4_DIRECTORY_INHERIT_ACE)) { 1441 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1442 "ln_ace4_to_aent: bad inherit flags " 1443 "%x", bits)); 1444 error = ENOTSUP; 1445 goto out; 1446 } 1447 acl = dfacl; 1448 } else { 1449 acl = normacl; 1450 } 1451 1452 if ((ace4p->who.utf8string_len == 6) && 1453 (bcmp(ACE4_WHO_OWNER, 1454 ace4p->who.utf8string_val, 6) == 0)) { 1455 if (acl->state > ace4_user_obj) { 1456 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1457 "ln_ace4_to_aent: OWNER@ found " 1458 "out of order")); 1459 error = ENOTSUP; 1460 goto out; 1461 } 1462 acl->state = ace4_user_obj; 1463 acl->seen |= USER_OBJ; 1464 vals = &acl->user_obj; 1465 vals->aent_type = USER_OBJ | acl->dfacl_flag; 1466 } else if ((ace4p->who.utf8string_len == 9) && 1467 (bcmp(ACE4_WHO_EVERYONE, ace4p->who.utf8string_val, 9) 1468 == 0)) { 1469 acl->state = ace4_other_obj; 1470 acl->seen |= OTHER_OBJ; 1471 vals = &acl->other_obj; 1472 vals->aent_type = OTHER_OBJ | acl->dfacl_flag; 1473 } else if ((ace4p->who.utf8string_len == 6) && 1474 (bcmp(ACE4_WHO_GROUP, ace4p->who.utf8string_val, 6) == 0)) { 1475 if (acl->state > ace4_group) { 1476 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1477 "ln_ace4_to_aent: group entry found " 1478 "out of order")); 1479 error = ENOTSUP; 1480 goto out; 1481 } 1482 acl->seen |= GROUP_OBJ; 1483 vals = &acl->group_obj; 1484 vals->aent_type = GROUP_OBJ | acl->dfacl_flag; 1485 acl->state = ace4_group; 1486 } else if (ace4p->flag & ACE4_IDENTIFIER_GROUP) { 1487 if (acl->state > ace4_group) { 1488 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1489 "ln_ace4_to_aent: group entry found " 1490 "out of order")); 1491 error = ENOTSUP; 1492 goto out; 1493 } 1494 acl->seen |= GROUP; 1495 vals = ace4vals_find(ace4p, &acl->group, 1496 &acl->numgroups); 1497 vals->aent_type = GROUP | acl->dfacl_flag; 1498 acl->state = ace4_group; 1499 } else { 1500 if (acl->state > ace4_user) { 1501 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1502 "ln_ace4_to_aent: user entry found " 1503 "out of order")); 1504 error = ENOTSUP; 1505 goto out; 1506 } 1507 acl->state = ace4_user; 1508 acl->seen |= USER; 1509 vals = ace4vals_find(ace4p, &acl->user, 1510 &acl->numusers); 1511 vals->aent_type = USER | acl->dfacl_flag; 1512 } 1513 ASSERT(acl->state > ace4_unused); 1514 1515 if (ace4p->type == ACE4_ACCESS_ALLOWED_ACE_TYPE) { 1516 /* no more than one allowed per aclent_t */ 1517 if (vals->allowed != ACE4_MASK_UNDEFINED) { 1518 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1519 "ln_ace4_to_aent: too many ALLOWs " 1520 "for one entity")); 1521 error = ENOTSUP; 1522 goto out; 1523 } 1524 vals->allowed = ace4p->access_mask; 1525 } else { 1526 /* 1527 * it's a DENY; if there was a previous DENY, it 1528 * must have been an ACL_MASK. 1529 */ 1530 if (vals->denied != ACE4_MASK_UNDEFINED) { 1531 /* ACL_MASK is for USER and GROUP only */ 1532 if ((acl->state != ace4_user) && 1533 (acl->state != ace4_group)) { 1534 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1535 "ln_ace4_to_aent: ACL_MASK-like " 1536 "DENY found on non-user/non-group " 1537 "entity")); 1538 error = ENOTSUP; 1539 goto out; 1540 } 1541 1542 if (! acl->hasmask) { 1543 acl->hasmask = 1; 1544 acl->acl_mask = vals->denied; 1545 /* check for mismatched ACL_MASK emulations */ 1546 } else if (acl->acl_mask != vals->denied) { 1547 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1548 "ln_ace4_to_aent: ACL_MASK " 1549 "mismatch")); 1550 error = ENOTSUP; 1551 goto out; 1552 } 1553 vals->mask = vals->denied; 1554 } 1555 vals->denied = ace4p->access_mask; 1556 } 1557 } 1558 1559 /* done collating; produce the aclent_t lists */ 1560 if (normacl->state != ace4_unused) { 1561 error = ace4_list_to_aent(normacl, aclentp, aclcnt, 1562 owner, group, isdir, isserver); 1563 if (error != 0) 1564 goto out; 1565 } 1566 if (dfacl->state != ace4_unused) { 1567 error = ace4_list_to_aent(dfacl, dfaclentp, dfaclcnt, 1568 owner, group, isdir, isserver); 1569 if (error != 0) 1570 goto out; 1571 } 1572 1573 out: 1574 if (normacl != NULL) 1575 ace4_list_free(normacl); 1576 if (dfacl != NULL) 1577 ace4_list_free(dfacl); 1578 1579 return (error); 1580 } 1581 1582 /* 1583 * Convert an NFSv4 ACL (in a vsecattr_t) to a POSIX draft ACL, following 1584 * the semantics of NFSv4_to_POSIX.html. Contact fsh-group@sun.com to 1585 * obtain this document. 1586 */ 1587 int 1588 vs_ace4_to_aent(vsecattr_t *vs_ace4, vsecattr_t *vs_aent, 1589 uid_t owner, gid_t group, int isdir, int isserver) 1590 { 1591 int error = 0; 1592 1593 error = ln_ace4_to_aent(vs_ace4->vsa_aclentp, vs_ace4->vsa_aclcnt, 1594 owner, group, 1595 (aclent_t **)&vs_aent->vsa_aclentp, &vs_aent->vsa_aclcnt, 1596 (aclent_t **)&vs_aent->vsa_dfaclentp, &vs_aent->vsa_dfaclcnt, 1597 isdir, isserver); 1598 if (error != 0) 1599 goto out; 1600 1601 vs_aent->vsa_mask = VSA_ACL | VSA_ACLCNT | VSA_DFACL | VSA_DFACLCNT; 1602 if ((vs_aent->vsa_aclcnt == 0) && (vs_aent->vsa_dfaclcnt == 0)) { 1603 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1604 "vs_ace4_to_aent: neither ACL nor default ACL found")); 1605 error = ENOTSUP; 1606 goto out; 1607 } 1608 1609 out: 1610 if (error != 0) { 1611 if (vs_aent != NULL) 1612 vs_aent_destroy(vs_aent); 1613 } 1614 1615 return (error); 1616 } 1617 1618 /* 1619 * compare two ace4 acls 1620 */ 1621 1622 static int 1623 ace4_cmp(nfsace4 *a, nfsace4 *b) 1624 { 1625 if (a->type < b->type) 1626 return (-1); 1627 if (a->type > b->type) 1628 return (1); 1629 if (a->flag < b->flag) 1630 return (-1); 1631 if (a->flag > b->flag) 1632 return (1); 1633 if (a->access_mask < b->access_mask) 1634 return (-1); 1635 if (a->access_mask > b->access_mask) 1636 return (1); 1637 return (utf8_compare(&a->who, &b->who)); 1638 } 1639 1640 int 1641 ln_ace4_cmp(nfsace4 *a, nfsace4* b, int n) 1642 { 1643 int rc; 1644 int i; 1645 1646 for (i = 0; i < n; i++) { 1647 rc = ace4_cmp(a + i, b + i); 1648 if (rc != 0) 1649 return (rc); 1650 } 1651 return (0); 1652 } 1653 1654 /* 1655 * Convert an ace_t to an nfsace4; the primary difference being 1656 * strings versus integer uid/gids. 1657 */ 1658 static int 1659 acet_to_ace4(ace_t *ace, nfsace4 *nfsace4, int isserver) 1660 { 1661 int error = 0; 1662 1663 if (ace == NULL) { 1664 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1665 "acet_to_ace4: NULL source")); 1666 error = EINVAL; 1667 goto out; 1668 } 1669 if (nfsace4 == NULL) { 1670 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1671 "acet_to_ace4: NULL destination")); 1672 error = EINVAL; 1673 goto out; 1674 } 1675 1676 switch (ace->a_type) { 1677 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1678 nfsace4->type = ACE4_ACCESS_ALLOWED_ACE_TYPE; 1679 break; 1680 case ACE_ACCESS_DENIED_ACE_TYPE: 1681 nfsace4->type = ACE4_ACCESS_DENIED_ACE_TYPE; 1682 break; 1683 default: 1684 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1685 "acet_to_ace4: unsupported type: %x", ace->a_type)); 1686 error = ENOTSUP; 1687 break; 1688 } 1689 if (error != 0) 1690 goto out; 1691 1692 acet_mask_to_ace4_mask(ace->a_access_mask, &nfsace4->access_mask); 1693 acet_flags_to_ace4_flags(ace->a_flags, &nfsace4->flag); 1694 1695 if (ace->a_flags & ACE_GROUP) { 1696 nfsace4->flag |= ACE4_IDENTIFIER_GROUP; 1697 (void) str_to_utf8(ACE4_WHO_GROUP, &nfsace4->who); 1698 } else if (ace->a_flags & ACE_IDENTIFIER_GROUP) { 1699 nfsace4->flag |= ACE4_IDENTIFIER_GROUP; 1700 /* 1701 * On the client, we do not allow an ACL with ACEs containing 1702 * the "unknown"/GID_UNKNOWN group to be set. This is because 1703 * it having GID_UNKNOWN in an ACE can only come from 1704 * the user having done a read-modify-write ACL manipulation 1705 * (e.g. setfacl -m or chmod A+) when there was an ACE with 1706 * an unmappable group already present. 1707 */ 1708 if (ace->a_who == GID_UNKNOWN && !isserver) { 1709 DTRACE_PROBE(nfs4clnt__err__acl__gid__unknown); 1710 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1711 "acet_to_ace4: GID_UNKNOWN is not allowed in " 1712 "the ACL")); 1713 error = EACCES; 1714 goto out; 1715 } 1716 error = nfs_idmap_gid_str(ace->a_who, &nfsace4->who, isserver); 1717 if (error != 0) 1718 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1719 "acet_to_ace4: idmap failed with %d", error)); 1720 } else if (ace->a_flags & ACE_OWNER) { 1721 (void) str_to_utf8(ACE4_WHO_OWNER, &nfsace4->who); 1722 } else if (ace->a_flags & ACE_EVERYONE) { 1723 (void) str_to_utf8(ACE4_WHO_EVERYONE, &nfsace4->who); 1724 } else { 1725 /* 1726 * Same rule as GID_UNKNOWN (above). 1727 */ 1728 if (ace->a_who == UID_UNKNOWN && !isserver) { 1729 DTRACE_PROBE(nfs4clnt__err__acl__uid__unknown); 1730 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1731 "acet_to_ace4: UID_UNKNOWN is not allowed in " 1732 "the ACL")); 1733 error = EACCES; 1734 goto out; 1735 } 1736 error = nfs_idmap_uid_str(ace->a_who, &nfsace4->who, isserver); 1737 if (error != 0) 1738 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1739 "acet_to_ace4: idmap failed with %d", error)); 1740 } 1741 1742 out: 1743 return (error); 1744 } 1745 1746 /* 1747 * Convert an nfsace4 to an ace_t, the primary difference being 1748 * integer uid/gids versus strings. 1749 */ 1750 static int 1751 ace4_to_acet(nfsace4 *nfsace4, ace_t *ace, uid_t owner, gid_t group, 1752 int isserver) 1753 { 1754 int error = 0; 1755 1756 if (nfsace4 == NULL) { 1757 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1758 "ace4_to_acet: NULL source")); 1759 return (EINVAL); 1760 } 1761 if (ace == NULL) { 1762 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1763 "ace4_to_acet: NULL destination")); 1764 return (EINVAL); 1765 } 1766 1767 switch (nfsace4->type) { 1768 case ACE4_ACCESS_ALLOWED_ACE_TYPE: 1769 ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 1770 break; 1771 case ACE4_ACCESS_DENIED_ACE_TYPE: 1772 ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 1773 break; 1774 default: 1775 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1776 "ace4_to_acet: unsupported type: %x", nfsace4->type)); 1777 error = ENOTSUP; 1778 break; 1779 } 1780 if (error != 0) 1781 goto out; 1782 1783 if (nfsace4->flag & ~(ACE4_VALID_FLAG_BITS)) { 1784 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1785 "ace4_to_acet: invalid flags: %x", nfsace4->flag)); 1786 error = EINVAL; 1787 goto out; 1788 } 1789 1790 /* check for invalid masks */ 1791 if (nfsace4->access_mask & ~(ACE4_VALID_MASK_BITS)) { 1792 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1793 "ace4_to_acet: invalid mask: %x", nfsace4->access_mask)); 1794 error = EINVAL; 1795 goto out; 1796 } 1797 1798 ace4_mask_to_acet_mask(nfsace4->access_mask, &ace->a_access_mask); 1799 1800 if (nfsace4->flag & ~ACE_NFSV4_SUP_FLAGS) { 1801 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1802 "ace4_to_acet: unsupported flags: %x", nfsace4->flag)); 1803 error = ENOTSUP; 1804 goto out; 1805 } 1806 ace4_flags_to_acet_flags(nfsace4->flag, &ace->a_flags); 1807 1808 if ((nfsace4->who.utf8string_len == 6) && 1809 (bcmp(ACE4_WHO_GROUP, 1810 nfsace4->who.utf8string_val, 6)) == 0) { 1811 ace->a_who = group; 1812 ace->a_flags |= ACE_GROUP | ACE_IDENTIFIER_GROUP; 1813 } else if ((nfsace4->who.utf8string_len == 6) && 1814 (bcmp(ACE4_WHO_OWNER, 1815 nfsace4->who.utf8string_val, 6) == 0)) { 1816 ace->a_flags |= ACE_OWNER; 1817 ace->a_who = owner; 1818 } else if ((nfsace4->who.utf8string_len == 9) && 1819 (bcmp(ACE4_WHO_EVERYONE, 1820 nfsace4->who.utf8string_val, 9) == 0)) { 1821 ace->a_flags |= ACE_EVERYONE; 1822 ace->a_who = 0; 1823 } else if (nfsace4->flag & ACE4_IDENTIFIER_GROUP) { 1824 ace->a_flags |= ACE_IDENTIFIER_GROUP; 1825 error = nfs_idmap_str_gid(&nfsace4->who, 1826 &ace->a_who, isserver); 1827 if (error != 0) { 1828 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1829 "ace4_to_acet: idmap failed with %d", 1830 error)); 1831 if (isserver && (error == EPERM)) 1832 error = NFS4ERR_BADOWNER; 1833 goto out; 1834 } 1835 error = validate_idmapping(&nfsace4->who, 1836 &ace->a_who, FALSE, isserver); 1837 if (error != 0) 1838 goto out; 1839 } else { 1840 error = nfs_idmap_str_uid(&nfsace4->who, 1841 &ace->a_who, isserver); 1842 if (error != 0) { 1843 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1844 "ace4_to_acet: idmap failed with %d", 1845 error)); 1846 if (isserver && (error == EPERM)) 1847 error = NFS4ERR_BADOWNER; 1848 goto out; 1849 } 1850 error = validate_idmapping(&nfsace4->who, 1851 &ace->a_who, TRUE, isserver); 1852 if (error != 0) 1853 goto out; 1854 } 1855 1856 out: 1857 return (error); 1858 } 1859 1860 static void 1861 ace4_mask_to_acet_mask(acemask4 ace4_mask, uint32_t *acet_mask) 1862 { 1863 *acet_mask = 0; 1864 1865 if (ace4_mask & ACE4_READ_DATA) 1866 *acet_mask |= ACE_READ_DATA; 1867 if (ace4_mask & ACE4_WRITE_DATA) 1868 *acet_mask |= ACE_WRITE_DATA; 1869 if (ace4_mask & ACE4_APPEND_DATA) 1870 *acet_mask |= ACE_APPEND_DATA; 1871 if (ace4_mask & ACE4_READ_NAMED_ATTRS) 1872 *acet_mask |= ACE_READ_NAMED_ATTRS; 1873 if (ace4_mask & ACE4_WRITE_NAMED_ATTRS) 1874 *acet_mask |= ACE_WRITE_NAMED_ATTRS; 1875 if (ace4_mask & ACE4_EXECUTE) 1876 *acet_mask |= ACE_EXECUTE; 1877 if (ace4_mask & ACE4_DELETE_CHILD) 1878 *acet_mask |= ACE_DELETE_CHILD; 1879 if (ace4_mask & ACE4_READ_ATTRIBUTES) 1880 *acet_mask |= ACE_READ_ATTRIBUTES; 1881 if (ace4_mask & ACE4_WRITE_ATTRIBUTES) 1882 *acet_mask |= ACE_WRITE_ATTRIBUTES; 1883 if (ace4_mask & ACE4_DELETE) 1884 *acet_mask |= ACE_DELETE; 1885 if (ace4_mask & ACE4_READ_ACL) 1886 *acet_mask |= ACE_READ_ACL; 1887 if (ace4_mask & ACE4_WRITE_ACL) 1888 *acet_mask |= ACE_WRITE_ACL; 1889 if (ace4_mask & ACE4_WRITE_OWNER) 1890 *acet_mask |= ACE_WRITE_OWNER; 1891 if (ace4_mask & ACE4_SYNCHRONIZE) 1892 *acet_mask |= ACE_SYNCHRONIZE; 1893 } 1894 1895 static void 1896 acet_mask_to_ace4_mask(uint32_t acet_mask, acemask4 *ace4_mask) 1897 { 1898 *ace4_mask = 0; 1899 1900 if (acet_mask & ACE_READ_DATA) 1901 *ace4_mask |= ACE4_READ_DATA; 1902 if (acet_mask & ACE_WRITE_DATA) 1903 *ace4_mask |= ACE4_WRITE_DATA; 1904 if (acet_mask & ACE_APPEND_DATA) 1905 *ace4_mask |= ACE_APPEND_DATA; 1906 if (acet_mask & ACE4_READ_NAMED_ATTRS) 1907 *ace4_mask |= ACE_READ_NAMED_ATTRS; 1908 if (acet_mask & ACE_WRITE_NAMED_ATTRS) 1909 *ace4_mask |= ACE4_WRITE_NAMED_ATTRS; 1910 if (acet_mask & ACE_EXECUTE) 1911 *ace4_mask |= ACE4_EXECUTE; 1912 if (acet_mask & ACE_DELETE_CHILD) 1913 *ace4_mask |= ACE4_DELETE_CHILD; 1914 if (acet_mask & ACE_READ_ATTRIBUTES) 1915 *ace4_mask |= ACE4_READ_ATTRIBUTES; 1916 if (acet_mask & ACE_WRITE_ATTRIBUTES) 1917 *ace4_mask |= ACE4_WRITE_ATTRIBUTES; 1918 if (acet_mask & ACE_DELETE) 1919 *ace4_mask |= ACE4_DELETE; 1920 if (acet_mask & ACE_READ_ACL) 1921 *ace4_mask |= ACE4_READ_ACL; 1922 if (acet_mask & ACE_WRITE_ACL) 1923 *ace4_mask |= ACE4_WRITE_ACL; 1924 if (acet_mask & ACE_WRITE_OWNER) 1925 *ace4_mask |= ACE4_WRITE_OWNER; 1926 if (acet_mask & ACE_SYNCHRONIZE) 1927 *ace4_mask |= ACE4_SYNCHRONIZE; 1928 } 1929 1930 static void 1931 ace4_flags_to_acet_flags(aceflag4 ace4_flags, uint16_t *acet_flags) 1932 { 1933 *acet_flags = 0; 1934 1935 if (ace4_flags & ACE4_FILE_INHERIT_ACE) 1936 *acet_flags |= ACE_FILE_INHERIT_ACE; 1937 if (ace4_flags & ACE4_DIRECTORY_INHERIT_ACE) 1938 *acet_flags |= ACE_DIRECTORY_INHERIT_ACE; 1939 if (ace4_flags & ACE4_NO_PROPAGATE_INHERIT_ACE) 1940 *acet_flags |= ACE_NO_PROPAGATE_INHERIT_ACE; 1941 if (ace4_flags & ACE4_INHERIT_ONLY_ACE) 1942 *acet_flags |= ACE_INHERIT_ONLY_ACE; 1943 if (ace4_flags & ACE4_SUCCESSFUL_ACCESS_ACE_FLAG) 1944 *acet_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 1945 if (ace4_flags & ACE4_FAILED_ACCESS_ACE_FLAG) 1946 *acet_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 1947 /* ACE_IDENTIFIER_GROUP is handled in ace4_to_acet() */ 1948 } 1949 1950 static void 1951 acet_flags_to_ace4_flags(uint16_t acet_flags, aceflag4 *ace4_flags) 1952 { 1953 *ace4_flags = 0; 1954 1955 if (acet_flags & ACE_FILE_INHERIT_ACE) 1956 *ace4_flags |= ACE4_FILE_INHERIT_ACE; 1957 if (acet_flags & ACE_DIRECTORY_INHERIT_ACE) 1958 *ace4_flags |= ACE4_DIRECTORY_INHERIT_ACE; 1959 if (acet_flags & ACE_NO_PROPAGATE_INHERIT_ACE) 1960 *ace4_flags |= ACE4_NO_PROPAGATE_INHERIT_ACE; 1961 if (acet_flags & ACE_INHERIT_ONLY_ACE) 1962 *ace4_flags |= ACE4_INHERIT_ONLY_ACE; 1963 if (acet_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 1964 *ace4_flags |= ACE4_SUCCESSFUL_ACCESS_ACE_FLAG; 1965 if (acet_flags & ACE_FAILED_ACCESS_ACE_FLAG) 1966 *ace4_flags |= ACE4_FAILED_ACCESS_ACE_FLAG; 1967 /* ACE4_IDENTIFIER_GROUP is handled in acet_to_ace4() */ 1968 } 1969 1970 int 1971 vs_ace4_to_acet(vsecattr_t *vs_ace4, vsecattr_t *vs_acet, 1972 uid_t owner, gid_t group, int isserver) 1973 { 1974 int error; 1975 int i; 1976 1977 if ((vs_ace4->vsa_mask & (VSA_ACE | VSA_ACECNT)) != 1978 (VSA_ACE | VSA_ACECNT)) 1979 return (EINVAL); 1980 if (vs_ace4->vsa_aclcnt < 0) 1981 return (EINVAL); 1982 if ((vs_ace4->vsa_aclcnt == 0) || (vs_ace4->vsa_aclentp == NULL)) 1983 return (0); 1984 1985 if (vs_ace4->vsa_aclcnt > 0) { 1986 vs_acet->vsa_aclentp = kmem_alloc(vs_ace4->vsa_aclcnt * 1987 sizeof (ace_t), KM_SLEEP); 1988 vs_acet->vsa_aclentsz = vs_ace4->vsa_aclcnt * sizeof (ace_t); 1989 } else 1990 vs_acet->vsa_aclentp = NULL; 1991 vs_acet->vsa_aclcnt = vs_ace4->vsa_aclcnt; 1992 vs_acet->vsa_mask = VSA_ACE | VSA_ACECNT; 1993 1994 for (i = 0; i < vs_ace4->vsa_aclcnt; i++) { 1995 error = ace4_to_acet((nfsace4 *)(vs_ace4->vsa_aclentp) + i, 1996 (ace_t *)(vs_acet->vsa_aclentp) + i, owner, group, 1997 isserver); 1998 if (error != 0) 1999 goto out; 2000 } 2001 2002 out: 2003 if (error != 0) 2004 vs_acet_destroy(vs_acet); 2005 2006 return (error); 2007 } 2008 2009 int 2010 vs_acet_to_ace4(vsecattr_t *vs_acet, vsecattr_t *vs_ace4, 2011 int isserver) 2012 { 2013 int error = 0; 2014 int i; 2015 2016 if (! (vs_acet->vsa_mask & VSA_ACE)) { 2017 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 2018 "vs_acet_to_ace4: VSA_ACE missing from mask")); 2019 return (EINVAL); 2020 } 2021 2022 if (vs_acet->vsa_aclcnt > 0) 2023 vs_ace4->vsa_aclentp = kmem_zalloc(vs_acet->vsa_aclcnt * 2024 sizeof (nfsace4), KM_SLEEP); 2025 else 2026 vs_ace4->vsa_aclentp = NULL; 2027 vs_ace4->vsa_aclcnt = vs_acet->vsa_aclcnt; 2028 vs_ace4->vsa_mask = VSA_ACE | VSA_ACECNT; 2029 2030 for (i = 0; i < vs_acet->vsa_aclcnt; i++) { 2031 error = acet_to_ace4((ace_t *)(vs_acet->vsa_aclentp) + i, 2032 (nfsace4 *)(vs_ace4->vsa_aclentp) + i, isserver); 2033 if (error != 0) 2034 goto out; 2035 } 2036 2037 out: 2038 if (error != 0) 2039 vs_ace4_destroy(vs_ace4); 2040 2041 return (error); 2042 } 2043 2044 void 2045 nfs4_acl_fill_cache(rnode4_t *rp, vsecattr_t *vsap) 2046 { 2047 size_t aclsize; 2048 vsecattr_t *rvsap; 2049 nfsace4 *tmp_ace4, *ace4; 2050 int i; 2051 2052 mutex_enter(&rp->r_statelock); 2053 if (rp->r_secattr != NULL) 2054 rvsap = rp->r_secattr; 2055 else { 2056 rvsap = kmem_zalloc(sizeof (*rvsap), KM_NOSLEEP); 2057 if (rvsap == NULL) { 2058 mutex_exit(&rp->r_statelock); 2059 return; 2060 } 2061 rp->r_secattr = rvsap; 2062 } 2063 2064 if (vsap->vsa_mask & VSA_ACE) { 2065 if (rvsap->vsa_aclentp != NULL) { 2066 if (rvsap->vsa_aclcnt != vsap->vsa_aclcnt) { 2067 vs_ace4_destroy(rvsap); 2068 rvsap->vsa_aclentp = NULL; 2069 } else { 2070 /* 2071 * The counts are equal so we don't have to 2072 * destroy the acl entries because we'd only 2073 * have to re-allocate them, but we do have to 2074 * destroy all of the who utf8strings. 2075 * The acl that we are now filling the cache 2076 * with may have the same amount of entries as 2077 * what is currently cached, but those entries 2078 * may not be the same. 2079 */ 2080 ace4 = (nfsace4 *) rvsap->vsa_aclentp; 2081 for (i = 0; i < rvsap->vsa_aclcnt; i++) { 2082 if (ace4[i].who.utf8string_val != NULL) 2083 kmem_free( 2084 ace4[i].who.utf8string_val, 2085 ace4[i].who.utf8string_len); 2086 } 2087 } 2088 } 2089 if (vsap->vsa_aclcnt > 0) { 2090 aclsize = vsap->vsa_aclcnt * sizeof (nfsace4); 2091 2092 if (rvsap->vsa_aclentp == NULL) { 2093 rvsap->vsa_aclentp = kmem_alloc(aclsize, 2094 KM_SLEEP); 2095 } 2096 2097 bcopy(vsap->vsa_aclentp, rvsap->vsa_aclentp, aclsize); 2098 2099 tmp_ace4 = (nfsace4 *) vsap->vsa_aclentp; 2100 ace4 = (nfsace4 *) rvsap->vsa_aclentp; 2101 for (i = 0; i < vsap->vsa_aclcnt; i++) { 2102 (void) utf8_copy(&tmp_ace4[i].who, 2103 &ace4[i].who); 2104 } 2105 } 2106 rvsap->vsa_aclcnt = vsap->vsa_aclcnt; 2107 rvsap->vsa_mask |= VSA_ACE | VSA_ACECNT; 2108 } 2109 if (vsap->vsa_mask & VSA_ACECNT) { 2110 if (rvsap->vsa_aclentp != NULL) { 2111 /* 2112 * If the caller requested to only cache the 2113 * count, get rid of the acl whether or not the 2114 * counts are equal because it may be invalid. 2115 */ 2116 if (vsap->vsa_mask == VSA_ACECNT || 2117 rvsap->vsa_aclcnt != vsap->vsa_aclcnt) { 2118 vs_ace4_destroy(rvsap); 2119 rvsap->vsa_aclentp = NULL; 2120 rvsap->vsa_mask &= ~VSA_ACE; 2121 } 2122 } 2123 rvsap->vsa_aclcnt = vsap->vsa_aclcnt; 2124 rvsap->vsa_mask |= VSA_ACECNT; 2125 } 2126 mutex_exit(&rp->r_statelock); 2127 } 2128 2129 /* 2130 * This should ONLY be called on the ACL cache (rnode4_t.r_secattr). The cache 2131 * is stored as a nfsv4 acl meaning the vsecattr_t.vsa_aclentp is a list of 2132 * nfsace4 entries and vsecattr_t.vsa_dfaclentp is NULL or not populated. 2133 */ 2134 void 2135 nfs4_acl_free_cache(vsecattr_t *vsap) 2136 { 2137 if (vsap == NULL) 2138 return; 2139 2140 if (vsap->vsa_aclentp != NULL) 2141 vs_ace4_destroy(vsap); 2142 2143 kmem_free(vsap, sizeof (*vsap)); 2144 vsap = NULL; 2145 } 2146 2147 static int 2148 validate_idmapping(utf8string *orig_who, uid_t *mapped_id, int isuser, 2149 int isserver) 2150 { 2151 if (u8s_mapped_to_nobody(orig_who, *mapped_id, isuser)) { 2152 if (isserver) { 2153 char *who = NULL; 2154 uint_t len = 0; 2155 /* SERVER */ 2156 /* 2157 * This code path gets executed on the server 2158 * in the case that we are setting an ACL. 2159 * 2160 * We silently got our who value (who@domain) 2161 * mapped to "nobody" (possibly because the 2162 * nfsmapid daemon was unresponsive). 2163 * We NEVER want to silently map the user or 2164 * group to "nobody" as this could end up 2165 * wrongly giving access to user or group 2166 * "nobody" rather than the entity it was 2167 * meant for. 2168 */ 2169 who = utf8_to_str(orig_who, &len, NULL); 2170 DTRACE_PROBE1(nfs4__acl__nobody, char *, who); 2171 if (who != NULL) 2172 kmem_free(who, len); 2173 return (NFS4ERR_BADOWNER); 2174 } else { 2175 char *who = NULL; 2176 uint_t len = 0; 2177 /* CLIENT */ 2178 /* 2179 * This code path gets executed on the client 2180 * when we are getting an ACL. 2181 * 2182 * We do not want to silently map user or group to 2183 * "nobody" because of the semantics that an ACL 2184 * modification interface (i.e. - setfacl -m, chmod A+) 2185 * may use to modify an ACL (i.e. - get the ACL 2186 * then use it as a basis for setting the 2187 * modified ACL). Therefore, change the mapping. 2188 */ 2189 who = utf8_to_str(orig_who, &len, NULL); 2190 DTRACE_PROBE1(nfs4__acl__nobody, char *, who); 2191 if (who != NULL) 2192 kmem_free(who, len); 2193 2194 /* 2195 * Re-mapped from UID_NOBODY/GID_NOBODY 2196 * to UID_UNKNOWN/GID_UNKNOWN and return. 2197 */ 2198 remap_id(mapped_id, isuser); 2199 return (0); 2200 } 2201 } 2202 return (0); 2203 } 2204 /* 2205 * Returns 1 if the who, utf8string was mapped to UID_NOBODY or GID_NOBODY. 2206 * Returns 0 if the who, utf8string was mapped correctly. 2207 */ 2208 static int 2209 u8s_mapped_to_nobody(utf8string *orig_who, uid_t mapped_id, int isuser) 2210 { 2211 if (orig_who->utf8string_len == 6 && 2212 bcmp("nobody", orig_who->utf8string_val, 6) == 0) 2213 return (0); 2214 2215 if (isuser) 2216 return (mapped_id == UID_NOBODY); 2217 2218 return (mapped_id == GID_NOBODY); 2219 } 2220 2221 /* 2222 * This function is used in the case that the utf8string passed over the wire 2223 * was mapped to UID_NOBODY or GID_NOBODY and we will remap the id to 2224 * to the appropriate mapping. That is UID_UNKNOWN or GID_UNKNOWN. 2225 */ 2226 static void 2227 remap_id(uid_t *id, int isuser) 2228 { 2229 if (isuser) 2230 *id = UID_UNKNOWN; 2231 2232 *id = GID_UNKNOWN; 2233 } 2234