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