1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2023 RackTop Systems, Inc. 26 */ 27 28 /* 29 * SMB server interfaces for ACL conversion (smb_acl_...) 30 * 31 * There are two variants of this interface: 32 * This is the library version. See also: 33 * $SRC/uts/common/fs/smbsrv/smb_acl.c 34 */ 35 36 #include <stddef.h> 37 #include <strings.h> 38 #include <syslog.h> 39 #include <assert.h> 40 41 #include <smbsrv/smb.h> 42 #include <smbsrv/smb_sid.h> 43 #include <smbsrv/smb_idmap.h> 44 45 #define ACE_ALL_TYPES 0x001F 46 47 /* 48 * ACE groups within a DACL 49 * 50 * This is from lower to higher ACE order priority 51 */ 52 #define SMB_AG_START 0 53 #define SMB_AG_ALW_INHRT 0 54 #define SMB_AG_DNY_INHRT 1 55 #define SMB_AG_ALW_DRCT 2 56 #define SMB_AG_DNY_DRCT 3 57 #define SMB_AG_NUM 4 58 59 #define DEFAULT_DACL_ACENUM 2 60 acl_t *acl_alloc(enum acl_type); 61 62 static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *); 63 static acl_t *smb_fsacl_null_empty(boolean_t); 64 static boolean_t smb_ace_isvalid(smb_ace_t *, int); 65 static uint16_t smb_ace_len(smb_ace_t *); 66 static uint32_t smb_ace_mask_g2s(uint32_t); 67 static uint16_t smb_ace_flags_tozfs(uint8_t); 68 static uint8_t smb_ace_flags_fromzfs(uint16_t); 69 static boolean_t smb_ace_wellknown_update(const char *, ace_t *); 70 71 smb_acl_t * 72 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt) 73 { 74 smb_acl_t *acl; 75 int size; 76 77 size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t)); 78 if ((acl = malloc(size)) == NULL) 79 return (NULL); 80 81 acl->sl_revision = revision; 82 acl->sl_bsize = bsize; 83 acl->sl_acecnt = acecnt; 84 acl->sl_aces = (smb_ace_t *)(acl + 1); 85 86 list_create(&acl->sl_sorted, sizeof (smb_ace_t), 87 offsetof(smb_ace_t, se_sln)); 88 return (acl); 89 } 90 91 void 92 smb_acl_free(smb_acl_t *acl) 93 { 94 int i; 95 void *ace; 96 97 if (acl == NULL) 98 return; 99 100 for (i = 0; i < acl->sl_acecnt; i++) 101 smb_sid_free(acl->sl_aces[i].se_sid); 102 103 while ((ace = list_head(&acl->sl_sorted)) != NULL) 104 list_remove(&acl->sl_sorted, ace); 105 list_destroy(&acl->sl_sorted); 106 free(acl); 107 } 108 109 /* 110 * smb_acl_len 111 * 112 * Returns the size of given ACL in bytes. Note that this 113 * is not an in-memory size, it's the ACL's size as it would 114 * appear on the wire 115 */ 116 uint16_t 117 smb_acl_len(smb_acl_t *acl) 118 { 119 return ((acl) ? acl->sl_bsize : 0); 120 } 121 122 boolean_t 123 smb_acl_isvalid(smb_acl_t *acl, int which_acl) 124 { 125 int i; 126 127 if (acl->sl_bsize < SMB_ACL_HDRSIZE) 128 return (B_FALSE); 129 130 if (acl->sl_revision != ACL_REVISION) { 131 /* 132 * we are rejecting ACLs with object-specific ACEs for now 133 */ 134 return (B_FALSE); 135 } 136 137 for (i = 0; i < acl->sl_acecnt; i++) { 138 if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl)) 139 return (B_FALSE); 140 } 141 142 return (B_TRUE); 143 } 144 145 /* 146 * smb_acl_sort 147 * 148 * Sorts the given ACL in place if it needs to be sorted. 149 * 150 * The following is an excerpt from MSDN website. 151 * 152 * Order of ACEs in a DACL 153 * 154 * For Windows NT versions 4.0 and earlier, the preferred order of ACEs 155 * is simple: In a DACL, all access-denied ACEs should precede any 156 * access-allowed ACEs. 157 * 158 * For Windows 2000 or later, the proper order of ACEs is more complicated 159 * because of the introduction of object-specific ACEs and automatic 160 * inheritance. 161 * 162 * The following describes the preferred order: 163 * 164 * To ensure that noninherited ACEs have precedence over inherited ACEs, 165 * place all noninherited ACEs in a group before any inherited ACEs. This 166 * ordering ensures, for example, that a noninherited access-denied ACE 167 * is enforced regardless of any inherited ACE that allows access. 168 * Within the groups of noninherited ACEs and inherited ACEs, order ACEs 169 * according to ACE type, as the following shows: 170 * . Access-denied ACEs that apply to the object itself 171 * . Access-denied ACEs that apply to a subobject of the 172 * object, such as a property set or property 173 * . Access-allowed ACEs that apply to the object itself 174 * . Access-allowed ACEs that apply to a subobject of the object 175 * 176 * So, here is the desired ACE order 177 * 178 * deny-direct, allow-direct, deny-inherited, allow-inherited 179 * 180 * Of course, not all ACE types are required in an ACL. 181 */ 182 void 183 smb_acl_sort(smb_acl_t *acl) 184 { 185 list_t ace_grps[SMB_AG_NUM]; 186 list_t *alist; 187 smb_ace_t *ace; 188 uint8_t ace_flags; 189 int ag, i; 190 191 assert(acl); 192 193 if (acl->sl_acecnt == 0) { 194 /* 195 * ACL with no entry is a valid ACL and it means 196 * no access for anybody. 197 */ 198 return; 199 } 200 201 for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { 202 list_create(&ace_grps[i], sizeof (smb_ace_t), 203 offsetof(smb_ace_t, se_sln)); 204 } 205 206 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) { 207 ace_flags = ace->se_hdr.se_flags; 208 209 switch (ace->se_hdr.se_type) { 210 case ACCESS_DENIED_ACE_TYPE: 211 ag = (ace_flags & INHERITED_ACE) ? 212 SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT; 213 break; 214 215 case ACCESS_ALLOWED_ACE_TYPE: 216 ag = (ace_flags & INHERITED_ACE) ? 217 SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT; 218 break; 219 220 default: 221 /* 222 * This is the lowest priority group so we put 223 * evertything unknown here. 224 */ 225 ag = SMB_AG_ALW_INHRT; 226 break; 227 } 228 229 /* Add the ACE to the selected group */ 230 list_insert_tail(&ace_grps[ag], ace); 231 } 232 233 /* 234 * start with highest priority ACE group and append 235 * the ACEs to the ACL. 236 */ 237 for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { 238 alist = &ace_grps[i]; 239 while ((ace = list_head(alist)) != NULL) { 240 list_remove(alist, ace); 241 list_insert_tail(&acl->sl_sorted, ace); 242 } 243 list_destroy(alist); 244 } 245 } 246 247 /* 248 * Error handling call-back for smb_idmap_batch_getmappings. 249 * Would be nice if this could report the path, but that's not 250 * passed down here. For now, use a dtrace fbt probe here. 251 */ 252 static void 253 smb_acl_bgm_error(smb_idmap_batch_t *sib, smb_idmap_t *sim) 254 { 255 256 if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) != 0) 257 return; 258 259 if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) { 260 /* 261 * Note: The ID and type we asked idmap to map 262 * were saved in *sim_id and sim_idtype. 263 */ 264 uid_t id = (sim->sim_id == NULL) ? (uid_t)-1 : *sim->sim_id; 265 syslog(LOG_ERR, "!smb_acl: Can't get SID for " 266 "ID=%u type=%d, status=%d", 267 id, sim->sim_idtype, sim->sim_stat); 268 } 269 270 if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) { 271 syslog(LOG_ERR, "!smb_acl: Can't get ID for " 272 "SID %s-%u, status=%d", 273 sim->sim_domsid, sim->sim_rid, sim->sim_stat); 274 } 275 } 276 277 /* 278 * smb_acl_from_zfs 279 * 280 * Converts given ZFS ACL to a Windows ACL. 281 * 282 * A pointer to allocated memory for the Windows ACL will be 283 * returned upon successful conversion. 284 */ 285 smb_acl_t * 286 smb_acl_from_zfs(acl_t *zacl) 287 { 288 ace_t *zace; 289 int numaces; 290 smb_acl_t *acl; 291 smb_ace_t *ace; 292 smb_idmap_batch_t sib; 293 smb_idmap_t *sim; 294 idmap_stat idm_stat; 295 296 idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, 297 SMB_IDMAP_ID2SID); 298 if (idm_stat != IDMAP_SUCCESS) 299 return (NULL); 300 301 /* 302 * Note that smb_fsacl_getsids sets up references in 303 * sib.sib_maps to the zace->a_who fields that live 304 * until smb_idmap_batch_destroy is called. 305 */ 306 if (smb_fsacl_getsids(&sib, zacl) != IDMAP_SUCCESS) { 307 smb_idmap_batch_destroy(&sib); 308 return (NULL); 309 } 310 311 acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt); 312 313 sim = sib.sib_maps; 314 for (numaces = 0, zace = zacl->acl_aclp; 315 numaces < zacl->acl_cnt; 316 zace++, numaces++, sim++) { 317 assert(sim->sim_sid); 318 if (sim->sim_sid == NULL) { 319 smb_acl_free(acl); 320 acl = NULL; 321 break; 322 } 323 324 ace = &acl->sl_aces[numaces]; 325 ace->se_hdr.se_type = zace->a_type; 326 ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags); 327 ace->se_mask = zace->a_access_mask; 328 ace->se_sid = smb_sid_dup(sim->sim_sid); 329 ace->se_hdr.se_bsize = smb_ace_len(ace); 330 331 acl->sl_bsize += ace->se_hdr.se_bsize; 332 } 333 334 smb_idmap_batch_destroy(&sib); 335 return (acl); 336 } 337 338 /* 339 * smb_acl_to_zfs 340 * 341 * Converts given Windows ACL to a ZFS ACL. 342 * 343 * fs_acl will contain a pointer to the created ZFS ACL. 344 * The allocated memory should be freed by calling 345 * smb_fsacl_free(). 346 * 347 * Since the output parameter, fs_acl, is allocated in this 348 * function, the caller has to make sure *fs_acl is NULL which 349 * means it's not pointing to any memory. 350 */ 351 uint32_t 352 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) 353 { 354 char sidstr[SMB_SID_STRSZ]; 355 smb_ace_t *ace; 356 acl_t *zacl; 357 ace_t *zace; 358 smb_idmap_batch_t sib; 359 smb_idmap_t *sim; 360 idmap_stat idm_stat; 361 int i; 362 363 assert(fs_acl); 364 assert(*fs_acl == NULL); 365 366 if (acl && !smb_acl_isvalid(acl, which_acl)) 367 return (NT_STATUS_INVALID_ACL); 368 369 if ((acl == NULL) || (acl->sl_acecnt == 0)) { 370 if (which_acl == SMB_DACL_SECINFO) { 371 *fs_acl = smb_fsacl_null_empty(acl == NULL); 372 } 373 374 return (NT_STATUS_SUCCESS); 375 } 376 377 idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, 378 SMB_IDMAP_SID2ID); 379 if (idm_stat != IDMAP_SUCCESS) 380 return (NT_STATUS_INTERNAL_ERROR); 381 382 zacl = smb_fsacl_alloc(acl->sl_acecnt, flags); 383 384 zace = zacl->acl_aclp; 385 ace = acl->sl_aces; 386 sim = sib.sib_maps; 387 388 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 389 zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES; 390 zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); 391 zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags); 392 zace->a_who = (uid_t)-1; 393 394 smb_sid_tostr(ace->se_sid, sidstr); 395 396 if (!smb_ace_wellknown_update(sidstr, zace)) { 397 sim->sim_id = &zace->a_who; 398 idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, 399 ace->se_sid, SMB_IDMAP_UNKNOWN); 400 401 if (idm_stat != IDMAP_SUCCESS) { 402 smb_fsacl_free(zacl); 403 smb_idmap_batch_destroy(&sib); 404 return (NT_STATUS_INTERNAL_ERROR); 405 } 406 } 407 } 408 409 idm_stat = smb_idmap_batch_getmappings(&sib, smb_acl_bgm_error); 410 if (idm_stat != IDMAP_SUCCESS) { 411 smb_fsacl_free(zacl); 412 smb_idmap_batch_destroy(&sib); 413 return (NT_STATUS_NONE_MAPPED); 414 } 415 416 /* 417 * Set the ACEs group flag based on the type of ID returned. 418 */ 419 zace = zacl->acl_aclp; 420 ace = acl->sl_aces; 421 sim = sib.sib_maps; 422 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 423 if (zace->a_who == (uid_t)-1) 424 continue; 425 426 if (sim->sim_idtype == SMB_IDMAP_GROUP) 427 zace->a_flags |= ACE_IDENTIFIER_GROUP; 428 } 429 430 smb_idmap_batch_destroy(&sib); 431 432 *fs_acl = zacl; 433 return (NT_STATUS_SUCCESS); 434 } 435 436 static boolean_t 437 smb_ace_wellknown_update(const char *sid, ace_t *zace) 438 { 439 struct { 440 char *sid; 441 uint16_t flags; 442 } map[] = { 443 { NT_WORLD_SIDSTR, ACE_EVERYONE }, 444 { NT_BUILTIN_CURRENT_OWNER_SIDSTR, ACE_OWNER }, 445 { NT_BUILTIN_CURRENT_GROUP_SIDSTR, 446 (ACE_GROUP | ACE_IDENTIFIER_GROUP) }, 447 }; 448 449 int i; 450 451 for (i = 0; i < (sizeof (map) / sizeof (map[0])); ++i) { 452 if (strcmp(sid, map[i].sid) == 0) { 453 zace->a_flags |= map[i].flags; 454 return (B_TRUE); 455 } 456 } 457 458 return (B_FALSE); 459 } 460 461 /* 462 * smb_fsacl_getsids 463 * 464 * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs. 465 * Note: sib is type SMB_IDMAP_ID2SID, zacl->acl_cnt entries. 466 */ 467 static idmap_stat 468 smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl) 469 { 470 ace_t *zace; 471 idmap_stat idm_stat; 472 smb_idmap_t *sim; 473 uid_t id; 474 int i, idtype; 475 476 sim = sib->sib_maps; 477 478 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; 479 zace++, i++, sim++) { 480 id = (uid_t)-1; /* some types do not need id */ 481 switch (zace->a_flags & ACE_TYPE_FLAGS) { 482 case ACE_OWNER: 483 idtype = SMB_IDMAP_OWNERAT; 484 break; 485 486 case (ACE_GROUP | ACE_IDENTIFIER_GROUP): 487 /* owning group */ 488 idtype = SMB_IDMAP_GROUPAT; 489 break; 490 491 case ACE_IDENTIFIER_GROUP: 492 /* regular group */ 493 idtype = SMB_IDMAP_GROUP; 494 id = zace->a_who; 495 /* for smb_acl_bgm_error ID2SID */ 496 sim->sim_id = &zace->a_who; 497 break; 498 499 case ACE_EVERYONE: 500 idtype = SMB_IDMAP_EVERYONE; 501 break; 502 503 default: 504 /* user entry */ 505 idtype = SMB_IDMAP_USER; 506 id = zace->a_who; 507 /* for smb_acl_bgm_error ID2SID */ 508 sim->sim_id = &zace->a_who; 509 break; 510 } 511 512 idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim, 513 id, idtype); 514 515 if (idm_stat != IDMAP_SUCCESS) { 516 return (idm_stat); 517 } 518 } 519 520 idm_stat = smb_idmap_batch_getmappings(sib, smb_acl_bgm_error); 521 return (idm_stat); 522 } 523 524 /* 525 * smb_fsacl_null_empty 526 * 527 * NULL DACL means everyone full-access 528 * Empty DACL means everyone full-deny 529 * 530 * ZFS ACL must have at least one entry so smb server has 531 * to simulate the aforementioned expected behavior by adding 532 * an entry in case the requested DACL is null or empty. Adding 533 * a everyone full-deny entry has proved to be problematic in 534 * tests since a deny entry takes precedence over allow entries. 535 * So, instead of adding a everyone full-deny, an owner ACE with 536 * owner implicit permissions will be set. 537 */ 538 static acl_t * 539 smb_fsacl_null_empty(boolean_t null) 540 { 541 acl_t *zacl; 542 ace_t *zace; 543 544 zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT); 545 zace = zacl->acl_aclp; 546 547 zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 548 if (null) { 549 zace->a_access_mask = ACE_ALL_PERMS; 550 zace->a_flags = ACE_EVERYONE; 551 } else { 552 zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | 553 ACE_READ_ATTRIBUTES; 554 zace->a_flags = ACE_OWNER; 555 } 556 557 return (zacl); 558 } 559 560 /* 561 * FS ACL (acl_t) Functions 562 */ 563 acl_t * 564 smb_fsacl_alloc(int acenum, int flags) 565 { 566 acl_t *acl; 567 568 acl = acl_alloc(ACE_T); 569 acl->acl_cnt = acenum; 570 if ((acl->acl_aclp = malloc(acl->acl_entry_size * acenum)) == NULL) 571 return (NULL); 572 573 acl->acl_flags = flags; 574 return (acl); 575 } 576 577 void 578 smb_fsacl_free(acl_t *acl) 579 { 580 if (acl) 581 acl_free(acl); 582 } 583 584 /* 585 * ACE Functions 586 */ 587 588 /* 589 * This is generic (ACL version 2) vs. object-specific 590 * (ACL version 4) ACE types. 591 */ 592 boolean_t 593 smb_ace_is_generic(int type) 594 { 595 switch (type) { 596 case ACE_ACCESS_ALLOWED_ACE_TYPE: 597 case ACE_ACCESS_DENIED_ACE_TYPE: 598 case ACE_SYSTEM_AUDIT_ACE_TYPE: 599 case ACE_SYSTEM_ALARM_ACE_TYPE: 600 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 601 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 602 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 603 case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE: 604 return (B_TRUE); 605 606 default: 607 break; 608 } 609 610 return (B_FALSE); 611 } 612 613 boolean_t 614 smb_ace_is_access(int type) 615 { 616 switch (type) { 617 case ACE_ACCESS_ALLOWED_ACE_TYPE: 618 case ACE_ACCESS_DENIED_ACE_TYPE: 619 case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: 620 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 621 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 623 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 624 case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 625 case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 626 return (B_TRUE); 627 628 default: 629 break; 630 } 631 632 return (B_FALSE); 633 } 634 635 boolean_t 636 smb_ace_is_audit(int type) 637 { 638 switch (type) { 639 case ACE_SYSTEM_AUDIT_ACE_TYPE: 640 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 641 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 642 case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 643 return (B_TRUE); 644 645 default: 646 break; 647 } 648 649 return (B_FALSE); 650 } 651 652 /* 653 * smb_ace_len 654 * 655 * Returns the length of the given ACE as it appears in an 656 * ACL on the wire (i.e. a flat buffer which contains the SID) 657 */ 658 static uint16_t 659 smb_ace_len(smb_ace_t *ace) 660 { 661 assert(ace); 662 assert(ace->se_sid); 663 664 if (ace == NULL) 665 return (0); 666 667 return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) + 668 smb_sid_len(ace->se_sid)); 669 } 670 671 /* 672 * smb_ace_mask_g2s 673 * 674 * Converts generic access bits in the given mask (if any) 675 * to file specific bits. Generic access masks shouldn't be 676 * stored in filesystem ACEs. 677 */ 678 static uint32_t 679 smb_ace_mask_g2s(uint32_t mask) 680 { 681 if (mask & GENERIC_ALL) { 682 mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE 683 | GENERIC_EXECUTE); 684 685 mask |= FILE_ALL_ACCESS; 686 return (mask); 687 } 688 689 if (mask & GENERIC_READ) { 690 mask &= ~GENERIC_READ; 691 mask |= FILE_GENERIC_READ; 692 } 693 694 if (mask & GENERIC_WRITE) { 695 mask &= ~GENERIC_WRITE; 696 mask |= FILE_GENERIC_WRITE; 697 } 698 699 if (mask & GENERIC_EXECUTE) { 700 mask &= ~GENERIC_EXECUTE; 701 mask |= FILE_GENERIC_EXECUTE; 702 } 703 704 return (mask); 705 } 706 707 /* 708 * smb_ace_flags_tozfs 709 * 710 * This function maps the flags which have different values 711 * in Windows and Solaris. The ones with the same value are 712 * transferred untouched. 713 */ 714 static uint16_t 715 smb_ace_flags_tozfs(uint8_t c_flags) 716 { 717 uint16_t z_flags = 0; 718 719 if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG) 720 z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 721 722 if (c_flags & FAILED_ACCESS_ACE_FLAG) 723 z_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 724 725 if (c_flags & INHERITED_ACE) 726 z_flags |= ACE_INHERITED_ACE; 727 728 z_flags |= (c_flags & ACE_INHERIT_FLAGS); 729 730 return (z_flags); 731 } 732 733 static uint8_t 734 smb_ace_flags_fromzfs(uint16_t z_flags) 735 { 736 uint8_t c_flags; 737 738 c_flags = z_flags & ACE_INHERIT_FLAGS; 739 740 if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 741 c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG; 742 743 if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG) 744 c_flags |= FAILED_ACCESS_ACE_FLAG; 745 746 if (z_flags & ACE_INHERITED_ACE) 747 c_flags |= INHERITED_ACE; 748 749 return (c_flags); 750 } 751 752 static boolean_t 753 smb_ace_isvalid(smb_ace_t *ace, int which_acl) 754 { 755 uint16_t min_len; 756 757 min_len = sizeof (smb_acehdr_t); 758 759 if (ace->se_hdr.se_bsize < min_len) 760 return (B_FALSE); 761 762 if (smb_ace_is_access(ace->se_hdr.se_type) && 763 (which_acl != SMB_DACL_SECINFO)) 764 return (B_FALSE); 765 766 if (smb_ace_is_audit(ace->se_hdr.se_type) && 767 (which_acl != SMB_SACL_SECINFO)) 768 return (B_FALSE); 769 770 if (smb_ace_is_generic(ace->se_hdr.se_type)) { 771 if (!smb_sid_isvalid(ace->se_sid)) 772 return (B_FALSE); 773 774 min_len += sizeof (ace->se_mask); 775 min_len += smb_sid_len(ace->se_sid); 776 777 if (ace->se_hdr.se_bsize < min_len) 778 return (B_FALSE); 779 } 780 781 /* 782 * object-specific ACE validation will be added later. 783 */ 784 return (B_TRUE); 785 } 786