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 2013 Nexenta Systems, Inc. All rights reserved. 26 * Copyright 2023 RackTop Systems, Inc. 27 */ 28 29 /* 30 * SMB server interfaces for ACL conversion (smb_acl_...) 31 * 32 * There are two variants of this interface: 33 * This is the kernel version. See also: 34 * $SRC/lib/smbsrv/libsmb/common/smb_acl.c 35 */ 36 37 #include <sys/sid.h> 38 #include <sys/acl.h> 39 #include <acl/acl_common.h> 40 #include <smbsrv/smb_sid.h> 41 #include <smbsrv/smb_fsops.h> 42 #include <smbsrv/smb_idmap.h> 43 #include <smbsrv/smb_kproto.h> 44 45 #define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE) 46 47 #define ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER) 48 #define ZACE_IS_OWNGRP(zace) \ 49 ((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP)) 50 51 #define ZACE_IS_USER(zace) \ 52 (((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace))) 53 #define ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP) 54 #define ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE) 55 56 #define ZACE_IS_PROPAGATE(zace) \ 57 ((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0) 58 59 #define ZACE_IS_CREATOR_OWNER(zace) \ 60 (ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID)) 61 62 #define ZACE_IS_CREATOR_GROUP(zace) \ 63 (ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID)) 64 65 #define ZACE_IS_CREATOR(zace) \ 66 (ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace)) 67 68 /* 69 * ACE groups within a DACL 70 * 71 * This is from lower to higher ACE order priority 72 */ 73 #define SMB_AG_START 0 74 #define SMB_AG_ALW_INHRT 0 75 #define SMB_AG_DNY_INHRT 1 76 #define SMB_AG_ALW_DRCT 2 77 #define SMB_AG_DNY_DRCT 3 78 #define SMB_AG_NUM 4 79 80 #define DEFAULT_DACL_ACENUM 2 81 /* 82 * Default ACL: 83 * owner: full access 84 * SYSTEM: full access 85 */ 86 #ifdef _KERNEL 87 static const ace_t default_dacl[DEFAULT_DACL_ACENUM] = { 88 { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, 89 { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP, 90 ACE_ACCESS_ALLOWED_ACE_TYPE } 91 }; 92 #endif /* _KERNEL */ 93 94 /* 95 * Note: 96 * 97 * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format 98 * smb_fsacl_xxx functions work with acl_t which represents the Solaris native 99 * format 100 */ 101 102 static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *); 103 static acl_t *smb_fsacl_null_empty(boolean_t); 104 #ifdef _KERNEL 105 static int smb_fsacl_inheritable(acl_t *, int); 106 static void smb_ace_inherit(ace_t *, ace_t *, int, uid_t, gid_t); 107 #endif /* _KERNEL */ 108 109 static boolean_t smb_ace_isvalid(smb_ace_t *, int); 110 static uint16_t smb_ace_len(smb_ace_t *); 111 static uint32_t smb_ace_mask_g2s(uint32_t); 112 static uint16_t smb_ace_flags_tozfs(uint8_t); 113 static uint8_t smb_ace_flags_fromzfs(uint16_t); 114 static boolean_t smb_ace_wellknown_update(const char *, ace_t *); 115 116 smb_acl_t * 117 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt) 118 { 119 smb_acl_t *acl; 120 int size; 121 122 size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t)); 123 acl = kmem_zalloc(size, KM_SLEEP); 124 acl->sl_revision = revision; 125 acl->sl_bsize = bsize; 126 acl->sl_acecnt = acecnt; 127 acl->sl_aces = (smb_ace_t *)(acl + 1); 128 129 list_create(&acl->sl_sorted, sizeof (smb_ace_t), 130 offsetof(smb_ace_t, se_sln)); 131 return (acl); 132 } 133 134 void 135 smb_acl_free(smb_acl_t *acl) 136 { 137 int i, size; 138 void *ace; 139 140 if (acl == NULL) 141 return; 142 143 for (i = 0; i < acl->sl_acecnt; i++) 144 smb_sid_free(acl->sl_aces[i].se_sid); 145 146 while ((ace = list_head(&acl->sl_sorted)) != NULL) 147 list_remove(&acl->sl_sorted, ace); 148 list_destroy(&acl->sl_sorted); 149 150 size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t)); 151 kmem_free(acl, size); 152 } 153 154 /* 155 * smb_acl_len 156 * 157 * Returns the size of given ACL in bytes. Note that this 158 * is not an in-memory size, it's the ACL's size as it would 159 * appear on the wire 160 */ 161 uint16_t 162 smb_acl_len(smb_acl_t *acl) 163 { 164 return ((acl) ? acl->sl_bsize : 0); 165 } 166 167 boolean_t 168 smb_acl_isvalid(smb_acl_t *acl, int which_acl) 169 { 170 int i; 171 172 if (acl->sl_bsize < SMB_ACL_HDRSIZE) 173 return (B_FALSE); 174 175 if (acl->sl_revision != ACL_REVISION) { 176 /* 177 * we are rejecting ACLs with object-specific ACEs for now 178 */ 179 return (B_FALSE); 180 } 181 182 for (i = 0; i < acl->sl_acecnt; i++) { 183 if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl)) 184 return (B_FALSE); 185 } 186 187 return (B_TRUE); 188 } 189 190 /* 191 * smb_acl_sort 192 * 193 * Sorts the given ACL in place if it needs to be sorted. 194 * 195 * The following is an excerpt from MSDN website. 196 * 197 * Order of ACEs in a DACL 198 * 199 * For Windows NT versions 4.0 and earlier, the preferred order of ACEs 200 * is simple: In a DACL, all access-denied ACEs should precede any 201 * access-allowed ACEs. 202 * 203 * For Windows 2000 or later, the proper order of ACEs is more complicated 204 * because of the introduction of object-specific ACEs and automatic 205 * inheritance. 206 * 207 * The following describes the preferred order: 208 * 209 * To ensure that noninherited ACEs have precedence over inherited ACEs, 210 * place all noninherited ACEs in a group before any inherited ACEs. This 211 * ordering ensures, for example, that a noninherited access-denied ACE 212 * is enforced regardless of any inherited ACE that allows access. 213 * Within the groups of noninherited ACEs and inherited ACEs, order ACEs 214 * according to ACE type, as the following shows: 215 * . Access-denied ACEs that apply to the object itself 216 * . Access-denied ACEs that apply to a subobject of the 217 * object, such as a property set or property 218 * . Access-allowed ACEs that apply to the object itself 219 * . Access-allowed ACEs that apply to a subobject of the object 220 * 221 * So, here is the desired ACE order 222 * 223 * deny-direct, allow-direct, deny-inherited, allow-inherited 224 * 225 * Of course, not all ACE types are required in an ACL. 226 */ 227 void 228 smb_acl_sort(smb_acl_t *acl) 229 { 230 list_t ace_grps[SMB_AG_NUM]; 231 list_t *alist; 232 smb_ace_t *ace; 233 uint8_t ace_flags; 234 int ag, i; 235 236 ASSERT(acl); 237 238 if (acl->sl_acecnt == 0) { 239 /* 240 * ACL with no entry is a valid ACL and it means 241 * no access for anybody. 242 */ 243 return; 244 } 245 246 for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { 247 list_create(&ace_grps[i], sizeof (smb_ace_t), 248 offsetof(smb_ace_t, se_sln)); 249 } 250 251 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) { 252 ace_flags = ace->se_hdr.se_flags; 253 254 switch (ace->se_hdr.se_type) { 255 case ACCESS_DENIED_ACE_TYPE: 256 ag = (ace_flags & INHERITED_ACE) ? 257 SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT; 258 break; 259 260 case ACCESS_ALLOWED_ACE_TYPE: 261 ag = (ace_flags & INHERITED_ACE) ? 262 SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT; 263 break; 264 265 default: 266 /* 267 * This is the lowest priority group so we put 268 * evertything unknown here. 269 */ 270 ag = SMB_AG_ALW_INHRT; 271 break; 272 } 273 274 /* Add the ACE to the selected group */ 275 list_insert_tail(&ace_grps[ag], ace); 276 } 277 278 /* 279 * start with highest priority ACE group and append 280 * the ACEs to the ACL. 281 */ 282 for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { 283 alist = &ace_grps[i]; 284 while ((ace = list_head(alist)) != NULL) { 285 list_remove(alist, ace); 286 list_insert_tail(&acl->sl_sorted, ace); 287 } 288 list_destroy(alist); 289 } 290 } 291 292 /* 293 * Error handling call-back for smb_idmap_batch_getmappings. 294 * Would be nice if this could report the path, but that's not 295 * passed down here. For now, use a dtrace fbt probe here. 296 */ 297 static void 298 smb_acl_bgm_error(smb_idmap_batch_t *sib, smb_idmap_t *sim) 299 { 300 301 if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) != 0) 302 return; 303 304 if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) { 305 /* 306 * Note: The ID and type we asked idmap to map 307 * were saved in *sim_id and sim_idtype. 308 */ 309 int id = (sim->sim_id == NULL) ? -1 : (int)*sim->sim_id; 310 cmn_err(CE_WARN, "!smb_acl: Can't get SID for " 311 "ID=%d type=%d, status=%d", 312 id, sim->sim_idtype, sim->sim_stat); 313 } 314 315 if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) { 316 cmn_err(CE_WARN, "!smb_acl: Can't get ID for " 317 "SID %s-%u, status=%d", 318 sim->sim_domsid, sim->sim_rid, sim->sim_stat); 319 } 320 } 321 322 /* 323 * smb_acl_from_zfs 324 * 325 * Converts given ZFS ACL to a Windows ACL. 326 * 327 * A pointer to allocated memory for the Win ACL will be 328 * returned upon successful conversion. 329 */ 330 smb_acl_t * 331 smb_acl_from_zfs(acl_t *zacl) 332 { 333 ace_t *zace; 334 int numaces; 335 smb_acl_t *acl; 336 smb_ace_t *ace; 337 smb_idmap_batch_t sib; 338 smb_idmap_t *sim; 339 idmap_stat idm_stat; 340 341 idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, 342 SMB_IDMAP_ID2SID); 343 if (idm_stat != IDMAP_SUCCESS) 344 return (NULL); 345 346 /* 347 * Note that smb_fsacl_getsids sets up references in 348 * sib.sib_maps to the zace->a_who fields that live 349 * until smb_idmap_batch_destroy is called. 350 */ 351 if (smb_fsacl_getsids(&sib, zacl) != IDMAP_SUCCESS) { 352 smb_idmap_batch_destroy(&sib); 353 return (NULL); 354 } 355 356 acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt); 357 358 sim = sib.sib_maps; 359 for (numaces = 0, zace = zacl->acl_aclp; 360 numaces < zacl->acl_cnt; 361 zace++, numaces++, sim++) { 362 ASSERT(sim->sim_sid); 363 if (sim->sim_sid == NULL) { 364 smb_acl_free(acl); 365 acl = NULL; 366 break; 367 } 368 369 ace = &acl->sl_aces[numaces]; 370 ace->se_hdr.se_type = zace->a_type; 371 ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags); 372 ace->se_mask = zace->a_access_mask; 373 ace->se_sid = smb_sid_dup(sim->sim_sid); 374 ace->se_hdr.se_bsize = smb_ace_len(ace); 375 376 acl->sl_bsize += ace->se_hdr.se_bsize; 377 } 378 379 smb_idmap_batch_destroy(&sib); 380 return (acl); 381 } 382 383 /* 384 * smb_acl_to_zfs 385 * 386 * Converts given Windows ACL to a ZFS ACL. 387 * 388 * fs_acl will contain a pointer to the created ZFS ACL. 389 * The allocated memory should be freed by calling 390 * smb_fsacl_free(). 391 * 392 * Since the output parameter, fs_acl, is allocated in this 393 * function, the caller has to make sure *fs_acl is NULL which 394 * means it's not pointing to any memory. 395 */ 396 uint32_t 397 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) 398 { 399 smb_ace_t *ace; 400 acl_t *zacl; 401 ace_t *zace; 402 smb_idmap_batch_t sib; 403 smb_idmap_t *sim; 404 idmap_stat idm_stat; 405 char *sidstr; 406 int i; 407 408 ASSERT(fs_acl); 409 ASSERT(*fs_acl == NULL); 410 411 if (acl && !smb_acl_isvalid(acl, which_acl)) 412 return (NT_STATUS_INVALID_ACL); 413 414 if ((acl == NULL) || (acl->sl_acecnt == 0)) { 415 if (which_acl == SMB_DACL_SECINFO) { 416 *fs_acl = smb_fsacl_null_empty(acl == NULL); 417 } 418 419 return (NT_STATUS_SUCCESS); 420 } 421 422 idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, 423 SMB_IDMAP_SID2ID); 424 if (idm_stat != IDMAP_SUCCESS) 425 return (NT_STATUS_INTERNAL_ERROR); 426 427 sidstr = kmem_alloc(SMB_SID_STRSZ, KM_SLEEP); 428 zacl = smb_fsacl_alloc(acl->sl_acecnt, flags); 429 430 zace = zacl->acl_aclp; 431 ace = acl->sl_aces; 432 sim = sib.sib_maps; 433 434 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 435 zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES; 436 zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); 437 zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags); 438 zace->a_who = (uid_t)-1; 439 440 smb_sid_tostr(ace->se_sid, sidstr); 441 442 if (!smb_ace_wellknown_update(sidstr, zace)) { 443 sim->sim_id = &zace->a_who; 444 idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, 445 ace->se_sid, SMB_IDMAP_UNKNOWN); 446 447 if (idm_stat != IDMAP_SUCCESS) { 448 kmem_free(sidstr, SMB_SID_STRSZ); 449 smb_fsacl_free(zacl); 450 smb_idmap_batch_destroy(&sib); 451 return (NT_STATUS_INTERNAL_ERROR); 452 } 453 } 454 } 455 456 kmem_free(sidstr, SMB_SID_STRSZ); 457 458 idm_stat = smb_idmap_batch_getmappings(&sib, smb_acl_bgm_error); 459 if (idm_stat != IDMAP_SUCCESS) { 460 smb_fsacl_free(zacl); 461 smb_idmap_batch_destroy(&sib); 462 return (NT_STATUS_NONE_MAPPED); 463 } 464 465 /* 466 * Set the ACEs group flag based on the type of ID returned. 467 */ 468 zace = zacl->acl_aclp; 469 ace = acl->sl_aces; 470 sim = sib.sib_maps; 471 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 472 if (zace->a_who == (uid_t)-1) 473 continue; 474 475 if (sim->sim_idtype == SMB_IDMAP_GROUP) 476 zace->a_flags |= ACE_IDENTIFIER_GROUP; 477 } 478 479 smb_idmap_batch_destroy(&sib); 480 481 *fs_acl = zacl; 482 return (NT_STATUS_SUCCESS); 483 } 484 485 static boolean_t 486 smb_ace_wellknown_update(const char *sid, ace_t *zace) 487 { 488 struct { 489 char *sid; 490 uint16_t flags; 491 } map[] = { 492 { NT_WORLD_SIDSTR, ACE_EVERYONE }, 493 { NT_BUILTIN_CURRENT_OWNER_SIDSTR, ACE_OWNER }, 494 { NT_BUILTIN_CURRENT_GROUP_SIDSTR, 495 (ACE_GROUP | ACE_IDENTIFIER_GROUP) }, 496 }; 497 498 int i; 499 500 for (i = 0; i < (sizeof (map) / sizeof (map[0])); ++i) { 501 if (strcmp(sid, map[i].sid) == 0) { 502 zace->a_flags |= map[i].flags; 503 return (B_TRUE); 504 } 505 } 506 507 return (B_FALSE); 508 } 509 510 /* 511 * smb_fsacl_getsids 512 * 513 * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs. 514 * Note: sib is type SMB_IDMAP_ID2SID, zacl->acl_cnt entries. 515 */ 516 static idmap_stat 517 smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl) 518 { 519 ace_t *zace; 520 idmap_stat idm_stat; 521 smb_idmap_t *sim; 522 uid_t id; 523 int i, idtype; 524 525 sim = sib->sib_maps; 526 527 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; 528 zace++, i++, sim++) { 529 id = (uid_t)-1; /* some types do not need id */ 530 switch (zace->a_flags & ACE_TYPE_FLAGS) { 531 case ACE_OWNER: 532 idtype = SMB_IDMAP_OWNERAT; 533 break; 534 535 case (ACE_GROUP | ACE_IDENTIFIER_GROUP): 536 /* owning group */ 537 idtype = SMB_IDMAP_GROUPAT; 538 break; 539 540 case ACE_IDENTIFIER_GROUP: 541 /* regular group */ 542 idtype = SMB_IDMAP_GROUP; 543 id = zace->a_who; 544 /* for smb_acl_bgm_error() ID2SID */ 545 sim->sim_id = &zace->a_who; 546 break; 547 548 case ACE_EVERYONE: 549 idtype = SMB_IDMAP_EVERYONE; 550 break; 551 552 default: 553 /* user entry */ 554 idtype = SMB_IDMAP_USER; 555 id = zace->a_who; 556 /* for smb_acl_bgm_error() ID2SID */ 557 sim->sim_id = &zace->a_who; 558 } 559 560 idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim, 561 id, idtype); 562 563 if (idm_stat != IDMAP_SUCCESS) { 564 return (idm_stat); 565 } 566 } 567 568 idm_stat = smb_idmap_batch_getmappings(sib, smb_acl_bgm_error); 569 return (idm_stat); 570 } 571 572 /* 573 * smb_fsacl_null_empty 574 * 575 * NULL DACL means everyone full-access 576 * Empty DACL means everyone full-deny 577 * 578 * ZFS ACL must have at least one entry so smb server has 579 * to simulate the aforementioned expected behavior by adding 580 * an entry in case the requested DACL is null or empty. Adding 581 * a everyone full-deny entry has proved to be problematic in 582 * tests since a deny entry takes precedence over allow entries. 583 * So, instead of adding a everyone full-deny, an owner ACE with 584 * owner implicit permissions will be set. 585 */ 586 static acl_t * 587 smb_fsacl_null_empty(boolean_t null) 588 { 589 acl_t *zacl; 590 ace_t *zace; 591 592 zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT); 593 zace = zacl->acl_aclp; 594 595 zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 596 if (null) { 597 zace->a_access_mask = ACE_ALL_PERMS; 598 zace->a_flags = ACE_EVERYONE; 599 } else { 600 zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | 601 ACE_READ_ATTRIBUTES; 602 zace->a_flags = ACE_OWNER; 603 } 604 605 return (zacl); 606 } 607 608 /* 609 * FS ACL (acl_t) Functions 610 */ 611 acl_t * 612 smb_fsacl_alloc(int acenum, int flags) 613 { 614 acl_t *acl; 615 616 acl = acl_alloc(ACE_T); 617 acl->acl_cnt = acenum; 618 acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP); 619 acl->acl_flags = flags; 620 return (acl); 621 } 622 623 void 624 smb_fsacl_free(acl_t *acl) 625 { 626 if (acl) 627 acl_free(acl); 628 } 629 630 /* 631 * smb_fsop_aclmerge 632 * 633 * smb_fsop_aclread/write routines which interact with filesystem 634 * work with single ACL. This routine merges given DACL and SACL 635 * which might have been created during CIFS to FS conversion into 636 * one single ACL. 637 */ 638 acl_t * 639 smb_fsacl_merge(acl_t *dacl, acl_t *sacl) 640 { 641 acl_t *acl; 642 int dacl_size; 643 644 ASSERT(dacl); 645 ASSERT(sacl); 646 647 acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags); 648 dacl_size = dacl->acl_cnt * dacl->acl_entry_size; 649 bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size); 650 bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size, 651 sacl->acl_cnt * sacl->acl_entry_size); 652 653 return (acl); 654 } 655 656 /* 657 * smb_fsacl_split 658 * 659 * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on 660 * the 'which_acl' parameter. Note that output dacl/sacl parameters could be 661 * NULL even if they're specified in 'which_acl', which means the target 662 * doesn't have any access and/or audit ACEs. 663 */ 664 void 665 smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl) 666 { 667 ace_t *zace; 668 ace_t *access_ace = NULL; 669 ace_t *audit_ace = NULL; 670 int naccess, naudit; 671 int get_dacl, get_sacl; 672 int i; 673 674 *dacl = *sacl = NULL; 675 naccess = naudit = 0; 676 get_dacl = (which_acl & SMB_DACL_SECINFO); 677 get_sacl = (which_acl & SMB_SACL_SECINFO); 678 679 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { 680 if (get_dacl && smb_ace_is_access(zace->a_type)) 681 naccess++; 682 else if (get_sacl && smb_ace_is_audit(zace->a_type)) 683 naudit++; 684 } 685 686 if (naccess) { 687 *dacl = smb_fsacl_alloc(naccess, zacl->acl_flags); 688 access_ace = (*dacl)->acl_aclp; 689 } 690 691 if (naudit) { 692 *sacl = smb_fsacl_alloc(naudit, zacl->acl_flags); 693 audit_ace = (*sacl)->acl_aclp; 694 } 695 696 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { 697 if (get_dacl && smb_ace_is_access(zace->a_type)) { 698 *access_ace = *zace; 699 access_ace++; 700 } else if (get_sacl && smb_ace_is_audit(zace->a_type)) { 701 *audit_ace = *zace; 702 audit_ace++; 703 } 704 } 705 } 706 707 /* 708 * ACE Inheritance Rules 709 * 710 * The system propagates inheritable ACEs to child objects according to a 711 * set of inheritance rules. The system places inherited ACEs in the child's 712 * DACL according to the preferred order of ACEs in a DACL. For Windows 713 * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs. 714 * 715 * The following table shows the ACEs inherited by container and noncontainer 716 * child objects for different combinations of inheritance flags. These 717 * inheritance rules work the same for both DACLs and SACLs. 718 * 719 * Parent ACE type Effect on Child ACL 720 * ----------------------- ------------------- 721 * OBJECT_INHERIT_ACE only Noncontainer child objects: 722 * Inherited as an effective ACE. 723 * Container child objects: 724 * Containers inherit an inherit-only ACE 725 * unless the NO_PROPAGATE_INHERIT_ACE bit 726 * flag is also set. 727 * 728 * CONTAINER_INHERIT_ACE only Noncontainer child objects: 729 * No effect on the child object. 730 * Container child objects: 731 * The child object inherits an effective ACE. 732 * The inherited ACE is inheritable unless the 733 * NO_PROPAGATE_INHERIT_ACE bit flag is also set. 734 * 735 * CONTAINER_INHERIT_ACE and 736 * OBJECT_INHERIT_ACE Noncontainer child objects: 737 * Inherited as an effective ACE. 738 * Container child objects: 739 * The child object inherits an effective ACE. 740 * The inherited ACE is inheritable unless the 741 * NO_PROPAGATE_INHERIT_ACE bit flag is also set 742 * 743 * No inheritance flags set No effect on child container or noncontainer 744 * objects. 745 * 746 * If an inherited ACE is an effective ACE for the child object, the system 747 * maps any generic rights to the specific rights for the child object. 748 * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the 749 * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic 750 * rights or generic SIDs are left unchanged so that they can be mapped 751 * appropriately when the ACE is inherited by the next generation of child 752 * objects. 753 * 754 * For a case in which a container object inherits an ACE that is both 755 * effective on the container and inheritable by its descendants, the 756 * container may inherit two ACEs. This occurs if the inheritable ACE 757 * contains generic information. The container inherits an inherit-only 758 * ACE containing the generic information and an effective-only ACE in 759 * which the generic information has been mapped. 760 */ 761 762 #ifdef _KERNEL 763 /* 764 * smb_fsacl_inherit 765 * 766 * Manufacture the inherited ACL from the given ACL considering 767 * the new object type (file/dir) specified by 'is_dir'. The 768 * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions. 769 * This function implements Windows inheritance rules explained above. 770 * 771 * Note that the in/out ACLs are ZFS ACLs not Windows ACLs 772 */ 773 acl_t * 774 smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, cred_t *cr) 775 { 776 boolean_t use_default = B_FALSE; 777 int num_inheritable = 0; 778 int numaces; 779 ace_t *dir_zace; 780 acl_t *new_zacl; 781 ace_t *new_zace; 782 ksid_t *owner_sid; 783 ksid_t *group_sid; 784 uid_t uid; 785 gid_t gid; 786 787 owner_sid = crgetsid(cr, KSID_OWNER); 788 group_sid = crgetsid(cr, KSID_GROUP); 789 ASSERT(owner_sid); 790 ASSERT(group_sid); 791 uid = owner_sid->ks_id; 792 gid = group_sid->ks_id; 793 794 num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir); 795 796 if (num_inheritable == 0) { 797 if (which_acl == SMB_DACL_SECINFO) { 798 /* No inheritable access ACEs -> default DACL */ 799 num_inheritable = DEFAULT_DACL_ACENUM; 800 use_default = B_TRUE; 801 } else { 802 return (NULL); 803 } 804 } 805 806 new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT); 807 new_zace = new_zacl->acl_aclp; 808 809 if (use_default) { 810 bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl)); 811 new_zace->a_who = uid; 812 return (new_zacl); 813 } 814 815 for (numaces = 0, dir_zace = dir_zacl->acl_aclp; 816 numaces < dir_zacl->acl_cnt; 817 dir_zace++, numaces++) { 818 switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) { 819 case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 820 /* 821 * Files inherit an effective ACE. 822 * 823 * Dirs inherit an effective ACE. 824 * The inherited ACE is inheritable unless the 825 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 826 */ 827 smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid); 828 new_zace++; 829 830 if (is_dir && ZACE_IS_CREATOR(dir_zace) && 831 (ZACE_IS_PROPAGATE(dir_zace))) { 832 *new_zace = *dir_zace; 833 new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 834 ACE_INHERITED_ACE); 835 new_zace++; 836 } 837 break; 838 839 case ACE_FILE_INHERIT_ACE: 840 /* 841 * Files inherit as an effective ACE. 842 * 843 * Dirs inherit an inherit-only ACE 844 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 845 * flag is also set. 846 */ 847 if (is_dir == 0) { 848 smb_ace_inherit(dir_zace, new_zace, is_dir, 849 uid, gid); 850 new_zace++; 851 } else if (ZACE_IS_PROPAGATE(dir_zace)) { 852 *new_zace = *dir_zace; 853 new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 854 ACE_INHERITED_ACE); 855 new_zace++; 856 } 857 break; 858 859 case ACE_DIRECTORY_INHERIT_ACE: 860 /* 861 * No effect on files 862 * 863 * Dirs inherit an effective ACE. 864 * The inherited ACE is inheritable unless the 865 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 866 */ 867 if (is_dir == 0) 868 break; 869 870 smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid); 871 new_zace++; 872 873 if (ZACE_IS_CREATOR(dir_zace) && 874 (ZACE_IS_PROPAGATE(dir_zace))) { 875 *new_zace = *dir_zace; 876 new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 877 ACE_INHERITED_ACE); 878 new_zace++; 879 } 880 881 break; 882 883 default: 884 break; 885 } 886 } 887 888 return (new_zacl); 889 } 890 #endif /* _KERNEL */ 891 892 /* 893 * smb_fsacl_from_vsa 894 * 895 * Converts given vsecattr_t structure to a acl_t structure. 896 * 897 * The allocated memory for retuned acl_t should be freed by 898 * calling acl_free(). 899 */ 900 acl_t * 901 smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type) 902 { 903 int aclbsize = 0; /* size of acl list in bytes */ 904 int dfaclbsize = 0; /* size of default acl list in bytes */ 905 int numacls; 906 acl_t *acl_info; 907 908 ASSERT(vsecattr); 909 910 acl_info = acl_alloc(acl_type); 911 if (acl_info == NULL) 912 return (NULL); 913 914 acl_info->acl_flags = 0; 915 916 switch (acl_type) { 917 918 case ACLENT_T: 919 numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt; 920 aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t); 921 dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t); 922 923 acl_info->acl_cnt = numacls; 924 acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize, 925 KM_SLEEP); 926 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, 927 aclbsize); 928 (void) memcpy((char *)acl_info->acl_aclp + aclbsize, 929 vsecattr->vsa_dfaclentp, dfaclbsize); 930 931 if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) 932 acl_info->acl_flags |= ACL_IS_TRIVIAL; 933 934 break; 935 936 case ACE_T: 937 aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); 938 acl_info->acl_cnt = vsecattr->vsa_aclcnt; 939 acl_info->acl_flags = vsecattr->vsa_aclflags; 940 acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP); 941 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, 942 aclbsize); 943 if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) 944 acl_info->acl_flags |= ACL_IS_TRIVIAL; 945 946 break; 947 948 default: 949 acl_free(acl_info); 950 return (NULL); 951 } 952 953 if (aclbsize && vsecattr->vsa_aclentp) 954 kmem_free(vsecattr->vsa_aclentp, aclbsize); 955 if (dfaclbsize && vsecattr->vsa_dfaclentp) 956 kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize); 957 958 return (acl_info); 959 } 960 961 /* 962 * smb_fsacl_to_vsa 963 * 964 * Converts given acl_t structure to a vsecattr_t structure. 965 * 966 * IMPORTANT: 967 * Upon successful return the memory allocated for vsa_aclentp 968 * should be freed by calling kmem_free(). The size is returned 969 * in aclbsize. 970 */ 971 int 972 smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize) 973 { 974 int error = 0; 975 int numacls; 976 aclent_t *aclp; 977 978 ASSERT(acl_info); 979 ASSERT(vsecattr); 980 ASSERT(aclbsize); 981 982 bzero(vsecattr, sizeof (vsecattr_t)); 983 *aclbsize = 0; 984 985 switch (acl_info->acl_type) { 986 case ACLENT_T: 987 numacls = acl_info->acl_cnt; 988 /* 989 * Minimum ACL size is three entries so might as well 990 * bail out here. Also limit request size to prevent user 991 * from allocating too much kernel memory. Maximum size 992 * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES 993 * for the default ACL part. 994 */ 995 if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) { 996 error = EINVAL; 997 break; 998 } 999 1000 vsecattr->vsa_mask = VSA_ACL; 1001 1002 vsecattr->vsa_aclcnt = numacls; 1003 *aclbsize = numacls * sizeof (aclent_t); 1004 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); 1005 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, 1006 *aclbsize); 1007 1008 /* Sort the acl list */ 1009 ksort((caddr_t)vsecattr->vsa_aclentp, 1010 vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls); 1011 1012 /* Break into acl and default acl lists */ 1013 for (numacls = 0, aclp = vsecattr->vsa_aclentp; 1014 numacls < vsecattr->vsa_aclcnt; 1015 aclp++, numacls++) { 1016 if (aclp->a_type & ACL_DEFAULT) 1017 break; 1018 } 1019 1020 /* Find where defaults start (if any) */ 1021 if (numacls < vsecattr->vsa_aclcnt) { 1022 vsecattr->vsa_mask |= VSA_DFACL; 1023 vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls; 1024 vsecattr->vsa_dfaclentp = aclp; 1025 vsecattr->vsa_aclcnt = numacls; 1026 } 1027 1028 /* Adjust if they're all defaults */ 1029 if (vsecattr->vsa_aclcnt == 0) { 1030 vsecattr->vsa_mask &= ~VSA_ACL; 1031 vsecattr->vsa_aclentp = NULL; 1032 } 1033 1034 /* Only directories can have defaults */ 1035 if (vsecattr->vsa_dfaclcnt && 1036 (acl_info->acl_flags & ACL_IS_DIR)) { 1037 error = ENOTDIR; 1038 } 1039 1040 break; 1041 1042 case ACE_T: 1043 if (acl_info->acl_cnt < 1 || 1044 acl_info->acl_cnt > MAX_ACL_ENTRIES) { 1045 error = EINVAL; 1046 break; 1047 } 1048 1049 vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 1050 vsecattr->vsa_aclcnt = acl_info->acl_cnt; 1051 vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL; 1052 *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); 1053 vsecattr->vsa_aclentsz = *aclbsize; 1054 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); 1055 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, 1056 *aclbsize); 1057 1058 break; 1059 1060 default: 1061 error = EINVAL; 1062 } 1063 1064 return (error); 1065 } 1066 1067 #ifdef _KERNEL 1068 /* 1069 * smb_fsacl_inheritable 1070 * 1071 * Checks to see if there are any inheritable ACEs in the 1072 * given ZFS ACL. Returns the number of inheritable ACEs. 1073 * 1074 * The inherited ACL could be different based on the type of 1075 * new object (file/dir) specified by 'is_dir'. 1076 * 1077 * Note that the input ACL is a ZFS ACL not Windows ACL. 1078 */ 1079 static int 1080 smb_fsacl_inheritable(acl_t *zacl, int is_dir) 1081 { 1082 int numaces; 1083 int num_inheritable = 0; 1084 ace_t *zace; 1085 1086 if (zacl == NULL) 1087 return (0); 1088 1089 for (numaces = 0, zace = zacl->acl_aclp; 1090 numaces < zacl->acl_cnt; 1091 zace++, numaces++) { 1092 switch (zace->a_flags & ACE_FD_INHERIT_ACE) { 1093 case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 1094 /* 1095 * Files inherit an effective ACE. 1096 * 1097 * Dirs inherit an effective ACE. 1098 * The inherited ACE is inheritable unless the 1099 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 1100 */ 1101 num_inheritable++; 1102 1103 if (is_dir && ZACE_IS_CREATOR(zace) && 1104 (ZACE_IS_PROPAGATE(zace))) { 1105 num_inheritable++; 1106 } 1107 break; 1108 1109 case ACE_FILE_INHERIT_ACE: 1110 /* 1111 * Files inherit as an effective ACE. 1112 * 1113 * Dirs inherit an inherit-only ACE 1114 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 1115 * flag is also set. 1116 */ 1117 if (is_dir == 0) 1118 num_inheritable++; 1119 else if (ZACE_IS_PROPAGATE(zace)) 1120 num_inheritable++; 1121 break; 1122 1123 case ACE_DIRECTORY_INHERIT_ACE: 1124 /* 1125 * No effect on files 1126 * 1127 * Dirs inherit an effective ACE. 1128 * The inherited ACE is inheritable unless the 1129 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 1130 */ 1131 if (is_dir == 0) 1132 break; 1133 1134 num_inheritable++; 1135 1136 if (ZACE_IS_CREATOR(zace) && 1137 (ZACE_IS_PROPAGATE(zace))) 1138 num_inheritable++; 1139 break; 1140 1141 default: 1142 break; 1143 } 1144 } 1145 1146 return (num_inheritable); 1147 } 1148 #endif /* _KERNEL */ 1149 1150 1151 /* 1152 * ACE Functions 1153 */ 1154 1155 /* 1156 * This is generic (ACL version 2) vs. object-specific 1157 * (ACL version 4) ACE types. 1158 */ 1159 boolean_t 1160 smb_ace_is_generic(int type) 1161 { 1162 switch (type) { 1163 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1164 case ACE_ACCESS_DENIED_ACE_TYPE: 1165 case ACE_SYSTEM_AUDIT_ACE_TYPE: 1166 case ACE_SYSTEM_ALARM_ACE_TYPE: 1167 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 1168 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 1169 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 1170 case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE: 1171 return (B_TRUE); 1172 1173 default: 1174 break; 1175 } 1176 1177 return (B_FALSE); 1178 } 1179 1180 boolean_t 1181 smb_ace_is_access(int type) 1182 { 1183 switch (type) { 1184 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1185 case ACE_ACCESS_DENIED_ACE_TYPE: 1186 case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: 1187 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1188 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1189 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 1190 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 1191 case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 1192 case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 1193 return (B_TRUE); 1194 1195 default: 1196 break; 1197 } 1198 1199 return (B_FALSE); 1200 } 1201 1202 boolean_t 1203 smb_ace_is_audit(int type) 1204 { 1205 switch (type) { 1206 case ACE_SYSTEM_AUDIT_ACE_TYPE: 1207 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1208 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 1209 case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 1210 return (B_TRUE); 1211 1212 default: 1213 break; 1214 } 1215 1216 return (B_FALSE); 1217 } 1218 1219 /* 1220 * smb_ace_len 1221 * 1222 * Returns the length of the given ACE as it appears in an 1223 * ACL on the wire (i.e. a flat buffer which contains the SID) 1224 */ 1225 static uint16_t 1226 smb_ace_len(smb_ace_t *ace) 1227 { 1228 ASSERT(ace); 1229 ASSERT(ace->se_sid); 1230 1231 if (ace == NULL) 1232 return (0); 1233 1234 return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) + 1235 smb_sid_len(ace->se_sid)); 1236 } 1237 1238 #ifdef _KERNEL 1239 static void 1240 smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir, uid_t uid, gid_t gid) 1241 { 1242 *zace = *dir_zace; 1243 1244 /* This is an effective ACE so remove the inherit_only flag */ 1245 zace->a_flags &= ~ACE_INHERIT_ONLY_ACE; 1246 /* Mark this ACE as inherited */ 1247 zace->a_flags |= ACE_INHERITED_ACE; 1248 1249 /* 1250 * If this is a file or NO_PROPAGATE is set then this inherited 1251 * ACE is not inheritable so clear the inheritance flags 1252 */ 1253 if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace))) 1254 zace->a_flags &= ~ACE_INHERIT_FLAGS; 1255 1256 /* 1257 * Replace creator owner/group ACEs with actual owner/group ACEs. 1258 * This is a non-inheritable effective ACE. 1259 */ 1260 if (ZACE_IS_CREATOR_OWNER(dir_zace)) { 1261 zace->a_who = uid; 1262 zace->a_flags &= ~ACE_INHERIT_FLAGS; 1263 } else if (ZACE_IS_CREATOR_GROUP(dir_zace)) { 1264 zace->a_who = gid; 1265 zace->a_flags |= ACE_IDENTIFIER_GROUP; 1266 zace->a_flags &= ~ACE_INHERIT_FLAGS; 1267 } 1268 } 1269 #endif /* _KERNEL */ 1270 1271 /* 1272 * smb_ace_mask_g2s 1273 * 1274 * Converts generic access bits in the given mask (if any) 1275 * to file specific bits. Generic access masks shouldn't be 1276 * stored in filesystem ACEs. 1277 */ 1278 static uint32_t 1279 smb_ace_mask_g2s(uint32_t mask) 1280 { 1281 if (mask & GENERIC_ALL) { 1282 mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE 1283 | GENERIC_EXECUTE); 1284 1285 mask |= FILE_ALL_ACCESS; 1286 return (mask); 1287 } 1288 1289 if (mask & GENERIC_READ) { 1290 mask &= ~GENERIC_READ; 1291 mask |= FILE_GENERIC_READ; 1292 } 1293 1294 if (mask & GENERIC_WRITE) { 1295 mask &= ~GENERIC_WRITE; 1296 mask |= FILE_GENERIC_WRITE; 1297 } 1298 1299 if (mask & GENERIC_EXECUTE) { 1300 mask &= ~GENERIC_EXECUTE; 1301 mask |= FILE_GENERIC_EXECUTE; 1302 } 1303 1304 return (mask); 1305 } 1306 1307 /* 1308 * smb_ace_flags_tozfs 1309 * 1310 * This function maps the flags which have different values 1311 * in Windows and Solaris. The ones with the same value are 1312 * transferred untouched. 1313 */ 1314 static uint16_t 1315 smb_ace_flags_tozfs(uint8_t c_flags) 1316 { 1317 uint16_t z_flags = 0; 1318 1319 if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG) 1320 z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 1321 1322 if (c_flags & FAILED_ACCESS_ACE_FLAG) 1323 z_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 1324 1325 if (c_flags & INHERITED_ACE) 1326 z_flags |= ACE_INHERITED_ACE; 1327 1328 z_flags |= (c_flags & ACE_INHERIT_FLAGS); 1329 1330 return (z_flags); 1331 } 1332 1333 static uint8_t 1334 smb_ace_flags_fromzfs(uint16_t z_flags) 1335 { 1336 uint8_t c_flags; 1337 1338 c_flags = z_flags & ACE_INHERIT_FLAGS; 1339 1340 if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 1341 c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG; 1342 1343 if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG) 1344 c_flags |= FAILED_ACCESS_ACE_FLAG; 1345 1346 if (z_flags & ACE_INHERITED_ACE) 1347 c_flags |= INHERITED_ACE; 1348 1349 return (c_flags); 1350 } 1351 1352 static boolean_t 1353 smb_ace_isvalid(smb_ace_t *ace, int which_acl) 1354 { 1355 uint16_t min_len; 1356 1357 min_len = sizeof (smb_acehdr_t); 1358 1359 if (ace->se_hdr.se_bsize < min_len) 1360 return (B_FALSE); 1361 1362 if (smb_ace_is_access(ace->se_hdr.se_type) && 1363 (which_acl != SMB_DACL_SECINFO)) 1364 return (B_FALSE); 1365 1366 if (smb_ace_is_audit(ace->se_hdr.se_type) && 1367 (which_acl != SMB_SACL_SECINFO)) 1368 return (B_FALSE); 1369 1370 if (smb_ace_is_generic(ace->se_hdr.se_type)) { 1371 if (!smb_sid_isvalid(ace->se_sid)) 1372 return (B_FALSE); 1373 1374 min_len += sizeof (ace->se_mask); 1375 min_len += smb_sid_len(ace->se_sid); 1376 1377 if (ace->se_hdr.se_bsize < min_len) 1378 return (B_FALSE); 1379 } 1380 1381 /* 1382 * object-specific ACE validation will be added later. 1383 */ 1384 return (B_TRUE); 1385 } 1386