1 /*- 2 * Copyright (c) 2008-2009 Edward Tomasz Napierała <trasz@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* 28 * ACL support routines specific to NFSv4 access control lists. These are 29 * utility routines for code common across file systems implementing NFSv4 30 * ACLs. 31 */ 32 33 #ifdef _KERNEL 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/mount.h> 40 #include <sys/priv.h> 41 #include <sys/vnode.h> 42 #include <sys/errno.h> 43 #include <sys/stat.h> 44 #include <sys/acl.h> 45 #else 46 #include <errno.h> 47 #include <assert.h> 48 #include <sys/acl.h> 49 #include <sys/stat.h> 50 #define KASSERT(a, b) assert(a) 51 #define CTASSERT(a) 52 #endif /* _KERNEL */ 53 54 #ifdef _KERNEL 55 56 static struct { 57 accmode_t accmode; 58 int mask; 59 } accmode2mask[] = {{VREAD, ACL_READ_DATA}, 60 {VWRITE, ACL_WRITE_DATA}, 61 {VAPPEND, ACL_APPEND_DATA}, 62 {VEXEC, ACL_EXECUTE}, 63 {VREAD_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 64 {VWRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 65 {VDELETE_CHILD, ACL_DELETE_CHILD}, 66 {VREAD_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 67 {VWRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 68 {VDELETE, ACL_DELETE}, 69 {VREAD_ACL, ACL_READ_ACL}, 70 {VWRITE_ACL, ACL_WRITE_ACL}, 71 {VWRITE_OWNER, ACL_WRITE_OWNER}, 72 {VSYNCHRONIZE, ACL_SYNCHRONIZE}, 73 {0, 0}}; 74 75 static int 76 _access_mask_from_accmode(accmode_t accmode) 77 { 78 int access_mask = 0, i; 79 80 for (i = 0; accmode2mask[i].accmode != 0; i++) { 81 if (accmode & accmode2mask[i].accmode) 82 access_mask |= accmode2mask[i].mask; 83 } 84 85 /* 86 * VAPPEND is just a modifier for VWRITE; if the caller asked 87 * for 'VAPPEND | VWRITE', we want to check for ACL_APPEND_DATA only. 88 */ 89 if (access_mask & ACL_APPEND_DATA) 90 access_mask &= ~ACL_WRITE_DATA; 91 92 return (access_mask); 93 } 94 95 /* 96 * Return 0, iff access is allowed, 1 otherwise. 97 */ 98 static int 99 _acl_denies(const struct acl *aclp, int access_mask, struct ucred *cred, 100 int file_uid, int file_gid, int *denied_explicitly) 101 { 102 int i; 103 const struct acl_entry *entry; 104 105 if (denied_explicitly != NULL) 106 *denied_explicitly = 0; 107 108 KASSERT(aclp->acl_cnt > 0, ("aclp->acl_cnt > 0")); 109 KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES, 110 ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); 111 112 for (i = 0; i < aclp->acl_cnt; i++) { 113 entry = &(aclp->acl_entry[i]); 114 115 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 116 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 117 continue; 118 if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) 119 continue; 120 switch (entry->ae_tag) { 121 case ACL_USER_OBJ: 122 if (file_uid != cred->cr_uid) 123 continue; 124 break; 125 case ACL_USER: 126 if (entry->ae_id != cred->cr_uid) 127 continue; 128 break; 129 case ACL_GROUP_OBJ: 130 if (!groupmember(file_gid, cred)) 131 continue; 132 break; 133 case ACL_GROUP: 134 if (!groupmember(entry->ae_id, cred)) 135 continue; 136 break; 137 default: 138 KASSERT(entry->ae_tag == ACL_EVERYONE, 139 ("entry->ae_tag == ACL_EVERYONE")); 140 } 141 142 if (entry->ae_entry_type == ACL_ENTRY_TYPE_DENY) { 143 if (entry->ae_perm & access_mask) { 144 if (denied_explicitly != NULL) 145 *denied_explicitly = 1; 146 return (1); 147 } 148 } 149 150 access_mask &= ~(entry->ae_perm); 151 if (access_mask == 0) 152 return (0); 153 } 154 155 return (1); 156 } 157 158 int 159 vaccess_acl_nfs4(enum vtype type, uid_t file_uid, gid_t file_gid, 160 struct acl *aclp, accmode_t accmode, struct ucred *cred, int *privused) 161 { 162 accmode_t priv_granted = 0; 163 int denied, explicitly_denied, access_mask, is_directory, 164 must_be_owner = 0; 165 166 KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND | 167 VEXPLICIT_DENY | VREAD_NAMED_ATTRS | VWRITE_NAMED_ATTRS | 168 VDELETE_CHILD | VREAD_ATTRIBUTES | VWRITE_ATTRIBUTES | VDELETE | 169 VREAD_ACL | VWRITE_ACL | VWRITE_OWNER | VSYNCHRONIZE)) == 0, 170 ("invalid bit in accmode")); 171 KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE), 172 ("VAPPEND without VWRITE")); 173 174 if (privused != NULL) 175 *privused = 0; 176 177 if (accmode & VADMIN) 178 must_be_owner = 1; 179 180 /* 181 * Ignore VSYNCHRONIZE permission. 182 */ 183 accmode &= ~VSYNCHRONIZE; 184 185 access_mask = _access_mask_from_accmode(accmode); 186 187 if (type == VDIR) 188 is_directory = 1; 189 else 190 is_directory = 0; 191 192 /* 193 * File owner is always allowed to read and write the ACL 194 * and basic attributes. This is to prevent a situation 195 * where user would change ACL in a way that prevents him 196 * from undoing the change. 197 */ 198 if (file_uid == cred->cr_uid) 199 access_mask &= ~(ACL_READ_ACL | ACL_WRITE_ACL | 200 ACL_READ_ATTRIBUTES | ACL_WRITE_ATTRIBUTES); 201 202 /* 203 * Ignore append permission for regular files; use write 204 * permission instead. 205 */ 206 if (!is_directory && (access_mask & ACL_APPEND_DATA)) { 207 access_mask &= ~ACL_APPEND_DATA; 208 access_mask |= ACL_WRITE_DATA; 209 } 210 211 denied = _acl_denies(aclp, access_mask, cred, file_uid, file_gid, 212 &explicitly_denied); 213 214 if (must_be_owner) { 215 if (file_uid != cred->cr_uid) 216 denied = EPERM; 217 } 218 219 if (!denied) 220 return (0); 221 222 /* 223 * Access failed. Iff it was not denied explicitly and 224 * VEXPLICIT_DENY flag was specified, allow access. 225 */ 226 if ((accmode & VEXPLICIT_DENY) && explicitly_denied == 0) 227 return (0); 228 229 accmode &= ~VEXPLICIT_DENY; 230 231 /* 232 * No match. Try to use privileges, if there are any. 233 */ 234 if (is_directory) { 235 if ((accmode & VEXEC) && !priv_check_cred(cred, 236 PRIV_VFS_LOOKUP, 0)) 237 priv_granted |= VEXEC; 238 } else { 239 if ((accmode & VEXEC) && !priv_check_cred(cred, 240 PRIV_VFS_EXEC, 0)) 241 priv_granted |= VEXEC; 242 } 243 244 if ((accmode & VREAD) && !priv_check_cred(cred, PRIV_VFS_READ, 0)) 245 priv_granted |= VREAD; 246 247 if ((accmode & (VWRITE | VAPPEND | VDELETE_CHILD)) && 248 !priv_check_cred(cred, PRIV_VFS_WRITE, 0)) 249 priv_granted |= (VWRITE | VAPPEND | VDELETE_CHILD); 250 251 if ((accmode & VADMIN_PERMS) && 252 !priv_check_cred(cred, PRIV_VFS_ADMIN, 0)) 253 priv_granted |= VADMIN_PERMS; 254 255 if ((accmode & VSTAT_PERMS) && 256 !priv_check_cred(cred, PRIV_VFS_STAT, 0)) 257 priv_granted |= VSTAT_PERMS; 258 259 if ((accmode & priv_granted) == accmode) { 260 if (privused != NULL) 261 *privused = 1; 262 263 return (0); 264 } 265 266 if (accmode & (VADMIN_PERMS | VDELETE_CHILD | VDELETE)) 267 denied = EPERM; 268 else 269 denied = EACCES; 270 271 return (denied); 272 } 273 #endif /* _KERNEL */ 274 275 static int 276 _acl_entry_matches(struct acl_entry *entry, acl_tag_t tag, acl_perm_t perm, 277 acl_entry_type_t entry_type) 278 { 279 if (entry->ae_tag != tag) 280 return (0); 281 282 if (entry->ae_id != ACL_UNDEFINED_ID) 283 return (0); 284 285 if (entry->ae_perm != perm) 286 return (0); 287 288 if (entry->ae_entry_type != entry_type) 289 return (0); 290 291 if (entry->ae_flags != 0) 292 return (0); 293 294 return (1); 295 } 296 297 static struct acl_entry * 298 _acl_append(struct acl *aclp, acl_tag_t tag, acl_perm_t perm, 299 acl_entry_type_t entry_type) 300 { 301 struct acl_entry *entry; 302 303 KASSERT(aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES, 304 ("aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES")); 305 306 entry = &(aclp->acl_entry[aclp->acl_cnt]); 307 aclp->acl_cnt++; 308 309 entry->ae_tag = tag; 310 entry->ae_id = ACL_UNDEFINED_ID; 311 entry->ae_perm = perm; 312 entry->ae_entry_type = entry_type; 313 entry->ae_flags = 0; 314 315 return (entry); 316 } 317 318 static struct acl_entry * 319 _acl_duplicate_entry(struct acl *aclp, int entry_index) 320 { 321 int i; 322 323 KASSERT(aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES, 324 ("aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES")); 325 326 for (i = aclp->acl_cnt; i > entry_index; i--) 327 aclp->acl_entry[i] = aclp->acl_entry[i - 1]; 328 329 aclp->acl_cnt++; 330 331 return (&(aclp->acl_entry[entry_index + 1])); 332 } 333 334 void 335 acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode, int file_owner_id) 336 { 337 int i, meets, must_append; 338 struct acl_entry *entry, *copy, *previous, 339 *a1, *a2, *a3, *a4, *a5, *a6; 340 mode_t amode; 341 const int READ = 04; 342 const int WRITE = 02; 343 const int EXEC = 01; 344 345 KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES, 346 ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); 347 348 /* 349 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt 350 * 351 * 3.16.6.3. Applying a Mode to an Existing ACL 352 */ 353 354 /* 355 * 1. For each ACE: 356 */ 357 for (i = 0; i < aclp->acl_cnt; i++) { 358 entry = &(aclp->acl_entry[i]); 359 360 /* 361 * 1.1. If the type is neither ALLOW or DENY - skip. 362 */ 363 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 364 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 365 continue; 366 367 /* 368 * 1.2. If ACL_ENTRY_INHERIT_ONLY is set - skip. 369 */ 370 if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) 371 continue; 372 373 /* 374 * 1.3. If ACL_ENTRY_FILE_INHERIT or ACL_ENTRY_DIRECTORY_INHERIT 375 * are set: 376 */ 377 if (entry->ae_flags & 378 (ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT)) { 379 /* 380 * 1.3.1. A copy of the current ACE is made, and placed 381 * in the ACL immediately following the current 382 * ACE. 383 */ 384 copy = _acl_duplicate_entry(aclp, i); 385 386 /* 387 * 1.3.2. In the first ACE, the flag 388 * ACL_ENTRY_INHERIT_ONLY is set. 389 */ 390 entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 391 392 /* 393 * 1.3.3. In the second ACE, the following flags 394 * are cleared: 395 * ACL_ENTRY_FILE_INHERIT, 396 * ACL_ENTRY_DIRECTORY_INHERIT, 397 * ACL_ENTRY_NO_PROPAGATE_INHERIT. 398 */ 399 copy->ae_flags &= ~(ACL_ENTRY_FILE_INHERIT | 400 ACL_ENTRY_DIRECTORY_INHERIT | 401 ACL_ENTRY_NO_PROPAGATE_INHERIT); 402 403 /* 404 * The algorithm continues on with the second ACE. 405 */ 406 i++; 407 entry = copy; 408 } 409 410 /* 411 * 1.4. If it's owner@, group@ or everyone@ entry, clear 412 * ACL_READ_DATA, ACL_WRITE_DATA, ACL_APPEND_DATA 413 * and ACL_EXECUTE. Continue to the next entry. 414 */ 415 if (entry->ae_tag == ACL_USER_OBJ || 416 entry->ae_tag == ACL_GROUP_OBJ || 417 entry->ae_tag == ACL_EVERYONE) { 418 entry->ae_perm &= ~(ACL_READ_DATA | ACL_WRITE_DATA | 419 ACL_APPEND_DATA | ACL_EXECUTE); 420 continue; 421 } 422 423 /* 424 * 1.5. Otherwise, if the "who" field did not match one 425 * of OWNER@, GROUP@, EVERYONE@: 426 * 427 * 1.5.1. If the type is ALLOW, check the preceding ACE. 428 * If it does not meet all of the following criteria: 429 */ 430 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW) 431 continue; 432 433 meets = 0; 434 if (i > 0) { 435 meets = 1; 436 previous = &(aclp->acl_entry[i - 1]); 437 438 /* 439 * 1.5.1.1. The type field is DENY, 440 */ 441 if (previous->ae_entry_type != ACL_ENTRY_TYPE_DENY) 442 meets = 0; 443 444 /* 445 * 1.5.1.2. The "who" field is the same as the current 446 * ACE, 447 * 448 * 1.5.1.3. The flag bit ACE4_IDENTIFIER_GROUP 449 * is the same as it is in the current ACE, 450 * and no other flag bits are set, 451 */ 452 if (previous->ae_id != entry->ae_id || 453 previous->ae_tag != entry->ae_tag) 454 meets = 0; 455 456 if (previous->ae_flags) 457 meets = 0; 458 459 /* 460 * 1.5.1.4. The mask bits are a subset of the mask bits 461 * of the current ACE, and are also subset of 462 * the following: ACL_READ_DATA, 463 * ACL_WRITE_DATA, ACL_APPEND_DATA, ACL_EXECUTE 464 */ 465 if (previous->ae_perm & ~(entry->ae_perm)) 466 meets = 0; 467 468 if (previous->ae_perm & ~(ACL_READ_DATA | 469 ACL_WRITE_DATA | ACL_APPEND_DATA | ACL_EXECUTE)) 470 meets = 0; 471 } 472 473 if (!meets) { 474 /* 475 * Then the ACE of type DENY, with a who equal 476 * to the current ACE, flag bits equal to 477 * (<current ACE flags> & <ACE_IDENTIFIER_GROUP>) 478 * and no mask bits, is prepended. 479 */ 480 previous = entry; 481 entry = _acl_duplicate_entry(aclp, i); 482 483 /* Adjust counter, as we've just added an entry. */ 484 i++; 485 486 previous->ae_tag = entry->ae_tag; 487 previous->ae_id = entry->ae_id; 488 previous->ae_flags = entry->ae_flags; 489 previous->ae_perm = 0; 490 previous->ae_entry_type = ACL_ENTRY_TYPE_DENY; 491 } 492 493 /* 494 * 1.5.2. The following modifications are made to the prepended 495 * ACE. The intent is to mask the following ACE 496 * to disallow ACL_READ_DATA, ACL_WRITE_DATA, 497 * ACL_APPEND_DATA, or ACL_EXECUTE, based upon the group 498 * permissions of the new mode. As a special case, 499 * if the ACE matches the current owner of the file, 500 * the owner bits are used, rather than the group bits. 501 * This is reflected in the algorithm below. 502 */ 503 amode = mode >> 3; 504 505 /* 506 * If ACE4_IDENTIFIER_GROUP is not set, and the "who" field 507 * in ACE matches the owner of the file, we shift amode three 508 * more bits, in order to have the owner permission bits 509 * placed in the three low order bits of amode. 510 */ 511 if (entry->ae_tag == ACL_USER && entry->ae_id == file_owner_id) 512 amode = amode >> 3; 513 514 if (entry->ae_perm & ACL_READ_DATA) { 515 if (amode & READ) 516 previous->ae_perm &= ~ACL_READ_DATA; 517 else 518 previous->ae_perm |= ACL_READ_DATA; 519 } 520 521 if (entry->ae_perm & ACL_WRITE_DATA) { 522 if (amode & WRITE) 523 previous->ae_perm &= ~ACL_WRITE_DATA; 524 else 525 previous->ae_perm |= ACL_WRITE_DATA; 526 } 527 528 if (entry->ae_perm & ACL_APPEND_DATA) { 529 if (amode & WRITE) 530 previous->ae_perm &= ~ACL_APPEND_DATA; 531 else 532 previous->ae_perm |= ACL_APPEND_DATA; 533 } 534 535 if (entry->ae_perm & ACL_EXECUTE) { 536 if (amode & EXEC) 537 previous->ae_perm &= ~ACL_EXECUTE; 538 else 539 previous->ae_perm |= ACL_EXECUTE; 540 } 541 542 /* 543 * 1.5.3. If ACE4_IDENTIFIER_GROUP is set in the flags 544 * of the ALLOW ace: 545 * 546 * XXX: This point is not there in the Falkner's draft. 547 */ 548 if (entry->ae_tag == ACL_GROUP && 549 entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) { 550 mode_t extramode, ownermode; 551 extramode = (mode >> 3) & 07; 552 ownermode = mode >> 6; 553 extramode &= ~ownermode; 554 555 if (extramode) { 556 if (extramode & READ) { 557 entry->ae_perm &= ~ACL_READ_DATA; 558 previous->ae_perm &= ~ACL_READ_DATA; 559 } 560 561 if (extramode & WRITE) { 562 entry->ae_perm &= 563 ~(ACL_WRITE_DATA | ACL_APPEND_DATA); 564 previous->ae_perm &= 565 ~(ACL_WRITE_DATA | ACL_APPEND_DATA); 566 } 567 568 if (extramode & EXEC) { 569 entry->ae_perm &= ~ACL_EXECUTE; 570 previous->ae_perm &= ~ACL_EXECUTE; 571 } 572 } 573 } 574 } 575 576 /* 577 * 2. If there at least six ACEs, the final six ACEs are examined. 578 * If they are not equal to what we want, append six ACEs. 579 */ 580 must_append = 0; 581 if (aclp->acl_cnt < 6) { 582 must_append = 1; 583 } else { 584 a6 = &(aclp->acl_entry[aclp->acl_cnt - 1]); 585 a5 = &(aclp->acl_entry[aclp->acl_cnt - 2]); 586 a4 = &(aclp->acl_entry[aclp->acl_cnt - 3]); 587 a3 = &(aclp->acl_entry[aclp->acl_cnt - 4]); 588 a2 = &(aclp->acl_entry[aclp->acl_cnt - 5]); 589 a1 = &(aclp->acl_entry[aclp->acl_cnt - 6]); 590 591 if (!_acl_entry_matches(a1, ACL_USER_OBJ, 0, 592 ACL_ENTRY_TYPE_DENY)) 593 must_append = 1; 594 if (!_acl_entry_matches(a2, ACL_USER_OBJ, ACL_WRITE_ACL | 595 ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 596 ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_ALLOW)) 597 must_append = 1; 598 if (!_acl_entry_matches(a3, ACL_GROUP_OBJ, 0, 599 ACL_ENTRY_TYPE_DENY)) 600 must_append = 1; 601 if (!_acl_entry_matches(a4, ACL_GROUP_OBJ, 0, 602 ACL_ENTRY_TYPE_ALLOW)) 603 must_append = 1; 604 if (!_acl_entry_matches(a5, ACL_EVERYONE, ACL_WRITE_ACL | 605 ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 606 ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_DENY)) 607 must_append = 1; 608 if (!_acl_entry_matches(a6, ACL_EVERYONE, ACL_READ_ACL | 609 ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | 610 ACL_SYNCHRONIZE, ACL_ENTRY_TYPE_ALLOW)) 611 must_append = 1; 612 } 613 614 if (must_append) { 615 KASSERT(aclp->acl_cnt + 6 <= ACL_MAX_ENTRIES, 616 ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); 617 618 a1 = _acl_append(aclp, ACL_USER_OBJ, 0, ACL_ENTRY_TYPE_DENY); 619 a2 = _acl_append(aclp, ACL_USER_OBJ, ACL_WRITE_ACL | 620 ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 621 ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_ALLOW); 622 a3 = _acl_append(aclp, ACL_GROUP_OBJ, 0, ACL_ENTRY_TYPE_DENY); 623 a4 = _acl_append(aclp, ACL_GROUP_OBJ, 0, ACL_ENTRY_TYPE_ALLOW); 624 a5 = _acl_append(aclp, ACL_EVERYONE, ACL_WRITE_ACL | 625 ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 626 ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_DENY); 627 a6 = _acl_append(aclp, ACL_EVERYONE, ACL_READ_ACL | 628 ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | 629 ACL_SYNCHRONIZE, ACL_ENTRY_TYPE_ALLOW); 630 631 KASSERT(a1 != NULL && a2 != NULL && a3 != NULL && a4 != NULL && 632 a5 != NULL && a6 != NULL, ("couldn't append to ACL.")); 633 } 634 635 /* 636 * 3. The final six ACEs are adjusted according to the incoming mode. 637 */ 638 if (mode & S_IRUSR) 639 a2->ae_perm |= ACL_READ_DATA; 640 else 641 a1->ae_perm |= ACL_READ_DATA; 642 if (mode & S_IWUSR) 643 a2->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 644 else 645 a1->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 646 if (mode & S_IXUSR) 647 a2->ae_perm |= ACL_EXECUTE; 648 else 649 a1->ae_perm |= ACL_EXECUTE; 650 651 if (mode & S_IRGRP) 652 a4->ae_perm |= ACL_READ_DATA; 653 else 654 a3->ae_perm |= ACL_READ_DATA; 655 if (mode & S_IWGRP) 656 a4->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 657 else 658 a3->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 659 if (mode & S_IXGRP) 660 a4->ae_perm |= ACL_EXECUTE; 661 else 662 a3->ae_perm |= ACL_EXECUTE; 663 664 if (mode & S_IROTH) 665 a6->ae_perm |= ACL_READ_DATA; 666 else 667 a5->ae_perm |= ACL_READ_DATA; 668 if (mode & S_IWOTH) 669 a6->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 670 else 671 a5->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 672 if (mode & S_IXOTH) 673 a6->ae_perm |= ACL_EXECUTE; 674 else 675 a5->ae_perm |= ACL_EXECUTE; 676 } 677 678 void 679 acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp) 680 { 681 int i; 682 mode_t old_mode = *_mode, mode = 0, seen = 0; 683 const struct acl_entry *entry; 684 685 KASSERT(aclp->acl_cnt > 0, ("aclp->acl_cnt > 0")); 686 KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES, 687 ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); 688 689 /* 690 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt 691 * 692 * 3.16.6.1. Recomputing mode upon SETATTR of ACL 693 */ 694 695 for (i = 0; i < aclp->acl_cnt; i++) { 696 entry = &(aclp->acl_entry[i]); 697 698 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 699 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 700 continue; 701 702 if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) 703 continue; 704 705 if (entry->ae_tag == ACL_USER_OBJ) { 706 if ((entry->ae_perm & ACL_READ_DATA) && 707 ((seen & S_IRUSR) == 0)) { 708 seen |= S_IRUSR; 709 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 710 mode |= S_IRUSR; 711 } 712 if ((entry->ae_perm & ACL_WRITE_DATA) && 713 ((seen & S_IWUSR) == 0)) { 714 seen |= S_IWUSR; 715 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 716 mode |= S_IWUSR; 717 } 718 if ((entry->ae_perm & ACL_EXECUTE) && 719 ((seen & S_IXUSR) == 0)) { 720 seen |= S_IXUSR; 721 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 722 mode |= S_IXUSR; 723 } 724 } else if (entry->ae_tag == ACL_GROUP_OBJ) { 725 if ((entry->ae_perm & ACL_READ_DATA) && 726 ((seen & S_IRGRP) == 0)) { 727 seen |= S_IRGRP; 728 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 729 mode |= S_IRGRP; 730 } 731 if ((entry->ae_perm & ACL_WRITE_DATA) && 732 ((seen & S_IWGRP) == 0)) { 733 seen |= S_IWGRP; 734 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 735 mode |= S_IWGRP; 736 } 737 if ((entry->ae_perm & ACL_EXECUTE) && 738 ((seen & S_IXGRP) == 0)) { 739 seen |= S_IXGRP; 740 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 741 mode |= S_IXGRP; 742 } 743 } else if (entry->ae_tag == ACL_EVERYONE) { 744 if (entry->ae_perm & ACL_READ_DATA) { 745 if ((seen & S_IRUSR) == 0) { 746 seen |= S_IRUSR; 747 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 748 mode |= S_IRUSR; 749 } 750 if ((seen & S_IRGRP) == 0) { 751 seen |= S_IRGRP; 752 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 753 mode |= S_IRGRP; 754 } 755 if ((seen & S_IROTH) == 0) { 756 seen |= S_IROTH; 757 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 758 mode |= S_IROTH; 759 } 760 } 761 if (entry->ae_perm & ACL_WRITE_DATA) { 762 if ((seen & S_IWUSR) == 0) { 763 seen |= S_IWUSR; 764 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 765 mode |= S_IWUSR; 766 } 767 if ((seen & S_IWGRP) == 0) { 768 seen |= S_IWGRP; 769 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 770 mode |= S_IWGRP; 771 } 772 if ((seen & S_IWOTH) == 0) { 773 seen |= S_IWOTH; 774 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 775 mode |= S_IWOTH; 776 } 777 } 778 if (entry->ae_perm & ACL_EXECUTE) { 779 if ((seen & S_IXUSR) == 0) { 780 seen |= S_IXUSR; 781 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 782 mode |= S_IXUSR; 783 } 784 if ((seen & S_IXGRP) == 0) { 785 seen |= S_IXGRP; 786 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 787 mode |= S_IXGRP; 788 } 789 if ((seen & S_IXOTH) == 0) { 790 seen |= S_IXOTH; 791 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 792 mode |= S_IXOTH; 793 } 794 } 795 } 796 } 797 798 *_mode = mode | (old_mode & ACL_PRESERVE_MASK); 799 } 800 801 void 802 acl_nfs4_compute_inherited_acl(const struct acl *parent_aclp, 803 struct acl *child_aclp, mode_t mode, int file_owner_id, 804 int is_directory) 805 { 806 int i, flags; 807 const struct acl_entry *parent_entry; 808 struct acl_entry *entry, *copy; 809 810 KASSERT(child_aclp->acl_cnt == 0, ("child_aclp->acl_cnt == 0")); 811 KASSERT(parent_aclp->acl_cnt > 0, ("parent_aclp->acl_cnt > 0")); 812 KASSERT(parent_aclp->acl_cnt <= ACL_MAX_ENTRIES, 813 ("parent_aclp->acl_cnt <= ACL_MAX_ENTRIES")); 814 815 /* 816 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt 817 * 818 * 3.16.6.2. Applying the mode given to CREATE or OPEN 819 * to an inherited ACL 820 */ 821 822 /* 823 * 1. Form an ACL that is the concatenation of all inheritable ACEs. 824 */ 825 for (i = 0; i < parent_aclp->acl_cnt; i++) { 826 parent_entry = &(parent_aclp->acl_entry[i]); 827 flags = parent_entry->ae_flags; 828 829 /* 830 * Entry is not inheritable at all. 831 */ 832 if ((flags & (ACL_ENTRY_DIRECTORY_INHERIT | 833 ACL_ENTRY_FILE_INHERIT)) == 0) 834 continue; 835 836 /* 837 * We're creating a file, but entry is not inheritable 838 * by files. 839 */ 840 if (!is_directory && (flags & ACL_ENTRY_FILE_INHERIT) == 0) 841 continue; 842 843 /* 844 * Entry is inheritable only by files, but has NO_PROPAGATE 845 * flag set, and we're creating a directory, so it wouldn't 846 * propagate to any file in that directory anyway. 847 */ 848 if (is_directory && 849 (flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0 && 850 (flags & ACL_ENTRY_NO_PROPAGATE_INHERIT)) 851 continue; 852 853 KASSERT(child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES, 854 ("child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES")); 855 child_aclp->acl_entry[child_aclp->acl_cnt] = *parent_entry; 856 child_aclp->acl_cnt++; 857 } 858 859 /* 860 * 2. For each entry in the new ACL, adjust its flags, possibly 861 * creating two entries in place of one. 862 */ 863 for (i = 0; i < child_aclp->acl_cnt; i++) { 864 entry = &(child_aclp->acl_entry[i]); 865 866 /* 867 * This is not in the specification, but SunOS 868 * apparently does that. 869 */ 870 if (((entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT) || 871 !is_directory) && 872 entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 873 entry->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER); 874 875 /* 876 * 2.A. If the ACL_ENTRY_NO_PROPAGATE_INHERIT is set, or if the object 877 * being created is not a directory, then clear the 878 * following flags: ACL_ENTRY_NO_PROPAGATE_INHERIT, 879 * ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT, 880 * ACL_ENTRY_INHERIT_ONLY. 881 */ 882 if (entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT || 883 !is_directory) { 884 entry->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT | 885 ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | 886 ACL_ENTRY_INHERIT_ONLY); 887 888 /* 889 * Continue on to the next ACE. 890 */ 891 continue; 892 } 893 894 /* 895 * 2.B. If the object is a directory and ACL_ENTRY_FILE_INHERIT 896 * is set, but ACL_ENTRY_NO_PROPAGATE_INHERIT is not set, ensure 897 * that ACL_ENTRY_INHERIT_ONLY is set. Continue to the 898 * next ACE. Otherwise... 899 */ 900 /* 901 * XXX: Read it again and make sure what does the "otherwise" 902 * apply to. 903 */ 904 if (is_directory && 905 (entry->ae_flags & ACL_ENTRY_FILE_INHERIT) && 906 ((entry->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0)) { 907 entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 908 continue; 909 } 910 911 /* 912 * 2.C. If the type of the ACE is neither ALLOW nor deny, 913 * then continue. 914 */ 915 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 916 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 917 continue; 918 919 /* 920 * 2.D. Copy the original ACE into a second, adjacent ACE. 921 */ 922 copy = _acl_duplicate_entry(child_aclp, i); 923 924 /* 925 * 2.E. On the first ACE, ensure that ACL_ENTRY_INHERIT_ONLY 926 * is set. 927 */ 928 entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 929 930 /* 931 * 2.F. On the second ACE, clear the following flags: 932 * ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_FILE_INHERIT, 933 * ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_INHERIT_ONLY. 934 */ 935 copy->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT | 936 ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | 937 ACL_ENTRY_INHERIT_ONLY); 938 939 /* 940 * 2.G. On the second ACE, if the type is ALLOW, 941 * an implementation MAY clear the following 942 * mask bits: ACL_WRITE_ACL, ACL_WRITE_OWNER. 943 */ 944 if (copy->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 945 copy->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER); 946 947 /* 948 * Increment the counter to skip the copied entry. 949 */ 950 i++; 951 } 952 953 /* 954 * 3. To ensure that the mode is honored, apply the algorithm describe 955 * in Section 2.16.6.3, using the mode that is to be used for file 956 * creation. 957 */ 958 acl_nfs4_sync_acl_from_mode(child_aclp, mode, file_owner_id); 959 } 960 961 #ifdef _KERNEL 962 static int 963 _acls_are_equal(const struct acl *a, const struct acl *b) 964 { 965 int i; 966 const struct acl_entry *entrya, *entryb; 967 968 if (a->acl_cnt != b->acl_cnt) 969 return (0); 970 971 for (i = 0; i < b->acl_cnt; i++) { 972 entrya = &(a->acl_entry[i]); 973 entryb = &(b->acl_entry[i]); 974 975 if (entrya->ae_tag != entryb->ae_tag || 976 entrya->ae_id != entryb->ae_id || 977 entrya->ae_perm != entryb->ae_perm || 978 entrya->ae_entry_type != entryb->ae_entry_type || 979 entrya->ae_flags != entryb->ae_flags) 980 return (0); 981 } 982 983 return (1); 984 } 985 986 /* 987 * This routine is used to determine whether to remove extended attribute 988 * that stores ACL contents. 989 */ 990 int 991 acl_nfs4_is_trivial(const struct acl *aclp, int file_owner_id) 992 { 993 int trivial; 994 mode_t tmpmode = 0; 995 struct acl *tmpaclp; 996 997 if (aclp->acl_cnt != 6) 998 return (0); 999 1000 /* 1001 * Compute the mode from the ACL, then compute new ACL from that mode. 1002 * If the ACLs are identical, then the ACL is trivial. 1003 * 1004 * XXX: I guess there is a faster way to do this. However, even 1005 * this slow implementation significantly speeds things up 1006 * for files that don't have non-trivial ACLs - it's critical 1007 * for performance to not use EA when they are not needed. 1008 */ 1009 tmpaclp = acl_alloc(M_WAITOK | M_ZERO); 1010 acl_nfs4_sync_mode_from_acl(&tmpmode, aclp); 1011 acl_nfs4_sync_acl_from_mode(tmpaclp, tmpmode, file_owner_id); 1012 trivial = _acls_are_equal(aclp, tmpaclp); 1013 acl_free(tmpaclp); 1014 1015 return (trivial); 1016 } 1017 #endif /* _KERNEL */ 1018 1019 int 1020 acl_nfs4_check(const struct acl *aclp, int is_directory) 1021 { 1022 int i; 1023 const struct acl_entry *entry; 1024 1025 /* 1026 * The spec doesn't seem to say anything about ACL validity. 1027 * It seems there is not much to do here. There is even no need 1028 * to count "owner@" or "everyone@" (ACL_USER_OBJ and ACL_EVERYONE) 1029 * entries, as there can be several of them and that's perfectly 1030 * valid. There can be none of them too. Really. 1031 */ 1032 1033 if (aclp->acl_cnt > ACL_MAX_ENTRIES || aclp->acl_cnt <= 0) 1034 return (EINVAL); 1035 1036 for (i = 0; i < aclp->acl_cnt; i++) { 1037 entry = &(aclp->acl_entry[i]); 1038 1039 switch (entry->ae_tag) { 1040 case ACL_USER_OBJ: 1041 case ACL_GROUP_OBJ: 1042 case ACL_EVERYONE: 1043 if (entry->ae_id != ACL_UNDEFINED_ID) 1044 return (EINVAL); 1045 break; 1046 1047 case ACL_USER: 1048 case ACL_GROUP: 1049 if (entry->ae_id == ACL_UNDEFINED_ID) 1050 return (EINVAL); 1051 break; 1052 1053 default: 1054 return (EINVAL); 1055 } 1056 1057 if ((entry->ae_perm | ACL_NFS4_PERM_BITS) != ACL_NFS4_PERM_BITS) 1058 return (EINVAL); 1059 1060 /* 1061 * Disallow ACL_ENTRY_TYPE_AUDIT and ACL_ENTRY_TYPE_ALARM for now. 1062 */ 1063 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 1064 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 1065 return (EINVAL); 1066 1067 if ((entry->ae_flags | ACL_FLAGS_BITS) != ACL_FLAGS_BITS) 1068 return (EINVAL); 1069 1070 /* Disallow unimplemented flags. */ 1071 if (entry->ae_flags & (ACL_ENTRY_SUCCESSFUL_ACCESS | 1072 ACL_ENTRY_FAILED_ACCESS)) 1073 return (EINVAL); 1074 1075 /* Disallow flags not allowed for ordinary files. */ 1076 if (!is_directory) { 1077 if (entry->ae_flags & (ACL_ENTRY_FILE_INHERIT | 1078 ACL_ENTRY_DIRECTORY_INHERIT | 1079 ACL_ENTRY_NO_PROPAGATE_INHERIT | ACL_ENTRY_INHERIT_ONLY)) 1080 return (EINVAL); 1081 } 1082 } 1083 1084 return (0); 1085 } 1086