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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * The following naming convention is used in function names. 31 * 32 * If an argument is one or more aclent_t, we use "aent". 33 * If an argument is one or more nfsace4, we use "ace4". 34 * If an argument is one or more ace_t, we use "acet". 35 * 36 * If there is an aggregate of the one above... 37 * If it's contained in a vsecattr_t, we prepend "vs_". 38 * If it's contained in an "array" (pointer) and length, we prepend "ln_". 39 * 40 * Thus, for example, suppose you have a function that converts an 41 * array of aclent_t structures into an array of nfsace4 structures, 42 * it's name would be "ln_aent_to_ace4". 43 */ 44 45 #include <sys/acl.h> 46 #include <nfs/nfs4_kprot.h> 47 #include <nfs/nfs4.h> 48 #include <nfs/rnode4.h> 49 #include <sys/cmn_err.h> 50 #include <sys/systm.h> 51 #include <sys/sdt.h> 52 53 #define ACE4_POSIX_SUPPORTED_BITS (ACE4_READ_DATA | \ 54 ACE4_WRITE_DATA | \ 55 ACE4_APPEND_DATA | \ 56 ACE4_EXECUTE | \ 57 ACE4_READ_ATTRIBUTES | \ 58 ACE4_READ_ACL | \ 59 ACE4_WRITE_ACL) 60 61 static int ace4vals_compare(const void *, const void *); 62 static int nfs4_ace4_list_construct(void *, void *, int); 63 static void nfs4_ace4_list_destroy(void *, void *); 64 static void ace4_list_free(ace4_list_t *); 65 static void ace4vals_init(ace4vals_t *, utf8string *); 66 static void ace4_list_init(ace4_list_t *, int); 67 static int ln_aent_preprocess(aclent_t *, int, 68 int *, o_mode_t *, int *, int *, int *); 69 static void ace4_make_deny(nfsace4 *, nfsace4 *, int, int, int); 70 static acemask4 mode_to_ace4_access(o_mode_t, int, int, int, int); 71 static int ln_aent_to_ace4(aclent_t *, int, nfsace4 **, int *, int, int); 72 static int ace4_mask_to_mode(acemask4, o_mode_t *, int); 73 static int ace4_allow_to_mode(acemask4, o_mode_t *, int); 74 static ace4vals_t *ace4vals_find(nfsace4 *, avl_tree_t *, int *); 75 static int ace4_to_aent_legal(nfsace4 *, int); 76 static int ace4vals_to_aent(ace4vals_t *, aclent_t *, ace4_list_t *, 77 uid_t, gid_t, int, int, int); 78 static int ace4_list_to_aent(ace4_list_t *, aclent_t **, int *, uid_t, gid_t, 79 int, int, int); 80 static int ln_ace4_to_aent(nfsace4 *ace4, int n, uid_t, gid_t, 81 aclent_t **, int *, aclent_t **, int *, int, int, int); 82 static int ace4_cmp(nfsace4 *, nfsace4 *); 83 static int acet_to_ace4(ace_t *, nfsace4 *, int); 84 static int ace4_to_acet(nfsace4 *, ace_t *, uid_t, gid_t, int, int); 85 static int validate_idmapping(utf8string *, uid_t, int, int, int); 86 static int u8s_mapped_to_nobody(utf8string *, uid_t, int); 87 static void ace4_mask_to_acet_mask(acemask4, uint32_t *); 88 static void acet_mask_to_ace4_mask(uint32_t, acemask4 *); 89 static void ace4_flags_to_acet_flags(aceflag4, uint16_t *); 90 static void acet_flags_to_ace4_flags(uint16_t, aceflag4 *); 91 92 /* 93 * The following two functions check and set ACE4_SYNCRONIZE, ACE4_WRITE_OWNER, 94 * ACE4_DELETE and ACE4_WRITE_ATTRIBUTES. 95 */ 96 static int access_mask_check(nfsace4 *, int, int, int); 97 static acemask4 access_mask_set(int, int, int, int, int); 98 99 static int nfs4_acl_debug = 0; 100 101 #define ACL_SYNCHRONIZE_SET_DENY 0x0000001 102 #define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002 103 #define ACL_SYNCHRONIZE_ERR_DENY 0x0000004 104 #define ACL_SYNCHRONIZE_ERR_ALLOW 0x0000008 105 106 #define ACL_WRITE_OWNER_SET_DENY 0x0000010 107 #define ACL_WRITE_OWNER_SET_ALLOW 0x0000020 108 #define ACL_WRITE_OWNER_ERR_DENY 0x0000040 109 #define ACL_WRITE_OWNER_ERR_ALLOW 0x0000080 110 111 #define ACL_DELETE_SET_DENY 0x0000100 112 #define ACL_DELETE_SET_ALLOW 0x0000200 113 #define ACL_DELETE_ERR_DENY 0x0000400 114 #define ACL_DELETE_ERR_ALLOW 0x0000800 115 116 #define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000 117 #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000 118 #define ACL_WRITE_ATTRS_OWNER_ERR_DENY 0x0004000 119 #define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW 0x0008000 120 121 #define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000 122 #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000 123 #define ACL_WRITE_ATTRS_WRITER_ERR_DENY 0x0040000 124 #define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW 0x0080000 125 126 #define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000 127 #define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000 128 #define ACL_WRITE_NAMED_WRITER_ERR_DENY 0x0400000 129 #define ACL_WRITE_NAMED_WRITER_ERR_ALLOW 0x0800000 130 131 #define ACL_READ_NAMED_READER_SET_DENY 0x1000000 132 #define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000 133 #define ACL_READ_NAMED_READER_ERR_DENY 0x4000000 134 #define ACL_READ_NAMED_READER_ERR_ALLOW 0x8000000 135 136 /* 137 * What we will send the server upon setting an ACL on our client 138 */ 139 static int nfs4_acl_client_produce = 140 (ACL_SYNCHRONIZE_SET_ALLOW | 141 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 142 ACL_WRITE_ATTRS_WRITER_SET_DENY); 143 144 /* 145 * What we will accept upon getting an ACL on our client 146 */ 147 static int nfs4_acl_client_consume = 148 (ACL_WRITE_OWNER_ERR_DENY | 149 ACL_WRITE_OWNER_ERR_ALLOW | 150 ACL_WRITE_ATTRS_OWNER_ERR_DENY | 151 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 152 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW | 153 ACL_WRITE_ATTRS_WRITER_SET_DENY); 154 155 /* 156 * What we will produce as an ACL on a newly created file 157 */ 158 static int nfs4_acl_server_produce = 159 (ACL_SYNCHRONIZE_SET_ALLOW | 160 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 161 ACL_WRITE_ATTRS_WRITER_SET_DENY); 162 163 /* 164 * What we will accept upon setting an ACL on our server 165 */ 166 static int nfs4_acl_server_consume = 167 (ACL_SYNCHRONIZE_ERR_DENY | 168 ACL_DELETE_ERR_DENY | 169 ACL_WRITE_OWNER_ERR_DENY | 170 ACL_WRITE_OWNER_ERR_ALLOW | 171 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 172 ACL_WRITE_ATTRS_OWNER_ERR_DENY | 173 ACL_WRITE_ATTRS_WRITER_SET_DENY | 174 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW | 175 ACL_WRITE_NAMED_WRITER_ERR_DENY | 176 ACL_READ_NAMED_READER_ERR_DENY); 177 178 static kmem_cache_t *nfs4_ace4vals_cache = NULL; 179 static kmem_cache_t *nfs4_ace4_list_cache = NULL; 180 181 static int 182 ace4vals_compare(const void *va, const void *vb) 183 { 184 const ace4vals_t *a = va, *b = vb; 185 186 if ((a->key == NULL) && (b->key == NULL)) 187 return (0); 188 else if (a->key == NULL) 189 return (-1); 190 else if (b->key == NULL) 191 return (1); 192 193 return (utf8_compare(a->key, b->key)); 194 } 195 196 /*ARGSUSED*/ 197 static int 198 nfs4_ace4_list_construct(void *voidp, void *arg, int kmem_flags) 199 { 200 ace4_list_t *a4l = voidp; 201 202 avl_create(&a4l->user, ace4vals_compare, sizeof (ace4vals_t), 203 offsetof(ace4vals_t, avl)); 204 avl_create(&a4l->group, ace4vals_compare, sizeof (ace4vals_t), 205 offsetof(ace4vals_t, avl)); 206 return (0); 207 } 208 209 /*ARGSUSED*/ 210 static void 211 nfs4_ace4_list_destroy(void *voidp, void *arg) 212 { 213 ace4_list_t *a4l = voidp; 214 215 avl_destroy(&a4l->user); 216 avl_destroy(&a4l->group); 217 } 218 219 void 220 nfs4_acl_init(void) 221 { 222 nfs4_ace4vals_cache = kmem_cache_create("nfs4_ace4vals_cache", 223 sizeof (ace4vals_t), 0, 224 NULL, NULL, 225 NULL, NULL, 226 NULL, 227 0); 228 nfs4_ace4_list_cache = kmem_cache_create("nfs4_ace4_list_cache", 229 sizeof (ace4_list_t), 0, 230 nfs4_ace4_list_construct, nfs4_ace4_list_destroy, 231 NULL, NULL, 232 NULL, 233 0); 234 } 235 236 void 237 vs_acet_destroy(vsecattr_t *vsp) 238 { 239 if (vsp->vsa_mask != (VSA_ACE | VSA_ACECNT)) 240 return; 241 242 if ((vsp->vsa_aclentp != NULL) && 243 (vsp->vsa_aclcnt > 0) && 244 (vsp->vsa_mask & VSA_ACE) && 245 (vsp->vsa_mask & VSA_ACECNT)) 246 kmem_free(vsp->vsa_aclentp, 247 vsp->vsa_aclcnt * sizeof (ace_t)); 248 249 vsp->vsa_aclentp = NULL; 250 vsp->vsa_aclcnt = 0; 251 } 252 253 void 254 vs_ace4_destroy(vsecattr_t *vsp) 255 { 256 nfsace4 *ace4; 257 int i; 258 259 if (vsp->vsa_mask != (VSA_ACE | VSA_ACECNT)) 260 return; 261 262 if ((vsp->vsa_aclentp != NULL) && 263 (vsp->vsa_aclcnt > 0) && 264 (vsp->vsa_mask & VSA_ACE) && 265 (vsp->vsa_mask & VSA_ACECNT)) { 266 for (i = 0; i < vsp->vsa_aclcnt; i++) { 267 ace4 = (nfsace4 *)vsp->vsa_aclentp + i; 268 if ((ace4->who.utf8string_len > 0) && 269 (ace4->who.utf8string_val != NULL)) 270 kmem_free(ace4->who.utf8string_val, 271 ace4->who.utf8string_len); 272 273 ace4->who.utf8string_val = NULL; 274 ace4->who.utf8string_len = 0; 275 } 276 277 kmem_free(vsp->vsa_aclentp, 278 vsp->vsa_aclcnt * sizeof (nfsace4)); 279 } 280 281 vsp->vsa_aclentp = NULL; 282 vsp->vsa_aclcnt = 0; 283 } 284 285 void 286 vs_aent_destroy(vsecattr_t *vsp) 287 { 288 if (vsp->vsa_mask & (VSA_ACE | VSA_ACECNT)) 289 return; 290 291 if ((vsp->vsa_aclentp != NULL) && 292 (vsp->vsa_aclcnt > 0) && 293 (vsp->vsa_mask & VSA_ACL) && 294 (vsp->vsa_mask & VSA_ACLCNT)) 295 kmem_free(vsp->vsa_aclentp, 296 vsp->vsa_aclcnt * sizeof (aclent_t)); 297 if ((vsp->vsa_dfaclentp != NULL) && 298 (vsp->vsa_dfaclcnt > 0) && 299 (vsp->vsa_mask & VSA_DFACL) && 300 (vsp->vsa_mask & VSA_DFACLCNT)) 301 kmem_free(vsp->vsa_dfaclentp, 302 vsp->vsa_dfaclcnt * sizeof (aclent_t)); 303 304 vsp->vsa_aclentp = NULL; 305 vsp->vsa_aclcnt = 0; 306 307 vsp->vsa_dfaclentp = NULL; 308 vsp->vsa_aclcnt = 0; 309 } 310 311 /* 312 * free all data associated with an ace4_list 313 */ 314 static void 315 ace4_list_free(ace4_list_t *a4l) 316 { 317 ace4vals_t *node; 318 void *cookie; 319 320 if (a4l == NULL) 321 return; 322 323 /* free all nodes, but don't destroy the trees themselves */ 324 cookie = NULL; 325 while ((node = avl_destroy_nodes(&a4l->user, &cookie)) != NULL) 326 kmem_cache_free(nfs4_ace4vals_cache, node); 327 cookie = NULL; 328 while ((node = avl_destroy_nodes(&a4l->group, &cookie)) != NULL) 329 kmem_cache_free(nfs4_ace4vals_cache, node); 330 331 /* free the container itself */ 332 kmem_cache_free(nfs4_ace4_list_cache, a4l); 333 } 334 335 static void 336 ace4vals_init(ace4vals_t *vals, utf8string *key) 337 { 338 bzero(vals, sizeof (*vals)); 339 vals->allowed = ACE4_MASK_UNDEFINED; 340 vals->denied = ACE4_MASK_UNDEFINED; 341 vals->mask = ACE4_MASK_UNDEFINED; 342 vals->key = key; 343 } 344 345 static void 346 ace4_list_init(ace4_list_t *a4l, int dfacl_flag) 347 { 348 ace4vals_init(&a4l->user_obj, NULL); 349 ace4vals_init(&a4l->group_obj, NULL); 350 ace4vals_init(&a4l->other_obj, NULL); 351 a4l->numusers = 0; 352 a4l->numgroups = 0; 353 a4l->acl_mask = 0; 354 a4l->hasmask = 0; 355 a4l->state = ace4_unused; 356 a4l->seen = 0; 357 a4l->dfacl_flag = dfacl_flag; 358 } 359 360 /* 361 * Make an initial pass over an array of aclent_t's. Gather 362 * information such as an ACL_MASK (if any), number of users, 363 * number of groups, and whether the array needs to be sorted. 364 */ 365 static int 366 ln_aent_preprocess(aclent_t *aclent, int n, 367 int *hasmask, o_mode_t *mask, 368 int *numuser, int *numgroup, int *needsort) 369 { 370 int error = 0; 371 int i; 372 int curtype = 0; 373 374 *hasmask = 0; 375 *mask = 07; 376 *needsort = 0; 377 *numuser = 0; 378 *numgroup = 0; 379 380 for (i = 0; i < n; i++) { 381 if (aclent[i].a_type < curtype) 382 *needsort = 1; 383 else if (aclent[i].a_type > curtype) 384 curtype = aclent[i].a_type; 385 if (aclent[i].a_type & USER) 386 (*numuser)++; 387 if (aclent[i].a_type & (GROUP | GROUP_OBJ)) 388 (*numgroup)++; 389 if (aclent[i].a_type & CLASS_OBJ) { 390 if (*hasmask) { 391 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 392 "ln_aent_preprocess: multiple CLASS_OBJs " 393 "(masks) found")); 394 error = EINVAL; 395 goto out; 396 } else { 397 *hasmask = 1; 398 *mask = aclent[i].a_perm; 399 } 400 } 401 } 402 403 if ((! *hasmask) && (*numuser + *numgroup > 1)) { 404 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 405 "ln_aent_preprocess: no CLASS_OBJs " 406 "(masks) found")); 407 error = EINVAL; 408 goto out; 409 } 410 411 out: 412 return (error); 413 } 414 415 static acemask4 416 access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow, 417 int isserver) 418 { 419 acemask4 access_mask = 0; 420 int nfs4_acl_produce; 421 int synchronize_set = 0, write_owner_set = 0; 422 int delete_set = 0, write_attrs_set = 0; 423 int read_named_set = 0, write_named_set = 0; 424 425 if (isserver) 426 nfs4_acl_produce = nfs4_acl_server_produce; 427 else 428 nfs4_acl_produce = nfs4_acl_client_produce; 429 430 if (isallow) { 431 synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW; 432 write_owner_set = ACL_WRITE_OWNER_SET_ALLOW; 433 delete_set = ACL_DELETE_SET_ALLOW; 434 if (hasreadperm) 435 read_named_set = ACL_READ_NAMED_READER_SET_ALLOW; 436 if (haswriteperm) 437 write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 438 if (isowner) 439 write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 440 else if (haswriteperm) 441 write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 442 } else { 443 synchronize_set = ACL_SYNCHRONIZE_SET_DENY; 444 write_owner_set = ACL_WRITE_OWNER_SET_DENY; 445 delete_set = ACL_DELETE_SET_DENY; 446 if (hasreadperm) 447 read_named_set = ACL_READ_NAMED_READER_SET_DENY; 448 if (haswriteperm) 449 write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY; 450 if (isowner) 451 write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY; 452 else if (haswriteperm) 453 write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY; 454 else 455 /* 456 * If the entity is not the owner and does not 457 * have write permissions ACE4_WRITE_ATTRIBUTES will 458 * always go in the DENY ACE. 459 */ 460 access_mask |= ACE4_WRITE_ATTRIBUTES; 461 } 462 463 if (nfs4_acl_produce & synchronize_set) 464 access_mask |= ACE4_SYNCHRONIZE; 465 if (nfs4_acl_produce & write_owner_set) 466 access_mask |= ACE4_WRITE_OWNER; 467 if (nfs4_acl_produce & delete_set) 468 access_mask |= ACE4_DELETE; 469 if (nfs4_acl_produce & write_attrs_set) 470 access_mask |= ACE4_WRITE_ATTRIBUTES; 471 if (nfs4_acl_produce & read_named_set) 472 access_mask |= ACE4_READ_NAMED_ATTRS; 473 if (nfs4_acl_produce & write_named_set) 474 access_mask |= ACE4_WRITE_NAMED_ATTRS; 475 476 return (access_mask); 477 } 478 479 /* 480 * Given an nfsace4 (presumably an ALLOW entry), make a 481 * corresponding DENY entry at the address given. 482 */ 483 static void 484 ace4_make_deny(nfsace4 *allow, nfsace4 *deny, int isdir, int isowner, 485 int isserver) 486 { 487 bcopy(allow, deny, sizeof (nfsace4)); 488 489 (void) utf8_copy(&allow->who, &deny->who); 490 491 deny->type = ACE4_ACCESS_DENIED_ACE_TYPE; 492 deny->access_mask ^= ACE4_POSIX_SUPPORTED_BITS; 493 if (isdir) 494 deny->access_mask ^= ACE4_DELETE_CHILD; 495 496 deny->access_mask &= ~(ACE4_SYNCHRONIZE | ACE4_WRITE_OWNER | 497 ACE4_DELETE | ACE4_WRITE_ATTRIBUTES | ACE4_READ_NAMED_ATTRS | 498 ACE4_WRITE_NAMED_ATTRS); 499 deny->access_mask |= access_mask_set((allow->access_mask & 500 ACE4_WRITE_DATA), (allow->access_mask & ACE4_READ_DATA), isowner, 501 FALSE, isserver); 502 } 503 504 /* 505 * Given an o_mode_t, convert it into an access_mask as used 506 * by nfsace4, assuming aclent_t -> nfsace4 semantics. 507 */ 508 static acemask4 509 mode_to_ace4_access(o_mode_t mode, int isdir, int isowner, int isallow, 510 int isserver) 511 { 512 acemask4 access = 0; 513 int haswriteperm = 0; 514 int hasreadperm = 0; 515 516 if (isallow) { 517 haswriteperm = (mode & 02); 518 hasreadperm = (mode & 04); 519 } else { 520 haswriteperm = !(mode & 02); 521 hasreadperm = !(mode & 04); 522 } 523 524 /* 525 * The following call takes care of correctly setting the following 526 * mask bits in the access_mask: 527 * ACE4_SYNCHRONIZE, ACE4_WRITE_OWNER, ACE4_DELETE, 528 * ACE4_WRITE_ATTRIBUTES, ACE4_WRITE_NAMED_ATTRS, ACE4_READ_NAMED_ATTRS 529 */ 530 access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow, 531 isserver); 532 533 if (isallow) { 534 access |= ACE4_READ_ACL | ACE4_READ_ATTRIBUTES; 535 if (isowner) 536 access |= ACE4_WRITE_ACL; 537 } else { 538 if (! isowner) 539 access |= ACE4_WRITE_ACL; 540 } 541 542 /* read */ 543 if (mode & 04) { 544 access |= ACE4_READ_DATA; 545 } 546 /* write */ 547 if (mode & 02) { 548 access |= ACE4_WRITE_DATA | 549 ACE4_APPEND_DATA; 550 if (isdir) 551 access |= ACE4_DELETE_CHILD; 552 } 553 /* exec */ 554 if (mode & 01) { 555 access |= ACE4_EXECUTE; 556 } 557 558 return (access); 559 } 560 561 /* 562 * Convert an array of aclent_t into an array of nfsace4 entries, 563 * following POSIX draft -> nfsv4 conversion semantics as outlined in 564 * the IETF draft. 565 */ 566 static int 567 ln_aent_to_ace4(aclent_t *aclent, int n, nfsace4 **acepp, int *rescount, 568 int isdir, int isserver) 569 { 570 int error = 0; 571 o_mode_t mask; 572 int numuser, numgroup, needsort; 573 int resultsize = 0; 574 int i, groupi = 0, skip; 575 nfsace4 *acep, *result = NULL; 576 int hasmask; 577 578 error = ln_aent_preprocess(aclent, n, &hasmask, &mask, 579 &numuser, &numgroup, &needsort); 580 if (error != 0) 581 goto out; 582 583 /* allow + deny for each aclent */ 584 resultsize = n * 2; 585 if (hasmask) { 586 /* 587 * stick extra deny on the group_obj and on each 588 * user|group for the mask (the group_obj was added 589 * into the count for numgroup) 590 */ 591 resultsize += numuser + numgroup; 592 /* ... and don't count the mask itself */ 593 resultsize -= 2; 594 } 595 596 /* sort the source if necessary */ 597 if (needsort) 598 ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls); 599 600 result = acep = kmem_zalloc(resultsize * sizeof (nfsace4), KM_SLEEP); 601 602 for (i = 0; i < n; i++) { 603 /* 604 * don't process CLASS_OBJ (mask); mask was grabbed in 605 * ln_aent_preprocess() 606 */ 607 if (aclent[i].a_type & CLASS_OBJ) 608 continue; 609 610 /* If we need an ACL_MASK emulator, prepend it now */ 611 if ((hasmask) && 612 (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) { 613 acep->type = ACE4_ACCESS_DENIED_ACE_TYPE; 614 acep->flag = 0; 615 if (aclent[i].a_type & GROUP_OBJ) { 616 (void) str_to_utf8(ACE4_WHO_GROUP, &acep->who); 617 acep->flag |= ACE4_IDENTIFIER_GROUP; 618 error = 0; 619 } else if (aclent[i].a_type & USER) { 620 error = nfs_idmap_uid_str(aclent[i].a_id, 621 &acep->who, isserver); 622 } else { 623 error = nfs_idmap_gid_str(aclent[i].a_id, 624 &acep->who, isserver); 625 acep->flag |= ACE4_IDENTIFIER_GROUP; 626 } 627 if (error != 0) { 628 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 629 "ln_aent_to_ace4: idmap translate " 630 "failed with %d", error)); 631 goto out; 632 } 633 if (aclent[i].a_type & ACL_DEFAULT) { 634 acep->flag |= ACE4_INHERIT_ONLY_ACE | 635 ACE4_FILE_INHERIT_ACE | 636 ACE4_DIRECTORY_INHERIT_ACE; 637 } 638 /* 639 * Set the access mask for the prepended deny 640 * ace. To do this, we invert the mask (found 641 * in ln_aent_preprocess()) then convert it to an 642 * DENY ace access_mask. 643 */ 644 acep->access_mask = mode_to_ace4_access((mask ^ 07), 645 isdir, 0, 0, isserver); 646 acep += 1; 647 } 648 649 /* handle a_perm -> access_mask */ 650 acep->access_mask = mode_to_ace4_access(aclent[i].a_perm, 651 isdir, aclent[i].a_type & USER_OBJ, 1, isserver); 652 653 /* emulate a default aclent */ 654 if (aclent[i].a_type & ACL_DEFAULT) { 655 acep->flag |= ACE4_INHERIT_ONLY_ACE | 656 ACE4_FILE_INHERIT_ACE | 657 ACE4_DIRECTORY_INHERIT_ACE; 658 } 659 660 /* 661 * handle a_perm and a_id 662 * 663 * this must be done last, since it involves the 664 * corresponding deny aces, which are handled 665 * differently for each different a_type. 666 */ 667 if (aclent[i].a_type & USER_OBJ) { 668 (void) str_to_utf8(ACE4_WHO_OWNER, &acep->who); 669 ace4_make_deny(acep, acep + 1, isdir, TRUE, isserver); 670 acep += 2; 671 } else if (aclent[i].a_type & USER) { 672 error = nfs_idmap_uid_str(aclent[i].a_id, &acep->who, 673 isserver); 674 if (error != 0) { 675 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 676 "ln_aent_to_ace4: uid idmap failed " 677 "with error %d", error)); 678 goto out; 679 } 680 ace4_make_deny(acep, acep + 1, isdir, FALSE, isserver); 681 acep += 2; 682 } else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) { 683 if (aclent[i].a_type & GROUP_OBJ) { 684 (void) str_to_utf8(ACE4_WHO_GROUP, &acep->who); 685 error = 0; 686 } else { 687 error = nfs_idmap_gid_str(aclent[i].a_id, 688 &acep->who, isserver); 689 } 690 if (error != 0) { 691 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 692 "ln_aent_to_ace4: gid idmap failed " 693 "with error %d", error)); 694 goto out; 695 } 696 acep->flag |= ACE4_IDENTIFIER_GROUP; 697 /* 698 * Set the corresponding deny for the group ace. 699 * 700 * The deny aces go after all of the groups, unlike 701 * everything else, where they immediately follow 702 * the allow ace. 703 * 704 * We calculate "skip", the number of slots to 705 * skip ahead for the deny ace, here. 706 * 707 * The pattern is: 708 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3 709 * thus, skip is 710 * (2 * numgroup) - 1 - groupi 711 * (2 * numgroup) to account for MD + A 712 * - 1 to account for the fact that we're on the 713 * access (A), not the mask (MD) 714 * - groupi to account for the fact that we have 715 * passed up groupi number of MD's. 716 */ 717 skip = (2 * numgroup) - 1 - groupi; 718 ace4_make_deny(acep, acep + skip, isdir, FALSE, 719 isserver); 720 /* 721 * If we just did the last group, skip acep past 722 * all of the denies; else, just move ahead one. 723 */ 724 if (++groupi >= numgroup) 725 acep += numgroup + 1; 726 else 727 acep += 1; 728 } else if (aclent[i].a_type & OTHER_OBJ) { 729 (void) str_to_utf8(ACE4_WHO_EVERYONE, &acep->who); 730 ace4_make_deny(acep, acep + 1, isdir, FALSE, isserver); 731 acep += 2; 732 } else { 733 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 734 "ln_aent_to_ace4: aclent_t with invalid type: %x", 735 aclent[i].a_type)); 736 error = EINVAL; 737 goto out; 738 } 739 } 740 741 *acepp = result; 742 *rescount = resultsize; 743 744 out: 745 746 if (error != 0) { 747 if ((result != NULL) && (resultsize > 0)) { 748 /* free any embedded "who" strings */ 749 for (i = 0; i < resultsize; i++) { 750 acep = result + i; 751 if ((acep->who.utf8string_len > 0) && 752 (acep->who.utf8string_val != NULL)) { 753 kmem_free(acep->who.utf8string_val, 754 acep->who.utf8string_len); 755 } 756 } 757 758 /* free the nfsace4 block */ 759 kmem_free(result, resultsize * sizeof (nfsace4)); 760 } 761 } 762 763 return (error); 764 } 765 766 /* 767 * Convert a POSIX draft ACL (in a vsecattr_t) to an NFSv4 ACL, following 768 * the semantics of the IETF draft, draft-ietf-nfsv4-acl-mapping-01.txt. 769 */ 770 int 771 vs_aent_to_ace4(vsecattr_t *aclentacl, vsecattr_t *vs_ace4, 772 int isdir, int isserver) 773 { 774 int error = 0; 775 nfsace4 *acebuf = NULL; 776 int acecnt = 0; 777 nfsace4 *dfacebuf = NULL; 778 int dfacecnt = 0; 779 780 /* initialize vs_ace4 in case we can't complete our work */ 781 vs_ace4->vsa_mask = 0; 782 vs_ace4->vsa_aclentp = NULL; 783 vs_ace4->vsa_aclcnt = 0; 784 vs_ace4->vsa_dfaclentp = NULL; 785 vs_ace4->vsa_dfaclcnt = 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 /* bad whos */ 1155 if ((ace4p->who.utf8string_len == 12) && 1156 (bcmp("INTERACTIVE@", ace4p->who.utf8string_val, 12) == 0)) { 1157 error = ENOTSUP; 1158 goto out; 1159 } 1160 if ((ace4p->who.utf8string_len == 8) && 1161 (bcmp("NETWORK@", ace4p->who.utf8string_val, 8) == 0)) { 1162 error = ENOTSUP; 1163 goto out; 1164 } 1165 if ((ace4p->who.utf8string_len == 7) && 1166 (bcmp("DIALUP@", ace4p->who.utf8string_val, 7) == 0)) { 1167 error = ENOTSUP; 1168 goto out; 1169 } 1170 if ((ace4p->who.utf8string_len == 6) && 1171 (bcmp("BATCH@", ace4p->who.utf8string_val, 6) == 0)) { 1172 error = ENOTSUP; 1173 goto out; 1174 } 1175 if ((ace4p->who.utf8string_len == 10) && 1176 (bcmp("ANONYMOUS@", ace4p->who.utf8string_val, 10) == 0)) { 1177 error = ENOTSUP; 1178 goto out; 1179 } 1180 if ((ace4p->who.utf8string_len == 14) && 1181 (bcmp("AUTHENTICATED@", ace4p->who.utf8string_val, 14) == 0)) { 1182 error = ENOTSUP; 1183 goto out; 1184 } 1185 if ((ace4p->who.utf8string_len == 8) && 1186 (bcmp("SERVICE@", ace4p->who.utf8string_val, 8) == 0)) { 1187 error = ENOTSUP; 1188 goto out; 1189 } 1190 1191 out: 1192 return (error); 1193 } 1194 1195 static int 1196 ace4vals_to_aent(ace4vals_t *vals, aclent_t *dest, ace4_list_t *list, 1197 uid_t owner, gid_t group, int isdir, int isserver, int just_count) 1198 { 1199 int error; 1200 acemask4 flips = ACE4_POSIX_SUPPORTED_BITS; 1201 1202 if (isdir) 1203 flips |= ACE4_DELETE_CHILD; 1204 if (vals->allowed != (vals->denied ^ flips)) { 1205 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1206 "ace4vals_to_aent: mis-matched allow/deny pair: %x/%x", 1207 vals->allowed, vals->denied)); 1208 error = ENOTSUP; 1209 goto out; 1210 } 1211 if ((list->hasmask) && (list->acl_mask != vals->mask) && 1212 (vals->aent_type & (USER | GROUP | GROUP_OBJ))) { 1213 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1214 "ace4vals_to_aent: entry is missing mask")); 1215 error = ENOTSUP; 1216 goto out; 1217 } 1218 error = ace4_allow_to_mode(vals->allowed, &dest->a_perm, isdir); 1219 if (error != 0) 1220 goto out; 1221 dest->a_type = vals->aent_type; 1222 if (dest->a_type & (USER | GROUP)) { 1223 if (dest->a_type & USER) 1224 error = nfs_idmap_str_uid(vals->key, &dest->a_id, 1225 isserver); 1226 else 1227 error = nfs_idmap_str_gid(vals->key, &dest->a_id, 1228 isserver); 1229 if (error != 0) { 1230 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1231 "ace4vals_to_aent: idmap failed with %d", error)); 1232 if (isserver && (error == EPERM)) 1233 error = NFS4ERR_BADOWNER; 1234 goto out; 1235 } 1236 1237 error = validate_idmapping(vals->key, dest->a_id, 1238 (dest->a_type & USER ? 1 : 0), isserver, just_count); 1239 if (error != 0) { 1240 goto out; 1241 } 1242 } else if (dest->a_type & USER_OBJ) { 1243 dest->a_id = owner; 1244 } else if (dest->a_type & GROUP_OBJ) { 1245 dest->a_id = group; 1246 } else if (dest->a_type & OTHER_OBJ) { 1247 dest->a_id = 0; 1248 } else { 1249 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1250 "ace4vals_to_aent: dest->a_type invalid: %x " 1251 "(internal error)", dest->a_type)); 1252 error = EINVAL; 1253 goto out; 1254 } 1255 1256 out: 1257 return (error); 1258 } 1259 1260 static int 1261 ace4_list_to_aent(ace4_list_t *list, aclent_t **aclentp, int *aclcnt, 1262 uid_t owner, gid_t group, int isdir, int isserver, int just_count) 1263 { 1264 int error = 0; 1265 aclent_t *aent, *result = NULL; 1266 ace4vals_t *vals; 1267 int resultcount; 1268 1269 if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) != 1270 (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) { 1271 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1272 "ace4_list_to_aent: required aclent_t entites " 1273 "missing")); 1274 error = ENOTSUP; 1275 goto out; 1276 } 1277 if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) { 1278 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1279 "ace4_list_to_aent: CLASS_OBJ (mask) missing")); 1280 error = ENOTSUP; 1281 goto out; 1282 } 1283 1284 resultcount = 3 + list->numusers + list->numgroups; 1285 /* 1286 * This must be the same condition as below, when we add the CLASS_OBJ 1287 * (aka ACL mask) 1288 */ 1289 if ((list->hasmask) || (! list->dfacl_flag)) 1290 resultcount += 1; 1291 1292 result = aent = kmem_alloc(resultcount * sizeof (aclent_t), KM_SLEEP); 1293 1294 /* USER_OBJ */ 1295 ASSERT(list->user_obj.aent_type & USER_OBJ); 1296 error = ace4vals_to_aent(&list->user_obj, aent, list, owner, group, 1297 isdir, isserver, just_count); 1298 1299 if (error != 0) 1300 goto out; 1301 ++aent; 1302 /* USER */ 1303 vals = NULL; 1304 for (vals = avl_first(&list->user); vals != NULL; 1305 vals = AVL_NEXT(&list->user, vals)) { 1306 ASSERT(vals->aent_type & USER); 1307 error = ace4vals_to_aent(vals, aent, list, owner, group, 1308 isdir, isserver, just_count); 1309 if (error != 0) 1310 goto out; 1311 ++aent; 1312 } 1313 /* GROUP_OBJ */ 1314 ASSERT(list->group_obj.aent_type & GROUP_OBJ); 1315 error = ace4vals_to_aent(&list->group_obj, aent, list, owner, group, 1316 isdir, isserver, just_count); 1317 if (error != 0) 1318 goto out; 1319 ++aent; 1320 /* GROUP */ 1321 vals = NULL; 1322 for (vals = avl_first(&list->group); vals != NULL; 1323 vals = AVL_NEXT(&list->group, vals)) { 1324 ASSERT(vals->aent_type & GROUP); 1325 error = ace4vals_to_aent(vals, aent, list, owner, group, 1326 isdir, isserver, just_count); 1327 if (error != 0) 1328 goto out; 1329 ++aent; 1330 } 1331 /* 1332 * CLASS_OBJ (aka ACL_MASK) 1333 * 1334 * An ACL_MASK is not fabricated if the ACL is a default ACL. 1335 * This is to follow UFS's behavior. 1336 */ 1337 if ((list->hasmask) || (! list->dfacl_flag)) { 1338 if (list->hasmask) { 1339 acemask4 flips = ACE4_POSIX_SUPPORTED_BITS; 1340 if (isdir) 1341 flips |= ACE4_DELETE_CHILD; 1342 error = ace4_mask_to_mode(list->acl_mask ^ flips, 1343 &aent->a_perm, isdir); 1344 if (error != 0) 1345 goto out; 1346 } else { 1347 /* fabricate the ACL_MASK from the group permissions */ 1348 error = ace4_mask_to_mode(list->group_obj.allowed, 1349 &aent->a_perm, isdir); 1350 if (error != 0) 1351 goto out; 1352 } 1353 aent->a_id = 0; 1354 aent->a_type = CLASS_OBJ | list->dfacl_flag; 1355 ++aent; 1356 } 1357 /* OTHER_OBJ */ 1358 ASSERT(list->other_obj.aent_type & OTHER_OBJ); 1359 error = ace4vals_to_aent(&list->other_obj, aent, list, owner, group, 1360 isdir, isserver, just_count); 1361 if (error != 0) 1362 goto out; 1363 ++aent; 1364 1365 *aclentp = result; 1366 *aclcnt = resultcount; 1367 1368 out: 1369 if (error != 0) { 1370 if (result != NULL) 1371 kmem_free(result, resultcount * sizeof (aclent_t)); 1372 } 1373 1374 return (error); 1375 } 1376 1377 /* 1378 * Convert a list of nfsace4 entries to equivalent regular and default 1379 * aclent_t lists. Return error (ENOTSUP) when conversion is not possible. 1380 */ 1381 static int 1382 ln_ace4_to_aent(nfsace4 *ace4, int n, 1383 uid_t owner, gid_t group, 1384 aclent_t **aclentp, int *aclcnt, 1385 aclent_t **dfaclentp, int *dfaclcnt, 1386 int isdir, int isserver, int just_count) 1387 { 1388 int error = 0; 1389 nfsace4 *ace4p; 1390 acemask4 bits; 1391 int i; 1392 ace4_list_t *normacl = NULL, *dfacl = NULL, *acl; 1393 ace4vals_t *vals; 1394 1395 *aclentp = NULL; 1396 *aclcnt = 0; 1397 *dfaclentp = NULL; 1398 *dfaclcnt = 0; 1399 1400 /* we need at least user_obj, group_obj, and other_obj */ 1401 if (n < 6) { 1402 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1403 "ln_ace4_to_aent: too few nfsace4 entries: %d", n)); 1404 error = ENOTSUP; 1405 goto out; 1406 } 1407 if (ace4 == NULL) { 1408 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1409 "ln_ace4_to_aent: NULL source")); 1410 error = EINVAL; 1411 goto out; 1412 } 1413 1414 normacl = kmem_cache_alloc(nfs4_ace4_list_cache, KM_SLEEP); 1415 ace4_list_init(normacl, 0); 1416 dfacl = kmem_cache_alloc(nfs4_ace4_list_cache, KM_SLEEP); 1417 ace4_list_init(dfacl, ACL_DEFAULT); 1418 1419 /* process every nfsace4... */ 1420 for (i = 0; i < n; i++) { 1421 ace4p = &ace4[i]; 1422 1423 /* rule out certain cases quickly */ 1424 error = ace4_to_aent_legal(ace4p, isserver); 1425 if (error != 0) 1426 goto out; 1427 1428 /* 1429 * Turn off these bits in order to not have to worry about 1430 * them when doing the checks for compliments. 1431 */ 1432 ace4p->access_mask &= ~(ACE4_WRITE_OWNER | ACE4_DELETE | 1433 ACE4_SYNCHRONIZE | ACE4_WRITE_ATTRIBUTES | 1434 ACE4_READ_NAMED_ATTRS | ACE4_WRITE_NAMED_ATTRS); 1435 1436 /* see if this should be a regular or default acl */ 1437 bits = ace4p->flag & 1438 (ACE4_INHERIT_ONLY_ACE | 1439 ACE4_FILE_INHERIT_ACE | 1440 ACE4_DIRECTORY_INHERIT_ACE); 1441 if (bits != 0) { 1442 /* all or nothing on these inherit bits */ 1443 if (bits != (ACE4_INHERIT_ONLY_ACE | 1444 ACE4_FILE_INHERIT_ACE | 1445 ACE4_DIRECTORY_INHERIT_ACE)) { 1446 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1447 "ln_ace4_to_aent: bad inherit flags " 1448 "%x", bits)); 1449 error = ENOTSUP; 1450 goto out; 1451 } 1452 acl = dfacl; 1453 } else { 1454 acl = normacl; 1455 } 1456 1457 if ((ace4p->who.utf8string_len == 6) && 1458 (bcmp(ACE4_WHO_OWNER, 1459 ace4p->who.utf8string_val, 6) == 0)) { 1460 if (acl->state > ace4_user_obj) { 1461 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1462 "ln_ace4_to_aent: OWNER@ found " 1463 "out of order")); 1464 error = ENOTSUP; 1465 goto out; 1466 } 1467 acl->state = ace4_user_obj; 1468 acl->seen |= USER_OBJ; 1469 vals = &acl->user_obj; 1470 vals->aent_type = USER_OBJ | acl->dfacl_flag; 1471 } else if ((ace4p->who.utf8string_len == 9) && 1472 (bcmp(ACE4_WHO_EVERYONE, ace4p->who.utf8string_val, 9) 1473 == 0)) { 1474 acl->state = ace4_other_obj; 1475 acl->seen |= OTHER_OBJ; 1476 vals = &acl->other_obj; 1477 vals->aent_type = OTHER_OBJ | acl->dfacl_flag; 1478 } else if (ace4p->flag & ACE4_IDENTIFIER_GROUP) { 1479 if (acl->state > ace4_group) { 1480 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1481 "ln_ace4_to_aent: group entry found " 1482 "out of order")); 1483 error = ENOTSUP; 1484 goto out; 1485 } 1486 if ((ace4p->who.utf8string_len == 6) && 1487 (bcmp(ACE4_WHO_GROUP, 1488 ace4p->who.utf8string_val, 6) == 0)) { 1489 acl->seen |= GROUP_OBJ; 1490 vals = &acl->group_obj; 1491 vals->aent_type = GROUP_OBJ | acl->dfacl_flag; 1492 } else { 1493 acl->seen |= GROUP; 1494 vals = ace4vals_find(ace4p, &acl->group, 1495 &acl->numgroups); 1496 vals->aent_type = GROUP | acl->dfacl_flag; 1497 } 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, just_count); 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, just_count); 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, int just_count) 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, just_count); 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 error = nfs_idmap_gid_str(ace->a_who, &nfsace4->who, isserver); 1701 if (error != 0) 1702 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1703 "acet_to_ace4: idmap failed with %d", error)); 1704 } else if (ace->a_flags & ACE_OWNER) { 1705 (void) str_to_utf8(ACE4_WHO_OWNER, &nfsace4->who); 1706 } else if (ace->a_flags & ACE_EVERYONE) { 1707 (void) str_to_utf8(ACE4_WHO_EVERYONE, &nfsace4->who); 1708 } else { 1709 error = nfs_idmap_uid_str(ace->a_who, &nfsace4->who, isserver); 1710 if (error != 0) 1711 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1712 "acet_to_ace4: idmap failed with %d", error)); 1713 } 1714 1715 out: 1716 return (error); 1717 } 1718 1719 /* 1720 * Convert an nfsace4 to an ace_t, the primary difference being 1721 * integer uid/gids versus strings. 1722 */ 1723 static int 1724 ace4_to_acet(nfsace4 *nfsace4, ace_t *ace, uid_t owner, gid_t group, 1725 int isserver, int just_count) 1726 { 1727 int error = 0; 1728 1729 if (nfsace4 == NULL) { 1730 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1731 "ace4_to_acet: NULL source")); 1732 return (EINVAL); 1733 } 1734 if (ace == NULL) { 1735 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1736 "ace4_to_acet: NULL destination")); 1737 return (EINVAL); 1738 } 1739 1740 switch (nfsace4->type) { 1741 case ACE4_ACCESS_ALLOWED_ACE_TYPE: 1742 ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 1743 break; 1744 case ACE4_ACCESS_DENIED_ACE_TYPE: 1745 ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 1746 break; 1747 default: 1748 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1749 "ace4_to_acet: unsupported type: %x", nfsace4->type)); 1750 error = ENOTSUP; 1751 break; 1752 } 1753 if (error != 0) 1754 goto out; 1755 1756 if (nfsace4->flag & ~(ACE4_VALID_FLAG_BITS)) { 1757 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1758 "ace4_to_acet: invalid flags: %x", nfsace4->flag)); 1759 error = EINVAL; 1760 goto out; 1761 } 1762 1763 /* check for invalid masks */ 1764 if (nfsace4->access_mask & ~(ACE4_VALID_MASK_BITS)) { 1765 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1766 "ace4_to_acet: invalid mask: %x", nfsace4->access_mask)); 1767 error = EINVAL; 1768 goto out; 1769 } 1770 1771 ace4_mask_to_acet_mask(nfsace4->access_mask, &ace->a_access_mask); 1772 1773 if (nfsace4->flag & ~ACE_NFSV4_SUP_FLAGS) { 1774 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1775 "ace4_to_acet: unsupported flags: %x", nfsace4->flag)); 1776 error = ENOTSUP; 1777 goto out; 1778 } 1779 ace4_flags_to_acet_flags(nfsace4->flag, &ace->a_flags); 1780 1781 if (nfsace4->flag & ACE4_IDENTIFIER_GROUP) { 1782 if ((nfsace4->who.utf8string_len == 6) && 1783 (bcmp(ACE4_WHO_GROUP, 1784 nfsace4->who.utf8string_val, 6)) == 0) { 1785 ace->a_who = group; 1786 ace->a_flags |= ACE_GROUP; 1787 error = 0; 1788 } else { 1789 ace->a_flags |= ACE_IDENTIFIER_GROUP; 1790 error = nfs_idmap_str_gid(&nfsace4->who, 1791 &ace->a_who, isserver); 1792 if (error != 0) { 1793 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1794 "ace4_to_acet: idmap failed with %d", 1795 error)); 1796 if (isserver && (error == EPERM)) 1797 error = NFS4ERR_BADOWNER; 1798 goto out; 1799 } 1800 error = validate_idmapping(&nfsace4->who, 1801 ace->a_who, FALSE, isserver, just_count); 1802 if (error != 0) { 1803 goto out; 1804 } 1805 } 1806 } else { 1807 if ((nfsace4->who.utf8string_len == 6) && 1808 (bcmp(ACE4_WHO_OWNER, 1809 nfsace4->who.utf8string_val, 6) == 0)) { 1810 ace->a_flags |= ACE_OWNER; 1811 ace->a_who = owner; 1812 error = 0; 1813 } else if ((nfsace4->who.utf8string_len == 9) && 1814 (bcmp(ACE4_WHO_EVERYONE, 1815 nfsace4->who.utf8string_val, 9) == 0)) { 1816 ace->a_flags |= ACE_EVERYONE; 1817 ace->a_who = 0; 1818 } else { 1819 error = nfs_idmap_str_uid(&nfsace4->who, 1820 &ace->a_who, isserver); 1821 if (error != 0) { 1822 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 1823 "ace4_to_acet: idmap failed with %d", 1824 error)); 1825 if (isserver && (error == EPERM)) 1826 error = NFS4ERR_BADOWNER; 1827 goto out; 1828 } 1829 error = validate_idmapping(&nfsace4->who, 1830 ace->a_who, TRUE, isserver, just_count); 1831 if (error != 0) { 1832 goto out; 1833 } 1834 } 1835 } 1836 1837 out: 1838 return (error); 1839 } 1840 1841 static void 1842 ace4_mask_to_acet_mask(acemask4 ace4_mask, uint32_t *acet_mask) 1843 { 1844 *acet_mask = 0; 1845 1846 if (ace4_mask & ACE4_READ_DATA) 1847 *acet_mask |= ACE_READ_DATA; 1848 if (ace4_mask & ACE4_WRITE_DATA) 1849 *acet_mask |= ACE_WRITE_DATA; 1850 if (ace4_mask & ACE4_APPEND_DATA) 1851 *acet_mask |= ACE_APPEND_DATA; 1852 if (ace4_mask & ACE4_READ_NAMED_ATTRS) 1853 *acet_mask |= ACE_READ_NAMED_ATTRS; 1854 if (ace4_mask & ACE4_WRITE_NAMED_ATTRS) 1855 *acet_mask |= ACE_WRITE_NAMED_ATTRS; 1856 if (ace4_mask & ACE4_EXECUTE) 1857 *acet_mask |= ACE_EXECUTE; 1858 if (ace4_mask & ACE4_DELETE_CHILD) 1859 *acet_mask |= ACE_DELETE_CHILD; 1860 if (ace4_mask & ACE4_READ_ATTRIBUTES) 1861 *acet_mask |= ACE_READ_ATTRIBUTES; 1862 if (ace4_mask & ACE4_WRITE_ATTRIBUTES) 1863 *acet_mask |= ACE_WRITE_ATTRIBUTES; 1864 if (ace4_mask & ACE4_DELETE) 1865 *acet_mask |= ACE_DELETE; 1866 if (ace4_mask & ACE4_READ_ACL) 1867 *acet_mask |= ACE_READ_ACL; 1868 if (ace4_mask & ACE4_WRITE_ACL) 1869 *acet_mask |= ACE_WRITE_ACL; 1870 if (ace4_mask & ACE4_WRITE_OWNER) 1871 *acet_mask |= ACE_WRITE_OWNER; 1872 if (ace4_mask & ACE4_SYNCHRONIZE) 1873 *acet_mask |= ACE_SYNCHRONIZE; 1874 } 1875 1876 static void 1877 acet_mask_to_ace4_mask(uint32_t acet_mask, acemask4 *ace4_mask) 1878 { 1879 *ace4_mask = 0; 1880 1881 if (acet_mask & ACE_READ_DATA) 1882 *ace4_mask |= ACE4_READ_DATA; 1883 if (acet_mask & ACE_WRITE_DATA) 1884 *ace4_mask |= ACE4_WRITE_DATA; 1885 if (acet_mask & ACE_APPEND_DATA) 1886 *ace4_mask |= ACE_APPEND_DATA; 1887 if (acet_mask & ACE4_READ_NAMED_ATTRS) 1888 *ace4_mask |= ACE_READ_NAMED_ATTRS; 1889 if (acet_mask & ACE_WRITE_NAMED_ATTRS) 1890 *ace4_mask |= ACE4_WRITE_NAMED_ATTRS; 1891 if (acet_mask & ACE_EXECUTE) 1892 *ace4_mask |= ACE4_EXECUTE; 1893 if (acet_mask & ACE_DELETE_CHILD) 1894 *ace4_mask |= ACE4_DELETE_CHILD; 1895 if (acet_mask & ACE_READ_ATTRIBUTES) 1896 *ace4_mask |= ACE4_READ_ATTRIBUTES; 1897 if (acet_mask & ACE_WRITE_ATTRIBUTES) 1898 *ace4_mask |= ACE4_WRITE_ATTRIBUTES; 1899 if (acet_mask & ACE_DELETE) 1900 *ace4_mask |= ACE4_DELETE; 1901 if (acet_mask & ACE_READ_ACL) 1902 *ace4_mask |= ACE4_READ_ACL; 1903 if (acet_mask & ACE_WRITE_ACL) 1904 *ace4_mask |= ACE4_WRITE_ACL; 1905 if (acet_mask & ACE_WRITE_OWNER) 1906 *ace4_mask |= ACE4_WRITE_OWNER; 1907 if (acet_mask & ACE_SYNCHRONIZE) 1908 *ace4_mask |= ACE4_SYNCHRONIZE; 1909 } 1910 1911 static void 1912 ace4_flags_to_acet_flags(aceflag4 ace4_flags, uint16_t *acet_flags) 1913 { 1914 *acet_flags = 0; 1915 1916 if (ace4_flags & ACE4_FILE_INHERIT_ACE) 1917 *acet_flags |= ACE_FILE_INHERIT_ACE; 1918 if (ace4_flags & ACE4_DIRECTORY_INHERIT_ACE) 1919 *acet_flags |= ACE_DIRECTORY_INHERIT_ACE; 1920 if (ace4_flags & ACE4_NO_PROPAGATE_INHERIT_ACE) 1921 *acet_flags |= ACE_NO_PROPAGATE_INHERIT_ACE; 1922 if (ace4_flags & ACE4_INHERIT_ONLY_ACE) 1923 *acet_flags |= ACE_INHERIT_ONLY_ACE; 1924 if (ace4_flags & ACE4_SUCCESSFUL_ACCESS_ACE_FLAG) 1925 *acet_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 1926 if (ace4_flags & ACE4_FAILED_ACCESS_ACE_FLAG) 1927 *acet_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 1928 if (ace4_flags & ACE4_IDENTIFIER_GROUP) 1929 *acet_flags |= ACE_IDENTIFIER_GROUP; 1930 } 1931 1932 static void 1933 acet_flags_to_ace4_flags(uint16_t acet_flags, aceflag4 *ace4_flags) 1934 { 1935 *ace4_flags = 0; 1936 1937 if (acet_flags & ACE_FILE_INHERIT_ACE) 1938 *ace4_flags |= ACE4_FILE_INHERIT_ACE; 1939 if (acet_flags & ACE_DIRECTORY_INHERIT_ACE) 1940 *ace4_flags |= ACE4_DIRECTORY_INHERIT_ACE; 1941 if (acet_flags & ACE_NO_PROPAGATE_INHERIT_ACE) 1942 *ace4_flags |= ACE4_NO_PROPAGATE_INHERIT_ACE; 1943 if (acet_flags & ACE_INHERIT_ONLY_ACE) 1944 *ace4_flags |= ACE4_INHERIT_ONLY_ACE; 1945 if (acet_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 1946 *ace4_flags |= ACE4_SUCCESSFUL_ACCESS_ACE_FLAG; 1947 if (acet_flags & ACE_FAILED_ACCESS_ACE_FLAG) 1948 *ace4_flags |= ACE4_FAILED_ACCESS_ACE_FLAG; 1949 if (acet_flags & ACE_IDENTIFIER_GROUP) 1950 *ace4_flags |= ACE4_IDENTIFIER_GROUP; 1951 } 1952 1953 int 1954 vs_ace4_to_acet(vsecattr_t *vs_ace4, vsecattr_t *vs_acet, 1955 uid_t owner, gid_t group, int isserver, int just_count) 1956 { 1957 int error; 1958 int i; 1959 1960 if ((vs_ace4->vsa_mask & (VSA_ACE | VSA_ACECNT)) != 1961 (VSA_ACE | VSA_ACECNT)) 1962 return (EINVAL); 1963 if (vs_ace4->vsa_aclcnt < 0) 1964 return (EINVAL); 1965 if ((vs_ace4->vsa_aclcnt == 0) || (vs_ace4->vsa_aclentp == NULL)) 1966 return (0); 1967 1968 if (vs_ace4->vsa_aclcnt > 0) 1969 vs_acet->vsa_aclentp = kmem_alloc(vs_ace4->vsa_aclcnt * 1970 sizeof (ace_t), KM_SLEEP); 1971 else 1972 vs_acet->vsa_aclentp = NULL; 1973 vs_acet->vsa_aclcnt = vs_ace4->vsa_aclcnt; 1974 vs_acet->vsa_mask = VSA_ACE | VSA_ACECNT; 1975 1976 for (i = 0; i < vs_ace4->vsa_aclcnt; i++) { 1977 error = ace4_to_acet((nfsace4 *)(vs_ace4->vsa_aclentp) + i, 1978 (ace_t *)(vs_acet->vsa_aclentp) + i, owner, group, 1979 isserver, just_count); 1980 if (error != 0) 1981 goto out; 1982 } 1983 1984 out: 1985 if (error != 0) 1986 vs_acet_destroy(vs_acet); 1987 1988 return (error); 1989 } 1990 1991 int 1992 vs_acet_to_ace4(vsecattr_t *vs_acet, vsecattr_t *vs_ace4, 1993 int isserver) 1994 { 1995 int error = 0; 1996 int i; 1997 1998 if (! (vs_acet->vsa_mask & VSA_ACE)) { 1999 NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE, 2000 "vs_acet_to_ace4: VSA_ACE missing from mask")); 2001 return (EINVAL); 2002 } 2003 2004 if (vs_acet->vsa_aclcnt > 0) 2005 vs_ace4->vsa_aclentp = kmem_zalloc(vs_acet->vsa_aclcnt * 2006 sizeof (nfsace4), KM_SLEEP); 2007 else 2008 vs_ace4->vsa_aclentp = NULL; 2009 vs_ace4->vsa_aclcnt = vs_acet->vsa_aclcnt; 2010 vs_ace4->vsa_mask = VSA_ACE | VSA_ACECNT; 2011 2012 for (i = 0; i < vs_acet->vsa_aclcnt; i++) { 2013 error = acet_to_ace4((ace_t *)(vs_acet->vsa_aclentp) + i, 2014 (nfsace4 *)(vs_ace4->vsa_aclentp) + i, isserver); 2015 if (error != 0) 2016 goto out; 2017 } 2018 2019 out: 2020 if (error != 0) 2021 vs_ace4_destroy(vs_ace4); 2022 2023 return (error); 2024 } 2025 2026 void 2027 nfs4_acl_fill_cache(rnode4_t *rp, vsecattr_t *vsap) 2028 { 2029 size_t aclsize; 2030 vsecattr_t *rvsap; 2031 nfsace4 *tmp_ace4, *ace4; 2032 int i; 2033 2034 mutex_enter(&rp->r_statelock); 2035 if (rp->r_secattr != NULL) 2036 rvsap = rp->r_secattr; 2037 else { 2038 rvsap = kmem_zalloc(sizeof (*rvsap), KM_NOSLEEP); 2039 if (rvsap == NULL) { 2040 mutex_exit(&rp->r_statelock); 2041 return; 2042 } 2043 rp->r_secattr = rvsap; 2044 } 2045 2046 if (vsap->vsa_mask & VSA_ACE) { 2047 if (rvsap->vsa_aclentp != NULL) { 2048 if (rvsap->vsa_aclcnt != vsap->vsa_aclcnt) { 2049 vs_ace4_destroy(rvsap); 2050 rvsap->vsa_aclentp = NULL; 2051 } else { 2052 /* 2053 * The counts are equal so we don't have to 2054 * destroy the acl entries because we'd only 2055 * have to re-allocate them, but we do have to 2056 * destroy all of the who utf8strings. 2057 * The acl that we are now filling the cache 2058 * with may have the same amount of entries as 2059 * what is currently cached, but those entries 2060 * may not be the same. 2061 */ 2062 ace4 = (nfsace4 *) rvsap->vsa_aclentp; 2063 for (i = 0; i < rvsap->vsa_aclcnt; i++) { 2064 if (ace4[i].who.utf8string_val != NULL) 2065 kmem_free( 2066 ace4[i].who.utf8string_val, 2067 ace4[i].who.utf8string_len); 2068 } 2069 } 2070 } 2071 if (vsap->vsa_aclcnt > 0) { 2072 aclsize = vsap->vsa_aclcnt * sizeof (nfsace4); 2073 2074 if (rvsap->vsa_aclentp == NULL) { 2075 rvsap->vsa_aclentp = kmem_alloc(aclsize, 2076 KM_SLEEP); 2077 } 2078 2079 bcopy(vsap->vsa_aclentp, rvsap->vsa_aclentp, aclsize); 2080 2081 tmp_ace4 = (nfsace4 *) vsap->vsa_aclentp; 2082 ace4 = (nfsace4 *) rvsap->vsa_aclentp; 2083 for (i = 0; i < vsap->vsa_aclcnt; i++) { 2084 (void) utf8_copy(&tmp_ace4[i].who, 2085 &ace4[i].who); 2086 } 2087 } 2088 rvsap->vsa_aclcnt = vsap->vsa_aclcnt; 2089 rvsap->vsa_mask |= VSA_ACE | VSA_ACECNT; 2090 } 2091 if (vsap->vsa_mask & VSA_ACECNT) { 2092 if (rvsap->vsa_aclentp != NULL) { 2093 /* 2094 * If the caller requested to only cache the 2095 * count, get rid of the acl whether or not the 2096 * counts are equal because it may be invalid. 2097 */ 2098 if (vsap->vsa_mask == VSA_ACECNT || 2099 rvsap->vsa_aclcnt != vsap->vsa_aclcnt) { 2100 vs_ace4_destroy(rvsap); 2101 rvsap->vsa_aclentp = NULL; 2102 rvsap->vsa_mask &= ~VSA_ACE; 2103 } 2104 } 2105 rvsap->vsa_aclcnt = vsap->vsa_aclcnt; 2106 rvsap->vsa_mask |= VSA_ACECNT; 2107 } 2108 mutex_exit(&rp->r_statelock); 2109 } 2110 2111 /* 2112 * This should ONLY be called on the ACL cache (rnode4_t.r_secattr). The cache 2113 * is stored as a nfsv4 acl meaning the vsecattr_t.vsa_aclentp is a list of 2114 * nfsace4 entries and vsecattr_t.vsa_dfaclentp is NULL or not populated. 2115 */ 2116 void 2117 nfs4_acl_free_cache(vsecattr_t *vsap) 2118 { 2119 if (vsap == NULL) 2120 return; 2121 2122 if (vsap->vsa_aclentp != NULL) 2123 vs_ace4_destroy(vsap); 2124 2125 kmem_free(vsap, sizeof (*vsap)); 2126 vsap = NULL; 2127 } 2128 2129 static int 2130 validate_idmapping(utf8string *orig_who, uid_t mapped_id, int isuser, 2131 int isserver, int just_count) 2132 { 2133 if (u8s_mapped_to_nobody(orig_who, mapped_id, isuser)) { 2134 if (isserver) { 2135 char *who = NULL; 2136 uint_t len = 0; 2137 2138 /* 2139 * This code path gets executed on the server 2140 * in the case that we are setting an ACL. 2141 * 2142 * We silently got our who value (who@domain) 2143 * mapped to "nobody" (possibly because the 2144 * nfsmapid daemon was unresponsive). 2145 * We NEVER want to silently map the user or 2146 * group to "nobody" as this could end up 2147 * wrongly giving access to user or group 2148 * "nobody" rather than the entity it was 2149 * meant for. 2150 */ 2151 who = utf8_to_str(orig_who, &len, NULL); 2152 DTRACE_PROBE1(nfs4__acl__nobody, char *, who); 2153 if (who != NULL) 2154 kmem_free(who, len); 2155 return (NFS4ERR_BADOWNER); 2156 } else { 2157 char *who = NULL; 2158 uint_t len = 0; 2159 /* CLIENT */ 2160 /* 2161 * This code path gets executed on the client 2162 * when we are getting an ACL. 2163 * 2164 * If the caller just requested the count 2165 * don't fail the request just because we 2166 * failed mapping the other portions of the 2167 * ACL. Things such as vn_createat expect it's 2168 * call to VOP_GETSECATTR (to get the 2169 * default acl count) to succeed in order to 2170 * create a file. 2171 * 2172 * If the caller requested more than the count, 2173 * return an error as we will not want to 2174 * silently map user or group to "nobody" 2175 * because of the semantics that an ACL 2176 * modification interface (i.e. - setfacl -m) 2177 * may use to modify an ACL (i.e. - get the ACL 2178 * then use it as a basis for setting the 2179 * modified ACL). 2180 */ 2181 who = utf8_to_str(orig_who, &len, NULL); 2182 if (just_count) { 2183 DTRACE_PROBE1(nfs4__acl__nobody, char *, who); 2184 if (who != NULL) 2185 kmem_free(who, len); 2186 return (0); 2187 } else { 2188 DTRACE_PROBE1(nfs4__acl__nobody, char *, who); 2189 if (who != NULL) 2190 kmem_free(who, len); 2191 return (EACCES); 2192 } 2193 } 2194 } 2195 return (0); 2196 } 2197 /* 2198 * Returns 1 if the who, utf8string was mapped to UID_NOBODY or GID_NOBODY. 2199 * Returns 0 if the who, utf8string was mapped correctly. 2200 */ 2201 static int 2202 u8s_mapped_to_nobody(utf8string *orig_who, uid_t mapped_id, int isuser) 2203 { 2204 if (orig_who->utf8string_len == 6 && 2205 bcmp("nobody", orig_who->utf8string_val, 6) == 0) 2206 return (0); 2207 2208 if (isuser) 2209 return (mapped_id == UID_NOBODY); 2210 2211 return (mapped_id == GID_NOBODY); 2212 } 2213