1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22f96bd5c8SAlan Wright * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24*b819cea2SGordon Ross * 25*b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 26da6c28aaSamw */ 27da6c28aaSamw 289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <sys/sid.h> 29da6c28aaSamw #include <sys/acl.h> 3055bf511dSas200622 #include <acl/acl_common.h> 316537f381Sas200622 #include <smbsrv/smb_sid.h> 32da6c28aaSamw #include <smbsrv/smb_fsops.h> 33da6c28aaSamw #include <smbsrv/smb_idmap.h> 3455bf511dSas200622 #include <smbsrv/smb_kproto.h> 35da6c28aaSamw 36da6c28aaSamw #define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE) 37da6c28aaSamw 38da6c28aaSamw #define ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER) 39da6c28aaSamw #define ZACE_IS_OWNGRP(zace) \ 40da6c28aaSamw ((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP)) 41da6c28aaSamw 42da6c28aaSamw #define ZACE_IS_USER(zace) \ 43da6c28aaSamw (((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace))) 44da6c28aaSamw #define ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP) 45da6c28aaSamw #define ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE) 46da6c28aaSamw 47da6c28aaSamw #define ZACE_IS_PROPAGATE(zace) \ 48da6c28aaSamw ((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0) 49da6c28aaSamw 50da6c28aaSamw #define ZACE_IS_CREATOR_OWNER(zace) \ 51da6c28aaSamw (ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID)) 52da6c28aaSamw 53da6c28aaSamw #define ZACE_IS_CREATOR_GROUP(zace) \ 54da6c28aaSamw (ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID)) 55da6c28aaSamw 56da6c28aaSamw #define ZACE_IS_CREATOR(zace) \ 57da6c28aaSamw (ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace)) 58da6c28aaSamw 59da6c28aaSamw /* 60da6c28aaSamw * ACE groups within a DACL 61da6c28aaSamw * 62da6c28aaSamw * This is from lower to higher ACE order priority 63da6c28aaSamw */ 64da6c28aaSamw #define SMB_AG_START 0 65da6c28aaSamw #define SMB_AG_ALW_INHRT 0 66da6c28aaSamw #define SMB_AG_DNY_INHRT 1 67da6c28aaSamw #define SMB_AG_ALW_DRCT 2 68da6c28aaSamw #define SMB_AG_DNY_DRCT 3 69da6c28aaSamw #define SMB_AG_NUM 4 70da6c28aaSamw 7155bf511dSas200622 #define DEFAULT_DACL_ACENUM 2 7255bf511dSas200622 /* 7355bf511dSas200622 * Default ACL: 7455bf511dSas200622 * owner: full access 7555bf511dSas200622 * SYSTEM: full access 7655bf511dSas200622 */ 77*b819cea2SGordon Ross #ifdef _KERNEL 788622ec45SGordon Ross static const ace_t const default_dacl[DEFAULT_DACL_ACENUM] = { 7955bf511dSas200622 { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, 8055bf511dSas200622 { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP, 8155bf511dSas200622 ACE_ACCESS_ALLOWED_ACE_TYPE } 8255bf511dSas200622 }; 83*b819cea2SGordon Ross #endif /* _KERNEL */ 8455bf511dSas200622 8555bf511dSas200622 /* 8655bf511dSas200622 * Note: 87da6c28aaSamw * 8855bf511dSas200622 * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format 8955bf511dSas200622 * smb_fsacl_xxx functions work with acl_t which represents the Solaris native 9055bf511dSas200622 * format 9155bf511dSas200622 */ 9255bf511dSas200622 93f96bd5c8SAlan Wright static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *); 94c8ec8eeaSjose borrego static acl_t *smb_fsacl_null_empty(boolean_t); 95*b819cea2SGordon Ross #ifdef _KERNEL 9655bf511dSas200622 static int smb_fsacl_inheritable(acl_t *, int); 979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_ace_inherit(ace_t *, ace_t *, int, uid_t, gid_t); 98*b819cea2SGordon Ross #endif /* _KERNEL */ 99*b819cea2SGordon Ross 10055bf511dSas200622 static boolean_t smb_ace_isvalid(smb_ace_t *, int); 10155bf511dSas200622 static uint16_t smb_ace_len(smb_ace_t *); 10255bf511dSas200622 static uint32_t smb_ace_mask_g2s(uint32_t); 103c8ec8eeaSjose borrego static uint16_t smb_ace_flags_tozfs(uint8_t); 10455bf511dSas200622 static uint8_t smb_ace_flags_fromzfs(uint16_t); 105f96bd5c8SAlan Wright static boolean_t smb_ace_wellknown_update(const char *, ace_t *); 10655bf511dSas200622 10755bf511dSas200622 smb_acl_t * 10855bf511dSas200622 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt) 10955bf511dSas200622 { 11055bf511dSas200622 smb_acl_t *acl; 11155bf511dSas200622 int size; 11255bf511dSas200622 11355bf511dSas200622 size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t)); 11455bf511dSas200622 acl = kmem_zalloc(size, KM_SLEEP); 11555bf511dSas200622 acl->sl_revision = revision; 11655bf511dSas200622 acl->sl_bsize = bsize; 11755bf511dSas200622 acl->sl_acecnt = acecnt; 11855bf511dSas200622 acl->sl_aces = (smb_ace_t *)(acl + 1); 11955bf511dSas200622 12055bf511dSas200622 list_create(&acl->sl_sorted, sizeof (smb_ace_t), 12155bf511dSas200622 offsetof(smb_ace_t, se_sln)); 12255bf511dSas200622 return (acl); 12355bf511dSas200622 } 12455bf511dSas200622 12555bf511dSas200622 void 12655bf511dSas200622 smb_acl_free(smb_acl_t *acl) 12755bf511dSas200622 { 12855bf511dSas200622 int i, size; 12955bf511dSas200622 void *ace; 13055bf511dSas200622 13155bf511dSas200622 if (acl == NULL) 13255bf511dSas200622 return; 13355bf511dSas200622 1346537f381Sas200622 for (i = 0; i < acl->sl_acecnt; i++) 1356537f381Sas200622 smb_sid_free(acl->sl_aces[i].se_sid); 13655bf511dSas200622 13755bf511dSas200622 while ((ace = list_head(&acl->sl_sorted)) != NULL) 13855bf511dSas200622 list_remove(&acl->sl_sorted, ace); 13955bf511dSas200622 list_destroy(&acl->sl_sorted); 14055bf511dSas200622 14155bf511dSas200622 size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t)); 14255bf511dSas200622 kmem_free(acl, size); 14355bf511dSas200622 } 14455bf511dSas200622 14555bf511dSas200622 /* 14655bf511dSas200622 * smb_acl_len 14755bf511dSas200622 * 14855bf511dSas200622 * Returns the size of given ACL in bytes. Note that this 14955bf511dSas200622 * is not an in-memory size, it's the ACL's size as it would 15055bf511dSas200622 * appear on the wire 15155bf511dSas200622 */ 15255bf511dSas200622 uint16_t 15355bf511dSas200622 smb_acl_len(smb_acl_t *acl) 15455bf511dSas200622 { 155c8ec8eeaSjose borrego return ((acl) ? acl->sl_bsize : 0); 15655bf511dSas200622 } 15755bf511dSas200622 15855bf511dSas200622 boolean_t 15955bf511dSas200622 smb_acl_isvalid(smb_acl_t *acl, int which_acl) 16055bf511dSas200622 { 16155bf511dSas200622 int i; 16255bf511dSas200622 16355bf511dSas200622 if (acl->sl_bsize < SMB_ACL_HDRSIZE) 16455bf511dSas200622 return (B_FALSE); 16555bf511dSas200622 16655bf511dSas200622 if (acl->sl_revision != ACL_REVISION) { 16755bf511dSas200622 /* 16855bf511dSas200622 * we are rejecting ACLs with object-specific ACEs for now 16955bf511dSas200622 */ 17055bf511dSas200622 return (B_FALSE); 17155bf511dSas200622 } 17255bf511dSas200622 17355bf511dSas200622 for (i = 0; i < acl->sl_acecnt; i++) { 17455bf511dSas200622 if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl)) 17555bf511dSas200622 return (B_FALSE); 17655bf511dSas200622 } 17755bf511dSas200622 17855bf511dSas200622 return (B_TRUE); 17955bf511dSas200622 } 18055bf511dSas200622 18155bf511dSas200622 /* 18255bf511dSas200622 * smb_acl_sort 18355bf511dSas200622 * 18455bf511dSas200622 * Sorts the given ACL in place if it needs to be sorted. 185da6c28aaSamw * 186da6c28aaSamw * The following is an excerpt from MSDN website. 187da6c28aaSamw * 188da6c28aaSamw * Order of ACEs in a DACL 189da6c28aaSamw * 190da6c28aaSamw * For Windows NT versions 4.0 and earlier, the preferred order of ACEs 191da6c28aaSamw * is simple: In a DACL, all access-denied ACEs should precede any 192da6c28aaSamw * access-allowed ACEs. 193da6c28aaSamw * 194da6c28aaSamw * For Windows 2000 or later, the proper order of ACEs is more complicated 195da6c28aaSamw * because of the introduction of object-specific ACEs and automatic 196da6c28aaSamw * inheritance. 197da6c28aaSamw * 198da6c28aaSamw * The following describes the preferred order: 199da6c28aaSamw * 200da6c28aaSamw * To ensure that noninherited ACEs have precedence over inherited ACEs, 201da6c28aaSamw * place all noninherited ACEs in a group before any inherited ACEs. This 202da6c28aaSamw * ordering ensures, for example, that a noninherited access-denied ACE 203da6c28aaSamw * is enforced regardless of any inherited ACE that allows access. 204da6c28aaSamw * Within the groups of noninherited ACEs and inherited ACEs, order ACEs 205da6c28aaSamw * according to ACE type, as the following shows: 206da6c28aaSamw * . Access-denied ACEs that apply to the object itself 207da6c28aaSamw * . Access-denied ACEs that apply to a subobject of the 208da6c28aaSamw * object, such as a property set or property 209da6c28aaSamw * . Access-allowed ACEs that apply to the object itself 210da6c28aaSamw * . Access-allowed ACEs that apply to a subobject of the object 211da6c28aaSamw * 21255bf511dSas200622 * So, here is the desired ACE order 213da6c28aaSamw * 214da6c28aaSamw * deny-direct, allow-direct, deny-inherited, allow-inherited 215da6c28aaSamw * 21655bf511dSas200622 * Of course, not all ACE types are required in an ACL. 217da6c28aaSamw */ 21855bf511dSas200622 void 219da6c28aaSamw smb_acl_sort(smb_acl_t *acl) 220da6c28aaSamw { 221da6c28aaSamw list_t ace_grps[SMB_AG_NUM]; 22255bf511dSas200622 list_t *alist; 22355bf511dSas200622 smb_ace_t *ace; 224da6c28aaSamw uint8_t ace_flags; 22555bf511dSas200622 int ag, i; 226da6c28aaSamw 227da6c28aaSamw ASSERT(acl); 228da6c28aaSamw 229da6c28aaSamw if (acl->sl_acecnt == 0) { 230da6c28aaSamw /* 231da6c28aaSamw * ACL with no entry is a valid ACL and it means 232da6c28aaSamw * no access for anybody. 233da6c28aaSamw */ 23455bf511dSas200622 return; 235da6c28aaSamw } 236da6c28aaSamw 237da6c28aaSamw for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { 23855bf511dSas200622 list_create(&ace_grps[i], sizeof (smb_ace_t), 23955bf511dSas200622 offsetof(smb_ace_t, se_sln)); 240da6c28aaSamw } 241da6c28aaSamw 24255bf511dSas200622 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) { 24355bf511dSas200622 ace_flags = ace->se_hdr.se_flags; 244da6c28aaSamw 24555bf511dSas200622 switch (ace->se_hdr.se_type) { 246da6c28aaSamw case ACCESS_DENIED_ACE_TYPE: 24755bf511dSas200622 ag = (ace_flags & INHERITED_ACE) ? 24855bf511dSas200622 SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT; 249da6c28aaSamw break; 250da6c28aaSamw 251da6c28aaSamw case ACCESS_ALLOWED_ACE_TYPE: 25255bf511dSas200622 ag = (ace_flags & INHERITED_ACE) ? 25355bf511dSas200622 SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT; 254da6c28aaSamw break; 255da6c28aaSamw 256da6c28aaSamw default: 257da6c28aaSamw /* 258da6c28aaSamw * This is the lowest priority group so we put 259da6c28aaSamw * evertything unknown here. 260da6c28aaSamw */ 261da6c28aaSamw ag = SMB_AG_ALW_INHRT; 262da6c28aaSamw break; 263da6c28aaSamw } 264da6c28aaSamw 26555bf511dSas200622 /* Add the ACE to the selected group */ 26655bf511dSas200622 list_insert_tail(&ace_grps[ag], ace); 267da6c28aaSamw } 268da6c28aaSamw 26955bf511dSas200622 /* 27055bf511dSas200622 * start with highest priority ACE group and append 27155bf511dSas200622 * the ACEs to the ACL. 27255bf511dSas200622 */ 27355bf511dSas200622 for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { 27455bf511dSas200622 alist = &ace_grps[i]; 27555bf511dSas200622 while ((ace = list_head(alist)) != NULL) { 27655bf511dSas200622 list_remove(alist, ace); 27755bf511dSas200622 list_insert_tail(&acl->sl_sorted, ace); 27855bf511dSas200622 } 279da6c28aaSamw list_destroy(alist); 280da6c28aaSamw } 281da6c28aaSamw } 282da6c28aaSamw 283da6c28aaSamw /* 28455bf511dSas200622 * smb_acl_from_zfs 285da6c28aaSamw * 28655bf511dSas200622 * Converts given ZFS ACL to a Windows ACL. 287da6c28aaSamw * 28855bf511dSas200622 * A pointer to allocated memory for the Win ACL will be 28955bf511dSas200622 * returned upon successful conversion. 290da6c28aaSamw */ 29155bf511dSas200622 smb_acl_t * 292f96bd5c8SAlan Wright smb_acl_from_zfs(acl_t *zacl) 293da6c28aaSamw { 29455bf511dSas200622 ace_t *zace; 29555bf511dSas200622 int numaces; 29655bf511dSas200622 smb_acl_t *acl; 29755bf511dSas200622 smb_ace_t *ace; 29855bf511dSas200622 smb_idmap_batch_t sib; 29955bf511dSas200622 smb_idmap_t *sim; 30055bf511dSas200622 idmap_stat idm_stat; 301da6c28aaSamw 30255bf511dSas200622 idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, 30355bf511dSas200622 SMB_IDMAP_ID2SID); 30455bf511dSas200622 if (idm_stat != IDMAP_SUCCESS) 30555bf511dSas200622 return (NULL); 30655bf511dSas200622 307f96bd5c8SAlan Wright if (smb_fsacl_getsids(&sib, zacl) != IDMAP_SUCCESS) { 30855bf511dSas200622 smb_idmap_batch_destroy(&sib); 30955bf511dSas200622 return (NULL); 31055bf511dSas200622 } 31155bf511dSas200622 31255bf511dSas200622 acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt); 31355bf511dSas200622 31455bf511dSas200622 sim = sib.sib_maps; 31555bf511dSas200622 for (numaces = 0, zace = zacl->acl_aclp; 31655bf511dSas200622 numaces < zacl->acl_cnt; 31755bf511dSas200622 zace++, numaces++, sim++) { 31855bf511dSas200622 ASSERT(sim->sim_sid); 31955bf511dSas200622 if (sim->sim_sid == NULL) { 32055bf511dSas200622 smb_acl_free(acl); 32155bf511dSas200622 acl = NULL; 32255bf511dSas200622 break; 32355bf511dSas200622 } 32455bf511dSas200622 32555bf511dSas200622 ace = &acl->sl_aces[numaces]; 32655bf511dSas200622 ace->se_hdr.se_type = zace->a_type; 32755bf511dSas200622 ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags); 32855bf511dSas200622 ace->se_mask = zace->a_access_mask; 3296537f381Sas200622 ace->se_sid = smb_sid_dup(sim->sim_sid); 33055bf511dSas200622 ace->se_hdr.se_bsize = smb_ace_len(ace); 33155bf511dSas200622 33255bf511dSas200622 acl->sl_bsize += ace->se_hdr.se_bsize; 33355bf511dSas200622 } 33455bf511dSas200622 33555bf511dSas200622 smb_idmap_batch_destroy(&sib); 33655bf511dSas200622 return (acl); 337da6c28aaSamw } 338da6c28aaSamw 339da6c28aaSamw /* 34055bf511dSas200622 * smb_acl_to_zfs 341da6c28aaSamw * 34255bf511dSas200622 * Converts given Windows ACL to a ZFS ACL. 34355bf511dSas200622 * 34455bf511dSas200622 * fs_acl will contain a pointer to the created ZFS ACL. 34555bf511dSas200622 * The allocated memory should be freed by calling 34655bf511dSas200622 * smb_fsacl_free(). 34755bf511dSas200622 * 34855bf511dSas200622 * Since the output parameter, fs_acl, is allocated in this 34955bf511dSas200622 * function, the caller has to make sure *fs_acl is NULL which 35055bf511dSas200622 * means it's not pointing to any memory. 351da6c28aaSamw */ 352da6c28aaSamw uint32_t 35355bf511dSas200622 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) 354da6c28aaSamw { 35555bf511dSas200622 smb_ace_t *ace; 35655bf511dSas200622 acl_t *zacl; 35755bf511dSas200622 ace_t *zace; 35855bf511dSas200622 smb_idmap_batch_t sib; 35955bf511dSas200622 smb_idmap_t *sim; 36055bf511dSas200622 idmap_stat idm_stat; 361f96bd5c8SAlan Wright char *sidstr; 362c8ec8eeaSjose borrego int i; 363da6c28aaSamw 36455bf511dSas200622 ASSERT(fs_acl); 36555bf511dSas200622 ASSERT(*fs_acl == NULL); 36655bf511dSas200622 36755bf511dSas200622 if (acl && !smb_acl_isvalid(acl, which_acl)) 36855bf511dSas200622 return (NT_STATUS_INVALID_ACL); 36955bf511dSas200622 37055bf511dSas200622 if ((acl == NULL) || (acl->sl_acecnt == 0)) { 37155bf511dSas200622 if (which_acl == SMB_DACL_SECINFO) { 372c8ec8eeaSjose borrego *fs_acl = smb_fsacl_null_empty(acl == NULL); 373da6c28aaSamw } 374da6c28aaSamw 37555bf511dSas200622 return (NT_STATUS_SUCCESS); 376da6c28aaSamw } 377da6c28aaSamw 37855bf511dSas200622 idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, 37955bf511dSas200622 SMB_IDMAP_SID2ID); 38055bf511dSas200622 if (idm_stat != IDMAP_SUCCESS) 38155bf511dSas200622 return (NT_STATUS_INTERNAL_ERROR); 38255bf511dSas200622 383f96bd5c8SAlan Wright sidstr = kmem_alloc(SMB_SID_STRSZ, KM_SLEEP); 38455bf511dSas200622 zacl = smb_fsacl_alloc(acl->sl_acecnt, flags); 38555bf511dSas200622 38655bf511dSas200622 zace = zacl->acl_aclp; 38755bf511dSas200622 ace = acl->sl_aces; 38855bf511dSas200622 sim = sib.sib_maps; 38955bf511dSas200622 39055bf511dSas200622 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 39155bf511dSas200622 zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES; 39255bf511dSas200622 zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); 393c8ec8eeaSjose borrego zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags); 394f96bd5c8SAlan Wright zace->a_who = (uid_t)-1; 39555bf511dSas200622 396f96bd5c8SAlan Wright smb_sid_tostr(ace->se_sid, sidstr); 397f96bd5c8SAlan Wright 398f96bd5c8SAlan Wright if (!smb_ace_wellknown_update(sidstr, zace)) { 39955bf511dSas200622 sim->sim_id = &zace->a_who; 40055bf511dSas200622 idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, 401f96bd5c8SAlan Wright ace->se_sid, SMB_IDMAP_UNKNOWN); 40255bf511dSas200622 40355bf511dSas200622 if (idm_stat != IDMAP_SUCCESS) { 404f96bd5c8SAlan Wright kmem_free(sidstr, SMB_SID_STRSZ); 40555bf511dSas200622 smb_fsacl_free(zacl); 40655bf511dSas200622 smb_idmap_batch_destroy(&sib); 40755bf511dSas200622 return (NT_STATUS_INTERNAL_ERROR); 40855bf511dSas200622 } 40955bf511dSas200622 } 410da6c28aaSamw } 411da6c28aaSamw 412f96bd5c8SAlan Wright kmem_free(sidstr, SMB_SID_STRSZ); 413f96bd5c8SAlan Wright 41455bf511dSas200622 idm_stat = smb_idmap_batch_getmappings(&sib); 41555bf511dSas200622 if (idm_stat != IDMAP_SUCCESS) { 41655bf511dSas200622 smb_fsacl_free(zacl); 41755bf511dSas200622 smb_idmap_batch_destroy(&sib); 41855bf511dSas200622 return (NT_STATUS_NONE_MAPPED); 419da6c28aaSamw } 420da6c28aaSamw 42155bf511dSas200622 /* 42255bf511dSas200622 * Set the ACEs group flag based on the type of ID returned. 42355bf511dSas200622 */ 42455bf511dSas200622 zace = zacl->acl_aclp; 42555bf511dSas200622 ace = acl->sl_aces; 42655bf511dSas200622 sim = sib.sib_maps; 42755bf511dSas200622 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 428f96bd5c8SAlan Wright if (zace->a_who == (uid_t)-1) 42955bf511dSas200622 continue; 43055bf511dSas200622 43155bf511dSas200622 if (sim->sim_idtype == SMB_IDMAP_GROUP) 43255bf511dSas200622 zace->a_flags |= ACE_IDENTIFIER_GROUP; 43355bf511dSas200622 } 43455bf511dSas200622 43555bf511dSas200622 smb_idmap_batch_destroy(&sib); 43655bf511dSas200622 43755bf511dSas200622 *fs_acl = zacl; 43855bf511dSas200622 return (NT_STATUS_SUCCESS); 439da6c28aaSamw } 440da6c28aaSamw 441f96bd5c8SAlan Wright static boolean_t 442f96bd5c8SAlan Wright smb_ace_wellknown_update(const char *sid, ace_t *zace) 443f96bd5c8SAlan Wright { 444f96bd5c8SAlan Wright struct { 445f96bd5c8SAlan Wright char *sid; 446f96bd5c8SAlan Wright uint16_t flags; 447f96bd5c8SAlan Wright } map[] = { 448f96bd5c8SAlan Wright { NT_WORLD_SIDSTR, ACE_EVERYONE }, 449f96bd5c8SAlan Wright { NT_BUILTIN_CURRENT_OWNER_SIDSTR, ACE_OWNER }, 450f96bd5c8SAlan Wright { NT_BUILTIN_CURRENT_GROUP_SIDSTR, 451f96bd5c8SAlan Wright (ACE_GROUP | ACE_IDENTIFIER_GROUP) }, 452f96bd5c8SAlan Wright }; 453f96bd5c8SAlan Wright 454f96bd5c8SAlan Wright int i; 455f96bd5c8SAlan Wright 456f96bd5c8SAlan Wright for (i = 0; i < (sizeof (map) / sizeof (map[0])); ++i) { 457f96bd5c8SAlan Wright if (strcmp(sid, map[i].sid) == 0) { 458f96bd5c8SAlan Wright zace->a_flags |= map[i].flags; 459f96bd5c8SAlan Wright return (B_TRUE); 460f96bd5c8SAlan Wright } 461f96bd5c8SAlan Wright } 462f96bd5c8SAlan Wright 463f96bd5c8SAlan Wright return (B_FALSE); 464f96bd5c8SAlan Wright } 465f96bd5c8SAlan Wright 466da6c28aaSamw /* 467c8ec8eeaSjose borrego * smb_fsacl_getsids 468da6c28aaSamw * 469da6c28aaSamw * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs. 470da6c28aaSamw */ 471da6c28aaSamw static idmap_stat 472f96bd5c8SAlan Wright smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl) 473da6c28aaSamw { 474da6c28aaSamw ace_t *zace; 475da6c28aaSamw idmap_stat idm_stat; 476da6c28aaSamw smb_idmap_t *sim; 477*b819cea2SGordon Ross uid_t id = (uid_t)-1; 478da6c28aaSamw int i, idtype; 479da6c28aaSamw 480da6c28aaSamw sim = sib->sib_maps; 481da6c28aaSamw 482da6c28aaSamw for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; 483da6c28aaSamw zace++, i++, sim++) { 484da6c28aaSamw switch (zace->a_flags & ACE_TYPE_FLAGS) { 485da6c28aaSamw case ACE_OWNER: 486f96bd5c8SAlan Wright idtype = SMB_IDMAP_OWNERAT; 487da6c28aaSamw break; 488da6c28aaSamw 489da6c28aaSamw case (ACE_GROUP | ACE_IDENTIFIER_GROUP): 490da6c28aaSamw /* owning group */ 491f96bd5c8SAlan Wright idtype = SMB_IDMAP_GROUPAT; 492da6c28aaSamw break; 493da6c28aaSamw 494da6c28aaSamw case ACE_IDENTIFIER_GROUP: 495da6c28aaSamw /* regular group */ 496da6c28aaSamw id = zace->a_who; 497da6c28aaSamw idtype = SMB_IDMAP_GROUP; 498da6c28aaSamw break; 499da6c28aaSamw 500da6c28aaSamw case ACE_EVERYONE: 501da6c28aaSamw idtype = SMB_IDMAP_EVERYONE; 502da6c28aaSamw break; 503da6c28aaSamw 504da6c28aaSamw default: 505da6c28aaSamw /* user entry */ 506da6c28aaSamw id = zace->a_who; 507da6c28aaSamw idtype = SMB_IDMAP_USER; 508da6c28aaSamw } 509da6c28aaSamw 510da6c28aaSamw idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim, 511da6c28aaSamw id, idtype); 512da6c28aaSamw 513da6c28aaSamw if (idm_stat != IDMAP_SUCCESS) { 514da6c28aaSamw return (idm_stat); 515da6c28aaSamw } 516da6c28aaSamw } 517da6c28aaSamw 518da6c28aaSamw idm_stat = smb_idmap_batch_getmappings(sib); 519da6c28aaSamw return (idm_stat); 520da6c28aaSamw } 521da6c28aaSamw 522da6c28aaSamw /* 523c8ec8eeaSjose borrego * smb_fsacl_null_empty 524da6c28aaSamw * 525da6c28aaSamw * NULL DACL means everyone full-access 526da6c28aaSamw * Empty DACL means everyone full-deny 527da6c28aaSamw * 528da6c28aaSamw * ZFS ACL must have at least one entry so smb server has 529da6c28aaSamw * to simulate the aforementioned expected behavior by adding 530da6c28aaSamw * an entry in case the requested DACL is null or empty. Adding 531da6c28aaSamw * a everyone full-deny entry has proved to be problematic in 532da6c28aaSamw * tests since a deny entry takes precedence over allow entries. 533da6c28aaSamw * So, instead of adding a everyone full-deny, an owner ACE with 534da6c28aaSamw * owner implicit permissions will be set. 535da6c28aaSamw */ 53655bf511dSas200622 static acl_t * 537c8ec8eeaSjose borrego smb_fsacl_null_empty(boolean_t null) 538da6c28aaSamw { 539da6c28aaSamw acl_t *zacl; 540da6c28aaSamw ace_t *zace; 541da6c28aaSamw 54255bf511dSas200622 zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT); 543da6c28aaSamw zace = zacl->acl_aclp; 544da6c28aaSamw 545da6c28aaSamw zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 546da6c28aaSamw if (null) { 547da6c28aaSamw zace->a_access_mask = ACE_ALL_PERMS; 548da6c28aaSamw zace->a_flags = ACE_EVERYONE; 549da6c28aaSamw } else { 550da6c28aaSamw zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | 551da6c28aaSamw ACE_READ_ATTRIBUTES; 552da6c28aaSamw zace->a_flags = ACE_OWNER; 553da6c28aaSamw } 554da6c28aaSamw 555da6c28aaSamw return (zacl); 556da6c28aaSamw } 557da6c28aaSamw 558da6c28aaSamw /* 55955bf511dSas200622 * FS ACL (acl_t) Functions 560da6c28aaSamw */ 56155bf511dSas200622 acl_t * 56255bf511dSas200622 smb_fsacl_alloc(int acenum, int flags) 563da6c28aaSamw { 56455bf511dSas200622 acl_t *acl; 565da6c28aaSamw 56655bf511dSas200622 acl = acl_alloc(ACE_T); 56755bf511dSas200622 acl->acl_cnt = acenum; 56855bf511dSas200622 acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP); 56955bf511dSas200622 acl->acl_flags = flags; 57055bf511dSas200622 return (acl); 571da6c28aaSamw } 572da6c28aaSamw 57355bf511dSas200622 void 57455bf511dSas200622 smb_fsacl_free(acl_t *acl) 575da6c28aaSamw { 57655bf511dSas200622 if (acl) 57755bf511dSas200622 acl_free(acl); 578da6c28aaSamw } 579da6c28aaSamw 580da6c28aaSamw /* 58155bf511dSas200622 * smb_fsop_aclmerge 582da6c28aaSamw * 58355bf511dSas200622 * smb_fsop_aclread/write routines which interact with filesystem 58455bf511dSas200622 * work with single ACL. This routine merges given DACL and SACL 58555bf511dSas200622 * which might have been created during CIFS to FS conversion into 58655bf511dSas200622 * one single ACL. 58755bf511dSas200622 */ 58855bf511dSas200622 acl_t * 58955bf511dSas200622 smb_fsacl_merge(acl_t *dacl, acl_t *sacl) 59055bf511dSas200622 { 59155bf511dSas200622 acl_t *acl; 59255bf511dSas200622 int dacl_size; 59355bf511dSas200622 59455bf511dSas200622 ASSERT(dacl); 59555bf511dSas200622 ASSERT(sacl); 59655bf511dSas200622 59755bf511dSas200622 acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags); 59855bf511dSas200622 dacl_size = dacl->acl_cnt * dacl->acl_entry_size; 59955bf511dSas200622 bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size); 60055bf511dSas200622 bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size, 60155bf511dSas200622 sacl->acl_cnt * sacl->acl_entry_size); 60255bf511dSas200622 60355bf511dSas200622 return (acl); 60455bf511dSas200622 } 60555bf511dSas200622 60655bf511dSas200622 /* 60755bf511dSas200622 * smb_fsacl_split 60855bf511dSas200622 * 60955bf511dSas200622 * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on 61055bf511dSas200622 * the 'which_acl' parameter. Note that output dacl/sacl parameters could be 61155bf511dSas200622 * NULL even if they're specified in 'which_acl', which means the target 61255bf511dSas200622 * doesn't have any access and/or audit ACEs. 61355bf511dSas200622 */ 61455bf511dSas200622 void 61555bf511dSas200622 smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl) 61655bf511dSas200622 { 61755bf511dSas200622 ace_t *zace; 618*b819cea2SGordon Ross ace_t *access_ace = NULL; 619*b819cea2SGordon Ross ace_t *audit_ace = NULL; 62055bf511dSas200622 int naccess, naudit; 62155bf511dSas200622 int get_dacl, get_sacl; 62255bf511dSas200622 int i; 62355bf511dSas200622 62455bf511dSas200622 *dacl = *sacl = NULL; 62555bf511dSas200622 naccess = naudit = 0; 62655bf511dSas200622 get_dacl = (which_acl & SMB_DACL_SECINFO); 62755bf511dSas200622 get_sacl = (which_acl & SMB_SACL_SECINFO); 62855bf511dSas200622 62955bf511dSas200622 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { 63055bf511dSas200622 if (get_dacl && smb_ace_is_access(zace->a_type)) 63155bf511dSas200622 naccess++; 63255bf511dSas200622 else if (get_sacl && smb_ace_is_audit(zace->a_type)) 63355bf511dSas200622 naudit++; 63455bf511dSas200622 } 63555bf511dSas200622 63655bf511dSas200622 if (naccess) { 63755bf511dSas200622 *dacl = smb_fsacl_alloc(naccess, zacl->acl_flags); 63855bf511dSas200622 access_ace = (*dacl)->acl_aclp; 63955bf511dSas200622 } 64055bf511dSas200622 64155bf511dSas200622 if (naudit) { 64255bf511dSas200622 *sacl = smb_fsacl_alloc(naudit, zacl->acl_flags); 64355bf511dSas200622 audit_ace = (*sacl)->acl_aclp; 64455bf511dSas200622 } 64555bf511dSas200622 64655bf511dSas200622 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { 64755bf511dSas200622 if (get_dacl && smb_ace_is_access(zace->a_type)) { 64855bf511dSas200622 *access_ace = *zace; 64955bf511dSas200622 access_ace++; 65055bf511dSas200622 } else if (get_sacl && smb_ace_is_audit(zace->a_type)) { 65155bf511dSas200622 *audit_ace = *zace; 65255bf511dSas200622 audit_ace++; 65355bf511dSas200622 } 65455bf511dSas200622 } 65555bf511dSas200622 } 65655bf511dSas200622 65755bf511dSas200622 /* 65855bf511dSas200622 * ACE Inheritance Rules 65955bf511dSas200622 * 66055bf511dSas200622 * The system propagates inheritable ACEs to child objects according to a 66155bf511dSas200622 * set of inheritance rules. The system places inherited ACEs in the child's 66255bf511dSas200622 * DACL according to the preferred order of ACEs in a DACL. For Windows 66355bf511dSas200622 * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs. 66455bf511dSas200622 * 66555bf511dSas200622 * The following table shows the ACEs inherited by container and noncontainer 66655bf511dSas200622 * child objects for different combinations of inheritance flags. These 66755bf511dSas200622 * inheritance rules work the same for both DACLs and SACLs. 66855bf511dSas200622 * 66955bf511dSas200622 * Parent ACE type Effect on Child ACL 67055bf511dSas200622 * ----------------------- ------------------- 67155bf511dSas200622 * OBJECT_INHERIT_ACE only Noncontainer child objects: 67255bf511dSas200622 * Inherited as an effective ACE. 67355bf511dSas200622 * Container child objects: 67455bf511dSas200622 * Containers inherit an inherit-only ACE 67555bf511dSas200622 * unless the NO_PROPAGATE_INHERIT_ACE bit 676da6c28aaSamw * flag is also set. 677da6c28aaSamw * 67855bf511dSas200622 * CONTAINER_INHERIT_ACE only Noncontainer child objects: 67955bf511dSas200622 * No effect on the child object. 68055bf511dSas200622 * Container child objects: 68155bf511dSas200622 * The child object inherits an effective ACE. 682da6c28aaSamw * The inherited ACE is inheritable unless the 68355bf511dSas200622 * NO_PROPAGATE_INHERIT_ACE bit flag is also set. 68455bf511dSas200622 * 68555bf511dSas200622 * CONTAINER_INHERIT_ACE and 68655bf511dSas200622 * OBJECT_INHERIT_ACE Noncontainer child objects: 68755bf511dSas200622 * Inherited as an effective ACE. 68855bf511dSas200622 * Container child objects: 68955bf511dSas200622 * The child object inherits an effective ACE. 69055bf511dSas200622 * The inherited ACE is inheritable unless the 69155bf511dSas200622 * NO_PROPAGATE_INHERIT_ACE bit flag is also set 69255bf511dSas200622 * 69355bf511dSas200622 * No inheritance flags set No effect on child container or noncontainer 69455bf511dSas200622 * objects. 69555bf511dSas200622 * 69655bf511dSas200622 * If an inherited ACE is an effective ACE for the child object, the system 69755bf511dSas200622 * maps any generic rights to the specific rights for the child object. 69855bf511dSas200622 * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the 69955bf511dSas200622 * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic 70055bf511dSas200622 * rights or generic SIDs are left unchanged so that they can be mapped 70155bf511dSas200622 * appropriately when the ACE is inherited by the next generation of child 70255bf511dSas200622 * objects. 70355bf511dSas200622 * 70455bf511dSas200622 * For a case in which a container object inherits an ACE that is both 70555bf511dSas200622 * effective on the container and inheritable by its descendants, the 70655bf511dSas200622 * container may inherit two ACEs. This occurs if the inheritable ACE 70755bf511dSas200622 * contains generic information. The container inherits an inherit-only 70855bf511dSas200622 * ACE containing the generic information and an effective-only ACE in 70955bf511dSas200622 * which the generic information has been mapped. 710da6c28aaSamw */ 711da6c28aaSamw 712*b819cea2SGordon Ross #ifdef _KERNEL 713da6c28aaSamw /* 71455bf511dSas200622 * smb_fsacl_inherit 715da6c28aaSamw * 716da6c28aaSamw * Manufacture the inherited ACL from the given ACL considering 717da6c28aaSamw * the new object type (file/dir) specified by 'is_dir'. The 718da6c28aaSamw * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions. 71955bf511dSas200622 * This function implements Windows inheritance rules explained above. 720da6c28aaSamw * 72155bf511dSas200622 * Note that the in/out ACLs are ZFS ACLs not Windows ACLs 722da6c28aaSamw */ 723da6c28aaSamw acl_t * 7249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, cred_t *cr) 725da6c28aaSamw { 726da6c28aaSamw boolean_t use_default = B_FALSE; 727da6c28aaSamw int num_inheritable = 0; 728da6c28aaSamw int numaces; 729da6c28aaSamw ace_t *dir_zace; 730da6c28aaSamw acl_t *new_zacl; 731da6c28aaSamw ace_t *new_zace; 7329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ksid_t *owner_sid; 7339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ksid_t *group_sid; 7349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uid_t uid; 7359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States gid_t gid; 7369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 7379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States owner_sid = crgetsid(cr, KSID_OWNER); 7389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States group_sid = crgetsid(cr, KSID_GROUP); 7399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(owner_sid); 7409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(group_sid); 7419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uid = owner_sid->ks_id; 7429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States gid = group_sid->ks_id; 743da6c28aaSamw 74455bf511dSas200622 num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir); 745da6c28aaSamw 746da6c28aaSamw if (num_inheritable == 0) { 747da6c28aaSamw if (which_acl == SMB_DACL_SECINFO) { 748da6c28aaSamw /* No inheritable access ACEs -> default DACL */ 749da6c28aaSamw num_inheritable = DEFAULT_DACL_ACENUM; 750da6c28aaSamw use_default = B_TRUE; 751da6c28aaSamw } else { 752da6c28aaSamw return (NULL); 753da6c28aaSamw } 754da6c28aaSamw } 755da6c28aaSamw 75655bf511dSas200622 new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT); 757da6c28aaSamw new_zace = new_zacl->acl_aclp; 758da6c28aaSamw 759da6c28aaSamw if (use_default) { 760da6c28aaSamw bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl)); 7619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States new_zace->a_who = uid; 762da6c28aaSamw return (new_zacl); 763da6c28aaSamw } 764da6c28aaSamw 765da6c28aaSamw for (numaces = 0, dir_zace = dir_zacl->acl_aclp; 766da6c28aaSamw numaces < dir_zacl->acl_cnt; 767da6c28aaSamw dir_zace++, numaces++) { 768da6c28aaSamw switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) { 769da6c28aaSamw case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 770da6c28aaSamw /* 771da6c28aaSamw * Files inherit an effective ACE. 772da6c28aaSamw * 773da6c28aaSamw * Dirs inherit an effective ACE. 774da6c28aaSamw * The inherited ACE is inheritable unless the 775da6c28aaSamw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 776da6c28aaSamw */ 7779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid); 778da6c28aaSamw new_zace++; 779da6c28aaSamw 780da6c28aaSamw if (is_dir && ZACE_IS_CREATOR(dir_zace) && 781da6c28aaSamw (ZACE_IS_PROPAGATE(dir_zace))) { 782da6c28aaSamw *new_zace = *dir_zace; 783da6c28aaSamw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 784da6c28aaSamw ACE_INHERITED_ACE); 785da6c28aaSamw new_zace++; 786da6c28aaSamw } 787da6c28aaSamw break; 788da6c28aaSamw 789da6c28aaSamw case ACE_FILE_INHERIT_ACE: 790da6c28aaSamw /* 791da6c28aaSamw * Files inherit as an effective ACE. 792da6c28aaSamw * 793da6c28aaSamw * Dirs inherit an inherit-only ACE 794da6c28aaSamw * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 795da6c28aaSamw * flag is also set. 796da6c28aaSamw */ 797da6c28aaSamw if (is_dir == 0) { 7989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_ace_inherit(dir_zace, new_zace, is_dir, 7999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uid, gid); 800da6c28aaSamw new_zace++; 801da6c28aaSamw } else if (ZACE_IS_PROPAGATE(dir_zace)) { 802da6c28aaSamw *new_zace = *dir_zace; 803da6c28aaSamw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 804da6c28aaSamw ACE_INHERITED_ACE); 805da6c28aaSamw new_zace++; 806da6c28aaSamw } 807da6c28aaSamw break; 808da6c28aaSamw 809da6c28aaSamw case ACE_DIRECTORY_INHERIT_ACE: 810da6c28aaSamw /* 811da6c28aaSamw * No effect on files 812da6c28aaSamw * 813da6c28aaSamw * Dirs inherit an effective ACE. 814da6c28aaSamw * The inherited ACE is inheritable unless the 815da6c28aaSamw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 816da6c28aaSamw */ 817da6c28aaSamw if (is_dir == 0) 818da6c28aaSamw break; 819da6c28aaSamw 8209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid); 821da6c28aaSamw new_zace++; 822da6c28aaSamw 823da6c28aaSamw if (ZACE_IS_CREATOR(dir_zace) && 824da6c28aaSamw (ZACE_IS_PROPAGATE(dir_zace))) { 825da6c28aaSamw *new_zace = *dir_zace; 826da6c28aaSamw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 827da6c28aaSamw ACE_INHERITED_ACE); 828da6c28aaSamw new_zace++; 829da6c28aaSamw } 830da6c28aaSamw 831da6c28aaSamw break; 832da6c28aaSamw 833da6c28aaSamw default: 834da6c28aaSamw break; 835da6c28aaSamw } 836da6c28aaSamw } 837da6c28aaSamw 838da6c28aaSamw return (new_zacl); 839da6c28aaSamw } 840*b819cea2SGordon Ross #endif /* _KERNEL */ 841da6c28aaSamw 84255bf511dSas200622 /* 84355bf511dSas200622 * smb_fsacl_from_vsa 84455bf511dSas200622 * 84555bf511dSas200622 * Converts given vsecattr_t structure to a acl_t structure. 84655bf511dSas200622 * 84755bf511dSas200622 * The allocated memory for retuned acl_t should be freed by 84855bf511dSas200622 * calling acl_free(). 84955bf511dSas200622 */ 85055bf511dSas200622 acl_t * 85155bf511dSas200622 smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type) 85255bf511dSas200622 { 85355bf511dSas200622 int aclbsize = 0; /* size of acl list in bytes */ 85455bf511dSas200622 int dfaclbsize = 0; /* size of default acl list in bytes */ 85555bf511dSas200622 int numacls; 85655bf511dSas200622 acl_t *acl_info; 85755bf511dSas200622 85855bf511dSas200622 ASSERT(vsecattr); 85955bf511dSas200622 86055bf511dSas200622 acl_info = acl_alloc(acl_type); 86155bf511dSas200622 if (acl_info == NULL) 86255bf511dSas200622 return (NULL); 86355bf511dSas200622 86455bf511dSas200622 acl_info->acl_flags = 0; 86555bf511dSas200622 86655bf511dSas200622 switch (acl_type) { 86755bf511dSas200622 86855bf511dSas200622 case ACLENT_T: 86955bf511dSas200622 numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt; 87055bf511dSas200622 aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t); 87155bf511dSas200622 dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t); 87255bf511dSas200622 87355bf511dSas200622 acl_info->acl_cnt = numacls; 87455bf511dSas200622 acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize, 87555bf511dSas200622 KM_SLEEP); 87655bf511dSas200622 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, 87755bf511dSas200622 aclbsize); 87855bf511dSas200622 (void) memcpy((char *)acl_info->acl_aclp + aclbsize, 87955bf511dSas200622 vsecattr->vsa_dfaclentp, dfaclbsize); 88055bf511dSas200622 88155bf511dSas200622 if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) 88255bf511dSas200622 acl_info->acl_flags |= ACL_IS_TRIVIAL; 88355bf511dSas200622 88455bf511dSas200622 break; 88555bf511dSas200622 88655bf511dSas200622 case ACE_T: 88755bf511dSas200622 aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); 88855bf511dSas200622 acl_info->acl_cnt = vsecattr->vsa_aclcnt; 88955bf511dSas200622 acl_info->acl_flags = vsecattr->vsa_aclflags; 89055bf511dSas200622 acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP); 89155bf511dSas200622 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, 89255bf511dSas200622 aclbsize); 89355bf511dSas200622 if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) 89455bf511dSas200622 acl_info->acl_flags |= ACL_IS_TRIVIAL; 89555bf511dSas200622 89655bf511dSas200622 break; 89755bf511dSas200622 89855bf511dSas200622 default: 89955bf511dSas200622 acl_free(acl_info); 90055bf511dSas200622 return (NULL); 90155bf511dSas200622 } 90255bf511dSas200622 90355bf511dSas200622 if (aclbsize && vsecattr->vsa_aclentp) 90455bf511dSas200622 kmem_free(vsecattr->vsa_aclentp, aclbsize); 90555bf511dSas200622 if (dfaclbsize && vsecattr->vsa_dfaclentp) 90655bf511dSas200622 kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize); 90755bf511dSas200622 90855bf511dSas200622 return (acl_info); 90955bf511dSas200622 } 91055bf511dSas200622 91155bf511dSas200622 /* 91255bf511dSas200622 * smb_fsacl_to_vsa 91355bf511dSas200622 * 91455bf511dSas200622 * Converts given acl_t structure to a vsecattr_t structure. 91555bf511dSas200622 * 91655bf511dSas200622 * IMPORTANT: 91755bf511dSas200622 * Upon successful return the memory allocated for vsa_aclentp 91855bf511dSas200622 * should be freed by calling kmem_free(). The size is returned 91955bf511dSas200622 * in aclbsize. 92055bf511dSas200622 */ 92155bf511dSas200622 int 92255bf511dSas200622 smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize) 92355bf511dSas200622 { 92455bf511dSas200622 int error = 0; 92555bf511dSas200622 int numacls; 92655bf511dSas200622 aclent_t *aclp; 92755bf511dSas200622 92855bf511dSas200622 ASSERT(acl_info); 92955bf511dSas200622 ASSERT(vsecattr); 93055bf511dSas200622 ASSERT(aclbsize); 93155bf511dSas200622 93255bf511dSas200622 bzero(vsecattr, sizeof (vsecattr_t)); 93355bf511dSas200622 *aclbsize = 0; 93455bf511dSas200622 93555bf511dSas200622 switch (acl_info->acl_type) { 93655bf511dSas200622 case ACLENT_T: 93755bf511dSas200622 numacls = acl_info->acl_cnt; 93855bf511dSas200622 /* 93955bf511dSas200622 * Minimum ACL size is three entries so might as well 94055bf511dSas200622 * bail out here. Also limit request size to prevent user 94155bf511dSas200622 * from allocating too much kernel memory. Maximum size 94255bf511dSas200622 * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES 94355bf511dSas200622 * for the default ACL part. 94455bf511dSas200622 */ 94555bf511dSas200622 if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) { 94655bf511dSas200622 error = EINVAL; 94755bf511dSas200622 break; 94855bf511dSas200622 } 94955bf511dSas200622 95055bf511dSas200622 vsecattr->vsa_mask = VSA_ACL; 95155bf511dSas200622 95255bf511dSas200622 vsecattr->vsa_aclcnt = numacls; 95355bf511dSas200622 *aclbsize = numacls * sizeof (aclent_t); 95455bf511dSas200622 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); 95555bf511dSas200622 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, 95655bf511dSas200622 *aclbsize); 95755bf511dSas200622 95855bf511dSas200622 /* Sort the acl list */ 95955bf511dSas200622 ksort((caddr_t)vsecattr->vsa_aclentp, 96055bf511dSas200622 vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls); 96155bf511dSas200622 96255bf511dSas200622 /* Break into acl and default acl lists */ 96355bf511dSas200622 for (numacls = 0, aclp = vsecattr->vsa_aclentp; 96455bf511dSas200622 numacls < vsecattr->vsa_aclcnt; 96555bf511dSas200622 aclp++, numacls++) { 96655bf511dSas200622 if (aclp->a_type & ACL_DEFAULT) 96755bf511dSas200622 break; 96855bf511dSas200622 } 96955bf511dSas200622 97055bf511dSas200622 /* Find where defaults start (if any) */ 97155bf511dSas200622 if (numacls < vsecattr->vsa_aclcnt) { 97255bf511dSas200622 vsecattr->vsa_mask |= VSA_DFACL; 97355bf511dSas200622 vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls; 97455bf511dSas200622 vsecattr->vsa_dfaclentp = aclp; 97555bf511dSas200622 vsecattr->vsa_aclcnt = numacls; 97655bf511dSas200622 } 97755bf511dSas200622 97855bf511dSas200622 /* Adjust if they're all defaults */ 97955bf511dSas200622 if (vsecattr->vsa_aclcnt == 0) { 98055bf511dSas200622 vsecattr->vsa_mask &= ~VSA_ACL; 98155bf511dSas200622 vsecattr->vsa_aclentp = NULL; 98255bf511dSas200622 } 98355bf511dSas200622 98455bf511dSas200622 /* Only directories can have defaults */ 98555bf511dSas200622 if (vsecattr->vsa_dfaclcnt && 98655bf511dSas200622 (acl_info->acl_flags & ACL_IS_DIR)) { 98755bf511dSas200622 error = ENOTDIR; 98855bf511dSas200622 } 98955bf511dSas200622 99055bf511dSas200622 break; 99155bf511dSas200622 99255bf511dSas200622 case ACE_T: 99355bf511dSas200622 if (acl_info->acl_cnt < 1 || 99455bf511dSas200622 acl_info->acl_cnt > MAX_ACL_ENTRIES) { 99555bf511dSas200622 error = EINVAL; 99655bf511dSas200622 break; 99755bf511dSas200622 } 99855bf511dSas200622 99955bf511dSas200622 vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 100055bf511dSas200622 vsecattr->vsa_aclcnt = acl_info->acl_cnt; 100155bf511dSas200622 vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL; 100255bf511dSas200622 *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); 100355bf511dSas200622 vsecattr->vsa_aclentsz = *aclbsize; 100455bf511dSas200622 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); 100555bf511dSas200622 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, 100655bf511dSas200622 *aclbsize); 100755bf511dSas200622 100855bf511dSas200622 break; 100955bf511dSas200622 101055bf511dSas200622 default: 101155bf511dSas200622 error = EINVAL; 101255bf511dSas200622 } 101355bf511dSas200622 101455bf511dSas200622 return (error); 101555bf511dSas200622 } 101655bf511dSas200622 1017*b819cea2SGordon Ross #ifdef _KERNEL 101855bf511dSas200622 /* 101955bf511dSas200622 * smb_fsacl_inheritable 102055bf511dSas200622 * 102155bf511dSas200622 * Checks to see if there are any inheritable ACEs in the 102255bf511dSas200622 * given ZFS ACL. Returns the number of inheritable ACEs. 102355bf511dSas200622 * 102455bf511dSas200622 * The inherited ACL could be different based on the type of 102555bf511dSas200622 * new object (file/dir) specified by 'is_dir'. 102655bf511dSas200622 * 102755bf511dSas200622 * Note that the input ACL is a ZFS ACL not Windows ACL. 102855bf511dSas200622 */ 102955bf511dSas200622 static int 103055bf511dSas200622 smb_fsacl_inheritable(acl_t *zacl, int is_dir) 103155bf511dSas200622 { 103255bf511dSas200622 int numaces; 103355bf511dSas200622 int num_inheritable = 0; 103455bf511dSas200622 ace_t *zace; 103555bf511dSas200622 103655bf511dSas200622 if (zacl == NULL) 103755bf511dSas200622 return (0); 103855bf511dSas200622 103955bf511dSas200622 for (numaces = 0, zace = zacl->acl_aclp; 104055bf511dSas200622 numaces < zacl->acl_cnt; 104155bf511dSas200622 zace++, numaces++) { 104255bf511dSas200622 switch (zace->a_flags & ACE_FD_INHERIT_ACE) { 104355bf511dSas200622 case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 104455bf511dSas200622 /* 104555bf511dSas200622 * Files inherit an effective ACE. 104655bf511dSas200622 * 104755bf511dSas200622 * Dirs inherit an effective ACE. 104855bf511dSas200622 * The inherited ACE is inheritable unless the 104955bf511dSas200622 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 105055bf511dSas200622 */ 105155bf511dSas200622 num_inheritable++; 105255bf511dSas200622 105355bf511dSas200622 if (is_dir && ZACE_IS_CREATOR(zace) && 105455bf511dSas200622 (ZACE_IS_PROPAGATE(zace))) { 105555bf511dSas200622 num_inheritable++; 105655bf511dSas200622 } 105755bf511dSas200622 break; 105855bf511dSas200622 105955bf511dSas200622 case ACE_FILE_INHERIT_ACE: 106055bf511dSas200622 /* 106155bf511dSas200622 * Files inherit as an effective ACE. 106255bf511dSas200622 * 106355bf511dSas200622 * Dirs inherit an inherit-only ACE 106455bf511dSas200622 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 106555bf511dSas200622 * flag is also set. 106655bf511dSas200622 */ 106755bf511dSas200622 if (is_dir == 0) 106855bf511dSas200622 num_inheritable++; 106955bf511dSas200622 else if (ZACE_IS_PROPAGATE(zace)) 107055bf511dSas200622 num_inheritable++; 107155bf511dSas200622 break; 107255bf511dSas200622 107355bf511dSas200622 case ACE_DIRECTORY_INHERIT_ACE: 107455bf511dSas200622 /* 107555bf511dSas200622 * No effect on files 107655bf511dSas200622 * 107755bf511dSas200622 * Dirs inherit an effective ACE. 107855bf511dSas200622 * The inherited ACE is inheritable unless the 107955bf511dSas200622 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 108055bf511dSas200622 */ 108155bf511dSas200622 if (is_dir == 0) 108255bf511dSas200622 break; 108355bf511dSas200622 108455bf511dSas200622 num_inheritable++; 108555bf511dSas200622 108655bf511dSas200622 if (ZACE_IS_CREATOR(zace) && 108755bf511dSas200622 (ZACE_IS_PROPAGATE(zace))) 108855bf511dSas200622 num_inheritable++; 108955bf511dSas200622 break; 109055bf511dSas200622 109155bf511dSas200622 default: 109255bf511dSas200622 break; 109355bf511dSas200622 } 109455bf511dSas200622 } 109555bf511dSas200622 109655bf511dSas200622 return (num_inheritable); 109755bf511dSas200622 } 1098*b819cea2SGordon Ross #endif /* _KERNEL */ 109955bf511dSas200622 110055bf511dSas200622 110155bf511dSas200622 /* 110255bf511dSas200622 * ACE Functions 110355bf511dSas200622 */ 110455bf511dSas200622 110555bf511dSas200622 /* 110655bf511dSas200622 * This is generic (ACL version 2) vs. object-specific 110755bf511dSas200622 * (ACL version 4) ACE types. 110855bf511dSas200622 */ 110955bf511dSas200622 boolean_t 111055bf511dSas200622 smb_ace_is_generic(int type) 111155bf511dSas200622 { 111255bf511dSas200622 switch (type) { 111355bf511dSas200622 case ACE_ACCESS_ALLOWED_ACE_TYPE: 111455bf511dSas200622 case ACE_ACCESS_DENIED_ACE_TYPE: 111555bf511dSas200622 case ACE_SYSTEM_AUDIT_ACE_TYPE: 111655bf511dSas200622 case ACE_SYSTEM_ALARM_ACE_TYPE: 111755bf511dSas200622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 111855bf511dSas200622 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 111955bf511dSas200622 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 112055bf511dSas200622 case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE: 112155bf511dSas200622 return (B_TRUE); 112255bf511dSas200622 112355bf511dSas200622 default: 112455bf511dSas200622 break; 112555bf511dSas200622 } 112655bf511dSas200622 112755bf511dSas200622 return (B_FALSE); 112855bf511dSas200622 } 112955bf511dSas200622 113055bf511dSas200622 boolean_t 113155bf511dSas200622 smb_ace_is_access(int type) 113255bf511dSas200622 { 113355bf511dSas200622 switch (type) { 113455bf511dSas200622 case ACE_ACCESS_ALLOWED_ACE_TYPE: 113555bf511dSas200622 case ACE_ACCESS_DENIED_ACE_TYPE: 113655bf511dSas200622 case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: 113755bf511dSas200622 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 113855bf511dSas200622 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 113955bf511dSas200622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 114055bf511dSas200622 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 114155bf511dSas200622 case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 114255bf511dSas200622 case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 114355bf511dSas200622 return (B_TRUE); 114455bf511dSas200622 114555bf511dSas200622 default: 114655bf511dSas200622 break; 114755bf511dSas200622 } 114855bf511dSas200622 114955bf511dSas200622 return (B_FALSE); 115055bf511dSas200622 } 115155bf511dSas200622 115255bf511dSas200622 boolean_t 115355bf511dSas200622 smb_ace_is_audit(int type) 115455bf511dSas200622 { 115555bf511dSas200622 switch (type) { 115655bf511dSas200622 case ACE_SYSTEM_AUDIT_ACE_TYPE: 115755bf511dSas200622 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 115855bf511dSas200622 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 115955bf511dSas200622 case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 116055bf511dSas200622 return (B_TRUE); 116155bf511dSas200622 116255bf511dSas200622 default: 116355bf511dSas200622 break; 116455bf511dSas200622 } 116555bf511dSas200622 116655bf511dSas200622 return (B_FALSE); 116755bf511dSas200622 } 116855bf511dSas200622 116955bf511dSas200622 /* 117055bf511dSas200622 * smb_ace_len 117155bf511dSas200622 * 117255bf511dSas200622 * Returns the length of the given ACE as it appears in an 117355bf511dSas200622 * ACL on the wire (i.e. a flat buffer which contains the SID) 117455bf511dSas200622 */ 117555bf511dSas200622 static uint16_t 117655bf511dSas200622 smb_ace_len(smb_ace_t *ace) 117755bf511dSas200622 { 117855bf511dSas200622 ASSERT(ace); 117955bf511dSas200622 ASSERT(ace->se_sid); 118055bf511dSas200622 118155bf511dSas200622 if (ace == NULL) 118255bf511dSas200622 return (0); 118355bf511dSas200622 118455bf511dSas200622 return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) + 11856537f381Sas200622 smb_sid_len(ace->se_sid)); 118655bf511dSas200622 } 118755bf511dSas200622 1188*b819cea2SGordon Ross #ifdef _KERNEL 1189da6c28aaSamw static void 11909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir, uid_t uid, gid_t gid) 1191da6c28aaSamw { 1192da6c28aaSamw *zace = *dir_zace; 1193c8ec8eeaSjose borrego 1194c8ec8eeaSjose borrego /* This is an effective ACE so remove the inherit_only flag */ 1195c8ec8eeaSjose borrego zace->a_flags &= ~ACE_INHERIT_ONLY_ACE; 1196c8ec8eeaSjose borrego /* Mark this ACE as inherited */ 1197da6c28aaSamw zace->a_flags |= ACE_INHERITED_ACE; 1198da6c28aaSamw 1199da6c28aaSamw /* 1200c8ec8eeaSjose borrego * If this is a file or NO_PROPAGATE is set then this inherited 1201c8ec8eeaSjose borrego * ACE is not inheritable so clear the inheritance flags 1202c8ec8eeaSjose borrego */ 1203c8ec8eeaSjose borrego if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace))) 1204c8ec8eeaSjose borrego zace->a_flags &= ~ACE_INHERIT_FLAGS; 1205c8ec8eeaSjose borrego 1206c8ec8eeaSjose borrego /* 1207c8ec8eeaSjose borrego * Replace creator owner/group ACEs with actual owner/group ACEs. 12089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * This is a non-inheritable effective ACE. 1209da6c28aaSamw */ 1210da6c28aaSamw if (ZACE_IS_CREATOR_OWNER(dir_zace)) { 12119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States zace->a_who = uid; 1212c8ec8eeaSjose borrego zace->a_flags &= ~ACE_INHERIT_FLAGS; 1213da6c28aaSamw } else if (ZACE_IS_CREATOR_GROUP(dir_zace)) { 12149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States zace->a_who = gid; 12159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States zace->a_flags |= ACE_IDENTIFIER_GROUP; 1216c8ec8eeaSjose borrego zace->a_flags &= ~ACE_INHERIT_FLAGS; 1217da6c28aaSamw } 1218da6c28aaSamw } 1219*b819cea2SGordon Ross #endif /* _KERNEL */ 1220da6c28aaSamw 122155bf511dSas200622 /* 122255bf511dSas200622 * smb_ace_mask_g2s 122355bf511dSas200622 * 122455bf511dSas200622 * Converts generic access bits in the given mask (if any) 122555bf511dSas200622 * to file specific bits. Generic access masks shouldn't be 122655bf511dSas200622 * stored in filesystem ACEs. 122755bf511dSas200622 */ 122855bf511dSas200622 static uint32_t 122955bf511dSas200622 smb_ace_mask_g2s(uint32_t mask) 123055bf511dSas200622 { 123155bf511dSas200622 if (mask & GENERIC_ALL) { 123255bf511dSas200622 mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE 123355bf511dSas200622 | GENERIC_EXECUTE); 123455bf511dSas200622 123555bf511dSas200622 mask |= FILE_ALL_ACCESS; 123655bf511dSas200622 return (mask); 123755bf511dSas200622 } 123855bf511dSas200622 123955bf511dSas200622 if (mask & GENERIC_READ) { 124055bf511dSas200622 mask &= ~GENERIC_READ; 124155bf511dSas200622 mask |= FILE_GENERIC_READ; 124255bf511dSas200622 } 124355bf511dSas200622 124455bf511dSas200622 if (mask & GENERIC_WRITE) { 124555bf511dSas200622 mask &= ~GENERIC_WRITE; 124655bf511dSas200622 mask |= FILE_GENERIC_WRITE; 124755bf511dSas200622 } 124855bf511dSas200622 124955bf511dSas200622 if (mask & GENERIC_EXECUTE) { 125055bf511dSas200622 mask &= ~GENERIC_EXECUTE; 125155bf511dSas200622 mask |= FILE_GENERIC_EXECUTE; 125255bf511dSas200622 } 125355bf511dSas200622 125455bf511dSas200622 return (mask); 125555bf511dSas200622 } 125655bf511dSas200622 1257c8ec8eeaSjose borrego /* 1258c8ec8eeaSjose borrego * smb_ace_flags_tozfs 1259c8ec8eeaSjose borrego * 1260c8ec8eeaSjose borrego * This function maps the flags which have different values 1261c8ec8eeaSjose borrego * in Windows and Solaris. The ones with the same value are 1262c8ec8eeaSjose borrego * transferred untouched. 1263c8ec8eeaSjose borrego */ 1264da6c28aaSamw static uint16_t 1265c8ec8eeaSjose borrego smb_ace_flags_tozfs(uint8_t c_flags) 1266da6c28aaSamw { 1267da6c28aaSamw uint16_t z_flags = 0; 1268da6c28aaSamw 1269da6c28aaSamw if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG) 1270da6c28aaSamw z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 1271da6c28aaSamw 1272da6c28aaSamw if (c_flags & FAILED_ACCESS_ACE_FLAG) 1273da6c28aaSamw z_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 1274da6c28aaSamw 1275da6c28aaSamw if (c_flags & INHERITED_ACE) 1276da6c28aaSamw z_flags |= ACE_INHERITED_ACE; 1277da6c28aaSamw 1278da6c28aaSamw z_flags |= (c_flags & ACE_INHERIT_FLAGS); 1279da6c28aaSamw 1280da6c28aaSamw return (z_flags); 1281da6c28aaSamw } 1282da6c28aaSamw 1283da6c28aaSamw static uint8_t 1284da6c28aaSamw smb_ace_flags_fromzfs(uint16_t z_flags) 1285da6c28aaSamw { 1286da6c28aaSamw uint8_t c_flags; 1287da6c28aaSamw 1288da6c28aaSamw c_flags = z_flags & ACE_INHERIT_FLAGS; 1289da6c28aaSamw 1290da6c28aaSamw if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 1291da6c28aaSamw c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG; 1292da6c28aaSamw 1293da6c28aaSamw if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG) 1294da6c28aaSamw c_flags |= FAILED_ACCESS_ACE_FLAG; 1295da6c28aaSamw 1296da6c28aaSamw if (z_flags & ACE_INHERITED_ACE) 1297da6c28aaSamw c_flags |= INHERITED_ACE; 1298da6c28aaSamw 1299da6c28aaSamw return (c_flags); 1300da6c28aaSamw } 1301da6c28aaSamw 130255bf511dSas200622 static boolean_t 130355bf511dSas200622 smb_ace_isvalid(smb_ace_t *ace, int which_acl) 130455bf511dSas200622 { 130555bf511dSas200622 uint16_t min_len; 130655bf511dSas200622 130755bf511dSas200622 min_len = sizeof (smb_acehdr_t); 130855bf511dSas200622 130955bf511dSas200622 if (ace->se_hdr.se_bsize < min_len) 131055bf511dSas200622 return (B_FALSE); 131155bf511dSas200622 131255bf511dSas200622 if (smb_ace_is_access(ace->se_hdr.se_type) && 131355bf511dSas200622 (which_acl != SMB_DACL_SECINFO)) 131455bf511dSas200622 return (B_FALSE); 131555bf511dSas200622 131655bf511dSas200622 if (smb_ace_is_audit(ace->se_hdr.se_type) && 131755bf511dSas200622 (which_acl != SMB_SACL_SECINFO)) 131855bf511dSas200622 return (B_FALSE); 131955bf511dSas200622 132055bf511dSas200622 if (smb_ace_is_generic(ace->se_hdr.se_type)) { 13216537f381Sas200622 if (!smb_sid_isvalid(ace->se_sid)) 132255bf511dSas200622 return (B_FALSE); 132355bf511dSas200622 132455bf511dSas200622 min_len += sizeof (ace->se_mask); 13256537f381Sas200622 min_len += smb_sid_len(ace->se_sid); 132655bf511dSas200622 132755bf511dSas200622 if (ace->se_hdr.se_bsize < min_len) 132855bf511dSas200622 return (B_FALSE); 132955bf511dSas200622 } 133055bf511dSas200622 1331da6c28aaSamw /* 133255bf511dSas200622 * object-specific ACE validation will be added later. 1333da6c28aaSamw */ 133455bf511dSas200622 return (B_TRUE); 1335da6c28aaSamw } 1336