15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 226139Sjb150015 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #pragma ident "%Z%%M% %I% %E% SMI" 275331Samw 285331Samw #include <sys/acl.h> 295521Sas200622 #include <acl/acl_common.h> 30*6432Sas200622 #include <smbsrv/smb_sid.h> 315331Samw #include <smbsrv/smb_fsops.h> 325331Samw #include <smbsrv/smb_idmap.h> 335521Sas200622 #include <smbsrv/smb_kproto.h> 345521Sas200622 #include <smbsrv/ntstatus.h> 355521Sas200622 #include <smbsrv/ntaccess.h> 365331Samw 375331Samw #define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE) 385331Samw 395331Samw #define ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER) 405331Samw #define ZACE_IS_OWNGRP(zace) \ 415331Samw ((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP)) 425331Samw 435331Samw #define ZACE_IS_USER(zace) \ 445331Samw (((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace))) 455331Samw #define ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP) 465331Samw #define ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE) 475331Samw 485331Samw #define ZACE_IS_PROPAGATE(zace) \ 495331Samw ((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0) 505331Samw 515331Samw #define ZACE_IS_CREATOR_OWNER(zace) \ 525331Samw (ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID)) 535331Samw 545331Samw #define ZACE_IS_CREATOR_GROUP(zace) \ 555331Samw (ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID)) 565331Samw 575331Samw #define ZACE_IS_CREATOR(zace) \ 585331Samw (ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace)) 595331Samw 605331Samw /* 615331Samw * ACE groups within a DACL 625331Samw * 635331Samw * This is from lower to higher ACE order priority 645331Samw */ 655331Samw #define SMB_AG_START 0 665331Samw #define SMB_AG_ALW_INHRT 0 675331Samw #define SMB_AG_DNY_INHRT 1 685331Samw #define SMB_AG_ALW_DRCT 2 695331Samw #define SMB_AG_DNY_DRCT 3 705331Samw #define SMB_AG_NUM 4 715331Samw 725331Samw /* 735521Sas200622 * SID for Everyone group: S-1-1-0. 745521Sas200622 */ 75*6432Sas200622 smb_sid_t everyone_sid = { 765521Sas200622 NT_SID_REVISION, 775521Sas200622 1, 785521Sas200622 NT_SECURITY_WORLD_AUTH, 795521Sas200622 { 0 } 805521Sas200622 }; 815521Sas200622 825521Sas200622 #define DEFAULT_DACL_ACENUM 2 835521Sas200622 /* 845521Sas200622 * Default ACL: 855521Sas200622 * owner: full access 865521Sas200622 * SYSTEM: full access 875521Sas200622 */ 885521Sas200622 static ace_t default_dacl[DEFAULT_DACL_ACENUM] = { 895521Sas200622 { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, 905521Sas200622 { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP, 915521Sas200622 ACE_ACCESS_ALLOWED_ACE_TYPE } 925521Sas200622 }; 935521Sas200622 945521Sas200622 /* 955521Sas200622 * Note: 965331Samw * 975521Sas200622 * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format 985521Sas200622 * smb_fsacl_xxx functions work with acl_t which represents the Solaris native 995521Sas200622 * format 1005521Sas200622 */ 1015521Sas200622 1025521Sas200622 static idmap_stat smb_acl_getsids(smb_idmap_batch_t *, acl_t *, uid_t, gid_t); 1035521Sas200622 static acl_t *smb_acl_null_empty(boolean_t null); 1045521Sas200622 1055521Sas200622 static int smb_fsacl_inheritable(acl_t *, int); 1065521Sas200622 1075521Sas200622 1085521Sas200622 static void smb_ace_inherit(ace_t *, ace_t *, int); 1095521Sas200622 static boolean_t smb_ace_isvalid(smb_ace_t *, int); 1105521Sas200622 static uint16_t smb_ace_len(smb_ace_t *); 1115521Sas200622 static uint32_t smb_ace_mask_g2s(uint32_t); 1125521Sas200622 static uint16_t smb_ace_flags_tozfs(uint8_t, int); 1135521Sas200622 static uint8_t smb_ace_flags_fromzfs(uint16_t); 1145521Sas200622 1155521Sas200622 smb_acl_t * 1165521Sas200622 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt) 1175521Sas200622 { 1185521Sas200622 smb_acl_t *acl; 1195521Sas200622 int size; 1205521Sas200622 1215521Sas200622 size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t)); 1225521Sas200622 acl = kmem_zalloc(size, KM_SLEEP); 1235521Sas200622 acl->sl_revision = revision; 1245521Sas200622 acl->sl_bsize = bsize; 1255521Sas200622 acl->sl_acecnt = acecnt; 1265521Sas200622 acl->sl_aces = (smb_ace_t *)(acl + 1); 1275521Sas200622 1285521Sas200622 list_create(&acl->sl_sorted, sizeof (smb_ace_t), 1295521Sas200622 offsetof(smb_ace_t, se_sln)); 1305521Sas200622 return (acl); 1315521Sas200622 } 1325521Sas200622 1335521Sas200622 void 1345521Sas200622 smb_acl_free(smb_acl_t *acl) 1355521Sas200622 { 1365521Sas200622 int i, size; 1375521Sas200622 void *ace; 1385521Sas200622 1395521Sas200622 if (acl == NULL) 1405521Sas200622 return; 1415521Sas200622 142*6432Sas200622 for (i = 0; i < acl->sl_acecnt; i++) 143*6432Sas200622 smb_sid_free(acl->sl_aces[i].se_sid); 1445521Sas200622 1455521Sas200622 while ((ace = list_head(&acl->sl_sorted)) != NULL) 1465521Sas200622 list_remove(&acl->sl_sorted, ace); 1475521Sas200622 list_destroy(&acl->sl_sorted); 1485521Sas200622 1495521Sas200622 size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t)); 1505521Sas200622 kmem_free(acl, size); 1515521Sas200622 } 1525521Sas200622 1535521Sas200622 /* 1545521Sas200622 * smb_acl_len 1555521Sas200622 * 1565521Sas200622 * Returns the size of given ACL in bytes. Note that this 1575521Sas200622 * is not an in-memory size, it's the ACL's size as it would 1585521Sas200622 * appear on the wire 1595521Sas200622 */ 1605521Sas200622 uint16_t 1615521Sas200622 smb_acl_len(smb_acl_t *acl) 1625521Sas200622 { 1635521Sas200622 if (acl == NULL) 1645521Sas200622 return (0); 1655521Sas200622 1665521Sas200622 return (acl->sl_bsize); 1675521Sas200622 } 1685521Sas200622 1695521Sas200622 boolean_t 1705521Sas200622 smb_acl_isvalid(smb_acl_t *acl, int which_acl) 1715521Sas200622 { 1725521Sas200622 int i; 1735521Sas200622 1745521Sas200622 if (acl->sl_bsize < SMB_ACL_HDRSIZE) 1755521Sas200622 return (B_FALSE); 1765521Sas200622 1775521Sas200622 if (acl->sl_revision != ACL_REVISION) { 1785521Sas200622 /* 1795521Sas200622 * we are rejecting ACLs with object-specific ACEs for now 1805521Sas200622 */ 1815521Sas200622 return (B_FALSE); 1825521Sas200622 } 1835521Sas200622 1845521Sas200622 for (i = 0; i < acl->sl_acecnt; i++) { 1855521Sas200622 if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl)) 1865521Sas200622 return (B_FALSE); 1875521Sas200622 } 1885521Sas200622 1895521Sas200622 return (B_TRUE); 1905521Sas200622 } 1915521Sas200622 1925521Sas200622 /* 1935521Sas200622 * smb_acl_sort 1945521Sas200622 * 1955521Sas200622 * Sorts the given ACL in place if it needs to be sorted. 1965331Samw * 1975331Samw * The following is an excerpt from MSDN website. 1985331Samw * 1995331Samw * Order of ACEs in a DACL 2005331Samw * 2015331Samw * For Windows NT versions 4.0 and earlier, the preferred order of ACEs 2025331Samw * is simple: In a DACL, all access-denied ACEs should precede any 2035331Samw * access-allowed ACEs. 2045331Samw * 2055331Samw * For Windows 2000 or later, the proper order of ACEs is more complicated 2065331Samw * because of the introduction of object-specific ACEs and automatic 2075331Samw * inheritance. 2085331Samw * 2095331Samw * The following describes the preferred order: 2105331Samw * 2115331Samw * To ensure that noninherited ACEs have precedence over inherited ACEs, 2125331Samw * place all noninherited ACEs in a group before any inherited ACEs. This 2135331Samw * ordering ensures, for example, that a noninherited access-denied ACE 2145331Samw * is enforced regardless of any inherited ACE that allows access. 2155331Samw * Within the groups of noninherited ACEs and inherited ACEs, order ACEs 2165331Samw * according to ACE type, as the following shows: 2175331Samw * . Access-denied ACEs that apply to the object itself 2185331Samw * . Access-denied ACEs that apply to a subobject of the 2195331Samw * object, such as a property set or property 2205331Samw * . Access-allowed ACEs that apply to the object itself 2215331Samw * . Access-allowed ACEs that apply to a subobject of the object 2225331Samw * 2235521Sas200622 * So, here is the desired ACE order 2245331Samw * 2255331Samw * deny-direct, allow-direct, deny-inherited, allow-inherited 2265331Samw * 2275521Sas200622 * Of course, not all ACE types are required in an ACL. 2285331Samw */ 2295521Sas200622 void 2305331Samw smb_acl_sort(smb_acl_t *acl) 2315331Samw { 2325521Sas200622 list_t ace_grps[SMB_AG_NUM]; 2335521Sas200622 list_t *alist; 2345331Samw smb_ace_t *ace; 2355331Samw uint8_t ace_flags; 2365521Sas200622 int ag, i; 2375331Samw 2385331Samw ASSERT(acl); 2395331Samw 2405331Samw if (acl->sl_acecnt == 0) { 2415331Samw /* 2425331Samw * ACL with no entry is a valid ACL and it means 2435331Samw * no access for anybody. 2445331Samw */ 2455521Sas200622 return; 2465331Samw } 2475331Samw 2485331Samw for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { 2495521Sas200622 list_create(&ace_grps[i], sizeof (smb_ace_t), 2505521Sas200622 offsetof(smb_ace_t, se_sln)); 2515331Samw } 2525331Samw 2535521Sas200622 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) { 2545521Sas200622 ace_flags = ace->se_hdr.se_flags; 2555331Samw 2565521Sas200622 switch (ace->se_hdr.se_type) { 2575331Samw case ACCESS_DENIED_ACE_TYPE: 2585521Sas200622 ag = (ace_flags & INHERITED_ACE) ? 2595521Sas200622 SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT; 2605331Samw break; 2615331Samw 2625331Samw case ACCESS_ALLOWED_ACE_TYPE: 2635521Sas200622 ag = (ace_flags & INHERITED_ACE) ? 2645521Sas200622 SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT; 2655331Samw break; 2665331Samw 2675331Samw default: 2685331Samw /* 2695331Samw * This is the lowest priority group so we put 2705331Samw * evertything unknown here. 2715331Samw */ 2725331Samw ag = SMB_AG_ALW_INHRT; 2735331Samw break; 2745331Samw } 2755331Samw 2765521Sas200622 /* Add the ACE to the selected group */ 2775521Sas200622 list_insert_tail(&ace_grps[ag], ace); 2785331Samw } 2795331Samw 2805521Sas200622 /* 2815521Sas200622 * start with highest priority ACE group and append 2825521Sas200622 * the ACEs to the ACL. 2835521Sas200622 */ 2845521Sas200622 for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { 2855521Sas200622 alist = &ace_grps[i]; 2865521Sas200622 while ((ace = list_head(alist)) != NULL) { 2875521Sas200622 list_remove(alist, ace); 2885521Sas200622 list_insert_tail(&acl->sl_sorted, ace); 2895521Sas200622 } 2905521Sas200622 list_destroy(alist); 2915331Samw } 2925331Samw } 2935331Samw 2945521Sas200622 /* 2955521Sas200622 * smb_acl_from_zfs 2965521Sas200622 * 2975521Sas200622 * Converts given ZFS ACL to a Windows ACL. 2985521Sas200622 * 2995521Sas200622 * A pointer to allocated memory for the Win ACL will be 3005521Sas200622 * returned upon successful conversion. 3015521Sas200622 */ 3025521Sas200622 smb_acl_t * 3035521Sas200622 smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid) 3045331Samw { 3055521Sas200622 ace_t *zace; 3065521Sas200622 int numaces; 3075521Sas200622 smb_acl_t *acl; 3085331Samw smb_ace_t *ace; 3095521Sas200622 smb_idmap_batch_t sib; 3105521Sas200622 smb_idmap_t *sim; 3115521Sas200622 idmap_stat idm_stat; 3125331Samw 3135521Sas200622 idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, 3145521Sas200622 SMB_IDMAP_ID2SID); 3155521Sas200622 if (idm_stat != IDMAP_SUCCESS) 3165331Samw return (NULL); 3175331Samw 3185521Sas200622 if (smb_acl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) { 3195521Sas200622 smb_idmap_batch_destroy(&sib); 3205521Sas200622 return (NULL); 3215331Samw } 3225331Samw 3235521Sas200622 acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt); 3245331Samw 3255521Sas200622 sim = sib.sib_maps; 3265521Sas200622 for (numaces = 0, zace = zacl->acl_aclp; 3275521Sas200622 numaces < zacl->acl_cnt; 3285521Sas200622 zace++, numaces++, sim++) { 3295521Sas200622 ASSERT(sim->sim_sid); 3305521Sas200622 if (sim->sim_sid == NULL) { 3315521Sas200622 smb_acl_free(acl); 3325521Sas200622 acl = NULL; 3335521Sas200622 break; 3345521Sas200622 } 3355331Samw 3365521Sas200622 ace = &acl->sl_aces[numaces]; 3375521Sas200622 ace->se_hdr.se_type = zace->a_type; 3385521Sas200622 ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags); 3395521Sas200622 ace->se_mask = zace->a_access_mask; 340*6432Sas200622 ace->se_sid = smb_sid_dup(sim->sim_sid); 3415521Sas200622 ace->se_hdr.se_bsize = smb_ace_len(ace); 3425521Sas200622 3435521Sas200622 acl->sl_bsize += ace->se_hdr.se_bsize; 3445331Samw } 3455331Samw 3465521Sas200622 smb_idmap_batch_destroy(&sib); 3475521Sas200622 return (acl); 3485331Samw } 3495331Samw 3505331Samw /* 3515521Sas200622 * smb_acl_to_zfs 3525331Samw * 3535521Sas200622 * Converts given Windows ACL to a ZFS ACL. 3545331Samw * 3555521Sas200622 * fs_acl will contain a pointer to the created ZFS ACL. 3565521Sas200622 * The allocated memory should be freed by calling 3575521Sas200622 * smb_fsacl_free(). 3585331Samw * 3595521Sas200622 * Since the output parameter, fs_acl, is allocated in this 3605521Sas200622 * function, the caller has to make sure *fs_acl is NULL which 3615521Sas200622 * means it's not pointing to any memory. 3625331Samw */ 3635331Samw uint32_t 3645521Sas200622 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) 3655331Samw { 3665521Sas200622 smb_ace_t *ace; 3675521Sas200622 acl_t *zacl; 3685521Sas200622 ace_t *zace; 3695521Sas200622 smb_idmap_batch_t sib; 3705521Sas200622 smb_idmap_t *sim; 3715521Sas200622 idmap_stat idm_stat; 3725521Sas200622 int i, isdir; 3735331Samw 3745521Sas200622 ASSERT(fs_acl); 3755521Sas200622 ASSERT(*fs_acl == NULL); 3765521Sas200622 3775521Sas200622 if (acl && !smb_acl_isvalid(acl, which_acl)) 3785521Sas200622 return (NT_STATUS_INVALID_ACL); 3795521Sas200622 3805521Sas200622 if ((acl == NULL) || (acl->sl_acecnt == 0)) { 3815521Sas200622 if (which_acl == SMB_DACL_SECINFO) { 3825521Sas200622 *fs_acl = smb_acl_null_empty(acl == NULL); 3835521Sas200622 } 3845521Sas200622 3855521Sas200622 return (NT_STATUS_SUCCESS); 3865331Samw } 3875331Samw 3885521Sas200622 idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, 3895521Sas200622 SMB_IDMAP_SID2ID); 3905521Sas200622 if (idm_stat != IDMAP_SUCCESS) 3915521Sas200622 return (NT_STATUS_INTERNAL_ERROR); 3925521Sas200622 3935521Sas200622 isdir = ((flags & ACL_IS_DIR) == ACL_IS_DIR); 3945521Sas200622 3955521Sas200622 zacl = smb_fsacl_alloc(acl->sl_acecnt, flags); 3965521Sas200622 3975521Sas200622 zace = zacl->acl_aclp; 3985521Sas200622 ace = acl->sl_aces; 3995521Sas200622 sim = sib.sib_maps; 4005521Sas200622 4015521Sas200622 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 4025521Sas200622 zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES; 4035521Sas200622 zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); 4045521Sas200622 zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags, 4055521Sas200622 isdir); 4065521Sas200622 407*6432Sas200622 if (smb_sid_cmp(ace->se_sid, &everyone_sid)) 4085521Sas200622 zace->a_flags |= ACE_EVERYONE; 4095521Sas200622 else { 4105521Sas200622 sim->sim_id = &zace->a_who; 4115521Sas200622 idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, 4125521Sas200622 ace->se_sid, -1); 4135521Sas200622 4145521Sas200622 if (idm_stat != IDMAP_SUCCESS) { 4155521Sas200622 smb_fsacl_free(zacl); 4165521Sas200622 smb_idmap_batch_destroy(&sib); 4175521Sas200622 return (NT_STATUS_INTERNAL_ERROR); 4185521Sas200622 } 4195521Sas200622 } 4205331Samw } 4215331Samw 4225521Sas200622 idm_stat = smb_idmap_batch_getmappings(&sib); 4235521Sas200622 if (idm_stat != IDMAP_SUCCESS) { 4245521Sas200622 smb_fsacl_free(zacl); 4255521Sas200622 smb_idmap_batch_destroy(&sib); 4265521Sas200622 return (NT_STATUS_NONE_MAPPED); 4275331Samw } 4285331Samw 4295521Sas200622 /* 4305521Sas200622 * Set the ACEs group flag based on the type of ID returned. 4315521Sas200622 */ 4325521Sas200622 zace = zacl->acl_aclp; 4335521Sas200622 ace = acl->sl_aces; 4345521Sas200622 sim = sib.sib_maps; 4355521Sas200622 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 4365521Sas200622 if (zace->a_flags & ACE_EVERYONE) 4375521Sas200622 continue; 4385521Sas200622 4395521Sas200622 if (sim->sim_idtype == SMB_IDMAP_GROUP) 4405521Sas200622 zace->a_flags |= ACE_IDENTIFIER_GROUP; 4415331Samw } 4425331Samw 4435521Sas200622 smb_idmap_batch_destroy(&sib); 4445521Sas200622 4455521Sas200622 *fs_acl = zacl; 4465521Sas200622 return (NT_STATUS_SUCCESS); 4475331Samw } 4485331Samw 4495331Samw /* 4505331Samw * smb_acl_getsids 4515331Samw * 4525331Samw * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs. 4535331Samw */ 4545331Samw static idmap_stat 4555331Samw smb_acl_getsids(smb_idmap_batch_t *sib, acl_t *zacl, uid_t uid, gid_t gid) 4565331Samw { 4575331Samw ace_t *zace; 4585331Samw idmap_stat idm_stat; 4595331Samw smb_idmap_t *sim; 4605331Samw uid_t id; 4615331Samw int i, idtype; 4625331Samw 4635331Samw sim = sib->sib_maps; 4645331Samw 4655331Samw for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; 4665331Samw zace++, i++, sim++) { 4675331Samw switch (zace->a_flags & ACE_TYPE_FLAGS) { 4685331Samw case ACE_OWNER: 4695331Samw id = uid; 4705331Samw idtype = SMB_IDMAP_USER; 4715331Samw break; 4725331Samw 4735331Samw case (ACE_GROUP | ACE_IDENTIFIER_GROUP): 4745331Samw /* owning group */ 4755331Samw id = gid; 4765331Samw idtype = SMB_IDMAP_GROUP; 4775331Samw break; 4785331Samw 4795331Samw case ACE_IDENTIFIER_GROUP: 4805331Samw /* regular group */ 4815331Samw id = zace->a_who; 4825331Samw idtype = SMB_IDMAP_GROUP; 4835331Samw break; 4845331Samw 4855331Samw case ACE_EVERYONE: 4865331Samw idtype = SMB_IDMAP_EVERYONE; 4875331Samw break; 4885331Samw 4895331Samw default: 4905331Samw /* user entry */ 4915331Samw id = zace->a_who; 4925331Samw idtype = SMB_IDMAP_USER; 4935331Samw } 4945331Samw 4955331Samw idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim, 4965331Samw id, idtype); 4975331Samw 4985331Samw if (idm_stat != IDMAP_SUCCESS) { 4995331Samw return (idm_stat); 5005331Samw } 5015331Samw } 5025331Samw 5035331Samw idm_stat = smb_idmap_batch_getmappings(sib); 5045331Samw return (idm_stat); 5055331Samw } 5065331Samw 5075331Samw /* 5085331Samw * smb_acl_null_empty 5095331Samw * 5105331Samw * NULL DACL means everyone full-access 5115331Samw * Empty DACL means everyone full-deny 5125331Samw * 5135331Samw * ZFS ACL must have at least one entry so smb server has 5145331Samw * to simulate the aforementioned expected behavior by adding 5155331Samw * an entry in case the requested DACL is null or empty. Adding 5165331Samw * a everyone full-deny entry has proved to be problematic in 5175331Samw * tests since a deny entry takes precedence over allow entries. 5185331Samw * So, instead of adding a everyone full-deny, an owner ACE with 5195331Samw * owner implicit permissions will be set. 5205331Samw */ 5215521Sas200622 static acl_t * 5225521Sas200622 smb_acl_null_empty(boolean_t null) 5235331Samw { 5245331Samw acl_t *zacl; 5255331Samw ace_t *zace; 5265331Samw 5275521Sas200622 zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT); 5285331Samw zace = zacl->acl_aclp; 5295331Samw 5305331Samw zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 5315331Samw if (null) { 5325331Samw zace->a_access_mask = ACE_ALL_PERMS; 5335331Samw zace->a_flags = ACE_EVERYONE; 5345331Samw } else { 5355331Samw zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | 5365331Samw ACE_READ_ATTRIBUTES; 5375331Samw zace->a_flags = ACE_OWNER; 5385331Samw } 5395331Samw 5405331Samw return (zacl); 5415331Samw } 5425331Samw 5435331Samw /* 5445521Sas200622 * FS ACL (acl_t) Functions 5455331Samw */ 5465521Sas200622 acl_t * 5475521Sas200622 smb_fsacl_alloc(int acenum, int flags) 5485331Samw { 5495521Sas200622 acl_t *acl; 5505331Samw 5515521Sas200622 acl = acl_alloc(ACE_T); 5525521Sas200622 acl->acl_cnt = acenum; 5535521Sas200622 acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP); 5545521Sas200622 acl->acl_flags = flags; 5555521Sas200622 return (acl); 5565521Sas200622 } 5575331Samw 5585521Sas200622 void 5595521Sas200622 smb_fsacl_free(acl_t *acl) 5605521Sas200622 { 5615521Sas200622 if (acl) 5625521Sas200622 acl_free(acl); 5635521Sas200622 } 5645331Samw 5655521Sas200622 /* 5665521Sas200622 * smb_fsop_aclmerge 5675521Sas200622 * 5685521Sas200622 * smb_fsop_aclread/write routines which interact with filesystem 5695521Sas200622 * work with single ACL. This routine merges given DACL and SACL 5705521Sas200622 * which might have been created during CIFS to FS conversion into 5715521Sas200622 * one single ACL. 5725521Sas200622 */ 5735521Sas200622 acl_t * 5745521Sas200622 smb_fsacl_merge(acl_t *dacl, acl_t *sacl) 5755521Sas200622 { 5765521Sas200622 acl_t *acl; 5775521Sas200622 int dacl_size; 5785331Samw 5795521Sas200622 ASSERT(dacl); 5805521Sas200622 ASSERT(sacl); 5815331Samw 5825521Sas200622 acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags); 5835521Sas200622 dacl_size = dacl->acl_cnt * dacl->acl_entry_size; 5845521Sas200622 bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size); 5855521Sas200622 bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size, 5865521Sas200622 sacl->acl_cnt * sacl->acl_entry_size); 5875331Samw 5885521Sas200622 return (acl); 5895331Samw } 5905331Samw 5915331Samw /* 5925521Sas200622 * smb_fsacl_split 5935331Samw * 5945521Sas200622 * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on 5955521Sas200622 * the 'which_acl' parameter. Note that output dacl/sacl parameters could be 5965521Sas200622 * NULL even if they're specified in 'which_acl', which means the target 5975521Sas200622 * doesn't have any access and/or audit ACEs. 5985331Samw */ 5995521Sas200622 void 6005521Sas200622 smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl) 6015331Samw { 6025331Samw ace_t *zace; 6035521Sas200622 ace_t *access_ace; 6045521Sas200622 ace_t *audit_ace; 6055521Sas200622 int naccess, naudit; 6065521Sas200622 int get_dacl, get_sacl; 6075521Sas200622 int i; 6085521Sas200622 6095521Sas200622 *dacl = *sacl = NULL; 6105521Sas200622 naccess = naudit = 0; 6115521Sas200622 get_dacl = (which_acl & SMB_DACL_SECINFO); 6125521Sas200622 get_sacl = (which_acl & SMB_SACL_SECINFO); 6135331Samw 6145521Sas200622 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { 6155521Sas200622 if (get_dacl && smb_ace_is_access(zace->a_type)) 6165521Sas200622 naccess++; 6175521Sas200622 else if (get_sacl && smb_ace_is_audit(zace->a_type)) 6185521Sas200622 naudit++; 6195521Sas200622 } 6205331Samw 6215521Sas200622 if (naccess) { 6225521Sas200622 *dacl = smb_fsacl_alloc(naccess, zacl->acl_flags); 6235521Sas200622 access_ace = (*dacl)->acl_aclp; 6245521Sas200622 } 6255331Samw 6265521Sas200622 if (naudit) { 6275521Sas200622 *sacl = smb_fsacl_alloc(naudit, zacl->acl_flags); 6285521Sas200622 audit_ace = (*sacl)->acl_aclp; 6295521Sas200622 } 6305331Samw 6315521Sas200622 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { 6325521Sas200622 if (get_dacl && smb_ace_is_access(zace->a_type)) { 6335521Sas200622 *access_ace = *zace; 6345521Sas200622 access_ace++; 6355521Sas200622 } else if (get_sacl && smb_ace_is_audit(zace->a_type)) { 6365521Sas200622 *audit_ace = *zace; 6375521Sas200622 audit_ace++; 6385331Samw } 6395331Samw } 6405331Samw } 6415331Samw 6425331Samw /* 6435521Sas200622 * ACE Inheritance Rules 6445521Sas200622 * 6455521Sas200622 * The system propagates inheritable ACEs to child objects according to a 6465521Sas200622 * set of inheritance rules. The system places inherited ACEs in the child's 6475521Sas200622 * DACL according to the preferred order of ACEs in a DACL. For Windows 6485521Sas200622 * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs. 6495521Sas200622 * 6505521Sas200622 * The following table shows the ACEs inherited by container and noncontainer 6515521Sas200622 * child objects for different combinations of inheritance flags. These 6525521Sas200622 * inheritance rules work the same for both DACLs and SACLs. 6535521Sas200622 * 6545521Sas200622 * Parent ACE type Effect on Child ACL 6555521Sas200622 * ----------------------- ------------------- 6565521Sas200622 * OBJECT_INHERIT_ACE only Noncontainer child objects: 6575521Sas200622 * Inherited as an effective ACE. 6585521Sas200622 * Container child objects: 6595521Sas200622 * Containers inherit an inherit-only ACE 6605521Sas200622 * unless the NO_PROPAGATE_INHERIT_ACE bit 6615521Sas200622 * flag is also set. 6625521Sas200622 * 6635521Sas200622 * CONTAINER_INHERIT_ACE only Noncontainer child objects: 6645521Sas200622 * No effect on the child object. 6655521Sas200622 * Container child objects: 6665521Sas200622 * The child object inherits an effective ACE. 6675521Sas200622 * The inherited ACE is inheritable unless the 6685521Sas200622 * NO_PROPAGATE_INHERIT_ACE bit flag is also set. 6695521Sas200622 * 6705521Sas200622 * CONTAINER_INHERIT_ACE and 6715521Sas200622 * OBJECT_INHERIT_ACE Noncontainer child objects: 6725521Sas200622 * Inherited as an effective ACE. 6735521Sas200622 * Container child objects: 6745521Sas200622 * The child object inherits an effective ACE. 6755521Sas200622 * The inherited ACE is inheritable unless the 6765521Sas200622 * NO_PROPAGATE_INHERIT_ACE bit flag is also set 6775521Sas200622 * 6785521Sas200622 * No inheritance flags set No effect on child container or noncontainer 6795521Sas200622 * objects. 6805521Sas200622 * 6815521Sas200622 * If an inherited ACE is an effective ACE for the child object, the system 6825521Sas200622 * maps any generic rights to the specific rights for the child object. 6835521Sas200622 * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the 6845521Sas200622 * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic 6855521Sas200622 * rights or generic SIDs are left unchanged so that they can be mapped 6865521Sas200622 * appropriately when the ACE is inherited by the next generation of child 6875521Sas200622 * objects. 6885521Sas200622 * 6895521Sas200622 * For a case in which a container object inherits an ACE that is both 6905521Sas200622 * effective on the container and inheritable by its descendants, the 6915521Sas200622 * container may inherit two ACEs. This occurs if the inheritable ACE 6925521Sas200622 * contains generic information. The container inherits an inherit-only 6935521Sas200622 * ACE containing the generic information and an effective-only ACE in 6945521Sas200622 * which the generic information has been mapped. 6955331Samw */ 6965331Samw 6975331Samw /* 6985521Sas200622 * smb_fsacl_inherit 6995331Samw * 7005331Samw * Manufacture the inherited ACL from the given ACL considering 7015331Samw * the new object type (file/dir) specified by 'is_dir'. The 7025331Samw * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions. 7035521Sas200622 * This function implements Windows inheritance rules explained above. 7045331Samw * 7055521Sas200622 * Note that the in/out ACLs are ZFS ACLs not Windows ACLs 7065331Samw */ 7075331Samw acl_t * 7085521Sas200622 smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid) 7095331Samw { 7105331Samw boolean_t use_default = B_FALSE; 7115331Samw int num_inheritable = 0; 7125331Samw int numaces; 7135331Samw ace_t *dir_zace; 7145331Samw acl_t *new_zacl; 7155331Samw ace_t *new_zace; 7165331Samw 7175521Sas200622 num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir); 7185331Samw 7195331Samw if (num_inheritable == 0) { 7205331Samw if (which_acl == SMB_DACL_SECINFO) { 7215331Samw /* No inheritable access ACEs -> default DACL */ 7225331Samw num_inheritable = DEFAULT_DACL_ACENUM; 7235331Samw use_default = B_TRUE; 7245331Samw } else { 7255331Samw return (NULL); 7265331Samw } 7275331Samw } 7285331Samw 7295521Sas200622 new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT); 7305331Samw new_zace = new_zacl->acl_aclp; 7315331Samw 7325331Samw if (use_default) { 7335331Samw bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl)); 7345331Samw new_zace->a_who = owner_uid; 7355331Samw return (new_zacl); 7365331Samw } 7375331Samw 7385331Samw for (numaces = 0, dir_zace = dir_zacl->acl_aclp; 7395331Samw numaces < dir_zacl->acl_cnt; 7405331Samw dir_zace++, numaces++) { 7415331Samw switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) { 7425331Samw case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 7435331Samw /* 7445331Samw * Files inherit an effective ACE. 7455331Samw * 7465331Samw * Dirs inherit an effective ACE. 7475331Samw * The inherited ACE is inheritable unless the 7485331Samw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 7495331Samw */ 7505331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 7515331Samw new_zace++; 7525331Samw 7535331Samw if (is_dir && ZACE_IS_CREATOR(dir_zace) && 7545331Samw (ZACE_IS_PROPAGATE(dir_zace))) { 7555331Samw *new_zace = *dir_zace; 7565331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 7575331Samw ACE_INHERITED_ACE); 7585331Samw new_zace++; 7595331Samw } 7605331Samw break; 7615331Samw 7625331Samw case ACE_FILE_INHERIT_ACE: 7635331Samw /* 7645331Samw * Files inherit as an effective ACE. 7655331Samw * 7665331Samw * Dirs inherit an inherit-only ACE 7675331Samw * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 7685331Samw * flag is also set. 7695331Samw */ 7705331Samw if (is_dir == 0) { 7715331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 7725331Samw new_zace++; 7735331Samw } else if (ZACE_IS_PROPAGATE(dir_zace)) { 7745331Samw *new_zace = *dir_zace; 7755331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 7765331Samw ACE_INHERITED_ACE); 7775331Samw new_zace++; 7785331Samw } 7795331Samw break; 7805331Samw 7815331Samw case ACE_DIRECTORY_INHERIT_ACE: 7825331Samw /* 7835331Samw * No effect on files 7845331Samw * 7855331Samw * Dirs inherit an effective ACE. 7865331Samw * The inherited ACE is inheritable unless the 7875331Samw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 7885331Samw */ 7895331Samw if (is_dir == 0) 7905331Samw break; 7915331Samw 7925331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 7935331Samw new_zace++; 7945331Samw 7955331Samw if (ZACE_IS_CREATOR(dir_zace) && 7965331Samw (ZACE_IS_PROPAGATE(dir_zace))) { 7975331Samw *new_zace = *dir_zace; 7985331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 7995331Samw ACE_INHERITED_ACE); 8005331Samw new_zace++; 8015331Samw } 8025331Samw 8035331Samw break; 8045331Samw 8055331Samw default: 8065331Samw break; 8075331Samw } 8085331Samw } 8095331Samw 8105331Samw return (new_zacl); 8115331Samw } 8125331Samw 8135521Sas200622 /* 8145521Sas200622 * smb_fsacl_from_vsa 8155521Sas200622 * 8165521Sas200622 * Converts given vsecattr_t structure to a acl_t structure. 8175521Sas200622 * 8185521Sas200622 * The allocated memory for retuned acl_t should be freed by 8195521Sas200622 * calling acl_free(). 8205521Sas200622 */ 8215521Sas200622 acl_t * 8225521Sas200622 smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type) 8235521Sas200622 { 8245521Sas200622 int aclbsize = 0; /* size of acl list in bytes */ 8255521Sas200622 int dfaclbsize = 0; /* size of default acl list in bytes */ 8265521Sas200622 int numacls; 8275521Sas200622 acl_t *acl_info; 8285521Sas200622 8295521Sas200622 ASSERT(vsecattr); 8305521Sas200622 8315521Sas200622 acl_info = acl_alloc(acl_type); 8325521Sas200622 if (acl_info == NULL) 8335521Sas200622 return (NULL); 8345521Sas200622 8355521Sas200622 acl_info->acl_flags = 0; 8365521Sas200622 8375521Sas200622 switch (acl_type) { 8385521Sas200622 8395521Sas200622 case ACLENT_T: 8405521Sas200622 numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt; 8415521Sas200622 aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t); 8425521Sas200622 dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t); 8435521Sas200622 8445521Sas200622 acl_info->acl_cnt = numacls; 8455521Sas200622 acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize, 8465521Sas200622 KM_SLEEP); 8475521Sas200622 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, 8485521Sas200622 aclbsize); 8495521Sas200622 (void) memcpy((char *)acl_info->acl_aclp + aclbsize, 8505521Sas200622 vsecattr->vsa_dfaclentp, dfaclbsize); 8515521Sas200622 8525521Sas200622 if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) 8535521Sas200622 acl_info->acl_flags |= ACL_IS_TRIVIAL; 8545521Sas200622 8555521Sas200622 break; 8565521Sas200622 8575521Sas200622 case ACE_T: 8585521Sas200622 aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); 8595521Sas200622 acl_info->acl_cnt = vsecattr->vsa_aclcnt; 8605521Sas200622 acl_info->acl_flags = vsecattr->vsa_aclflags; 8615521Sas200622 acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP); 8625521Sas200622 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, 8635521Sas200622 aclbsize); 8645521Sas200622 if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) 8655521Sas200622 acl_info->acl_flags |= ACL_IS_TRIVIAL; 8665521Sas200622 8675521Sas200622 break; 8685521Sas200622 8695521Sas200622 default: 8705521Sas200622 acl_free(acl_info); 8715521Sas200622 return (NULL); 8725521Sas200622 } 8735521Sas200622 8745521Sas200622 if (aclbsize && vsecattr->vsa_aclentp) 8755521Sas200622 kmem_free(vsecattr->vsa_aclentp, aclbsize); 8765521Sas200622 if (dfaclbsize && vsecattr->vsa_dfaclentp) 8775521Sas200622 kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize); 8785521Sas200622 8795521Sas200622 return (acl_info); 8805521Sas200622 } 8815521Sas200622 8825521Sas200622 /* 8835521Sas200622 * smb_fsacl_to_vsa 8845521Sas200622 * 8855521Sas200622 * Converts given acl_t structure to a vsecattr_t structure. 8865521Sas200622 * 8875521Sas200622 * IMPORTANT: 8885521Sas200622 * Upon successful return the memory allocated for vsa_aclentp 8895521Sas200622 * should be freed by calling kmem_free(). The size is returned 8905521Sas200622 * in aclbsize. 8915521Sas200622 */ 8925521Sas200622 int 8935521Sas200622 smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize) 8945521Sas200622 { 8955521Sas200622 int error = 0; 8965521Sas200622 int numacls; 8975521Sas200622 aclent_t *aclp; 8985521Sas200622 8995521Sas200622 ASSERT(acl_info); 9005521Sas200622 ASSERT(vsecattr); 9015521Sas200622 ASSERT(aclbsize); 9025521Sas200622 9035521Sas200622 bzero(vsecattr, sizeof (vsecattr_t)); 9045521Sas200622 *aclbsize = 0; 9055521Sas200622 9065521Sas200622 switch (acl_info->acl_type) { 9075521Sas200622 case ACLENT_T: 9085521Sas200622 numacls = acl_info->acl_cnt; 9095521Sas200622 /* 9105521Sas200622 * Minimum ACL size is three entries so might as well 9115521Sas200622 * bail out here. Also limit request size to prevent user 9125521Sas200622 * from allocating too much kernel memory. Maximum size 9135521Sas200622 * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES 9145521Sas200622 * for the default ACL part. 9155521Sas200622 */ 9165521Sas200622 if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) { 9175521Sas200622 error = EINVAL; 9185521Sas200622 break; 9195521Sas200622 } 9205521Sas200622 9215521Sas200622 vsecattr->vsa_mask = VSA_ACL; 9225521Sas200622 9235521Sas200622 vsecattr->vsa_aclcnt = numacls; 9245521Sas200622 *aclbsize = numacls * sizeof (aclent_t); 9255521Sas200622 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); 9265521Sas200622 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, 9275521Sas200622 *aclbsize); 9285521Sas200622 9295521Sas200622 /* Sort the acl list */ 9305521Sas200622 ksort((caddr_t)vsecattr->vsa_aclentp, 9315521Sas200622 vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls); 9325521Sas200622 9335521Sas200622 /* Break into acl and default acl lists */ 9345521Sas200622 for (numacls = 0, aclp = vsecattr->vsa_aclentp; 9355521Sas200622 numacls < vsecattr->vsa_aclcnt; 9365521Sas200622 aclp++, numacls++) { 9375521Sas200622 if (aclp->a_type & ACL_DEFAULT) 9385521Sas200622 break; 9395521Sas200622 } 9405521Sas200622 9415521Sas200622 /* Find where defaults start (if any) */ 9425521Sas200622 if (numacls < vsecattr->vsa_aclcnt) { 9435521Sas200622 vsecattr->vsa_mask |= VSA_DFACL; 9445521Sas200622 vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls; 9455521Sas200622 vsecattr->vsa_dfaclentp = aclp; 9465521Sas200622 vsecattr->vsa_aclcnt = numacls; 9475521Sas200622 } 9485521Sas200622 9495521Sas200622 /* Adjust if they're all defaults */ 9505521Sas200622 if (vsecattr->vsa_aclcnt == 0) { 9515521Sas200622 vsecattr->vsa_mask &= ~VSA_ACL; 9525521Sas200622 vsecattr->vsa_aclentp = NULL; 9535521Sas200622 } 9545521Sas200622 9555521Sas200622 /* Only directories can have defaults */ 9565521Sas200622 if (vsecattr->vsa_dfaclcnt && 9575521Sas200622 (acl_info->acl_flags & ACL_IS_DIR)) { 9585521Sas200622 error = ENOTDIR; 9595521Sas200622 } 9605521Sas200622 9615521Sas200622 break; 9625521Sas200622 9635521Sas200622 case ACE_T: 9645521Sas200622 if (acl_info->acl_cnt < 1 || 9655521Sas200622 acl_info->acl_cnt > MAX_ACL_ENTRIES) { 9665521Sas200622 error = EINVAL; 9675521Sas200622 break; 9685521Sas200622 } 9695521Sas200622 9705521Sas200622 vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 9715521Sas200622 vsecattr->vsa_aclcnt = acl_info->acl_cnt; 9725521Sas200622 vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL; 9735521Sas200622 *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); 9745521Sas200622 vsecattr->vsa_aclentsz = *aclbsize; 9755521Sas200622 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); 9765521Sas200622 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, 9775521Sas200622 *aclbsize); 9785521Sas200622 9795521Sas200622 break; 9805521Sas200622 9815521Sas200622 default: 9825521Sas200622 error = EINVAL; 9835521Sas200622 } 9845521Sas200622 9855521Sas200622 return (error); 9865521Sas200622 } 9875521Sas200622 9885521Sas200622 /* 9895521Sas200622 * smb_fsacl_inheritable 9905521Sas200622 * 9915521Sas200622 * Checks to see if there are any inheritable ACEs in the 9925521Sas200622 * given ZFS ACL. Returns the number of inheritable ACEs. 9935521Sas200622 * 9945521Sas200622 * The inherited ACL could be different based on the type of 9955521Sas200622 * new object (file/dir) specified by 'is_dir'. 9965521Sas200622 * 9975521Sas200622 * Note that the input ACL is a ZFS ACL not Windows ACL. 9985521Sas200622 * 9995521Sas200622 * Any ACE except creator owner/group: 10005521Sas200622 * 10015521Sas200622 * FI DI NP #F #D 10025521Sas200622 * ---- ---- ---- ---- ---- 10035521Sas200622 * - - ? 0 0 10045521Sas200622 * X - - 1 1 10055521Sas200622 * X - X 1 0 10065521Sas200622 * - X - 0 1 10075521Sas200622 * - X X 0 1 10085521Sas200622 * X X - 1 1 10095521Sas200622 * X X X 1 1 10105521Sas200622 * 10115521Sas200622 * Creator owner/group ACE: 10125521Sas200622 * 10135521Sas200622 * FI DI NP #F #D 10145521Sas200622 * ---- ---- ---- ---- ---- 10155521Sas200622 * - - ? 0 0 10165521Sas200622 * X - - 1r 1c 10175521Sas200622 * X - X 1r 0 10185521Sas200622 * - X - 0 2 10195521Sas200622 * - X X 0 1r 10205521Sas200622 * X X - 1r 2 10215521Sas200622 * X X X 1r 1r 10225521Sas200622 * 10235521Sas200622 * Legend: 10245521Sas200622 * 10255521Sas200622 * FI: File Inherit 10265521Sas200622 * DI: Dir Inherit 10275521Sas200622 * NP: No Propagate 10285521Sas200622 * #F: #ACE for a new file 10295521Sas200622 * #D: #ACE for a new dir 10305521Sas200622 * 10315521Sas200622 * X: bit is set 10325521Sas200622 * -: bit is not set 10335521Sas200622 * ?: don't care 10345521Sas200622 * 10355521Sas200622 * 1r: one owner/group ACE 10365521Sas200622 * 1c: one creator owner/group ACE 10375521Sas200622 */ 10385521Sas200622 static int 10395521Sas200622 smb_fsacl_inheritable(acl_t *zacl, int is_dir) 10405521Sas200622 { 10415521Sas200622 int numaces; 10425521Sas200622 int num_inheritable = 0; 10435521Sas200622 ace_t *zace; 10445521Sas200622 10455521Sas200622 if (zacl == NULL) 10465521Sas200622 return (0); 10475521Sas200622 10485521Sas200622 for (numaces = 0, zace = zacl->acl_aclp; 10495521Sas200622 numaces < zacl->acl_cnt; 10505521Sas200622 zace++, numaces++) { 10515521Sas200622 switch (zace->a_flags & ACE_FD_INHERIT_ACE) { 10525521Sas200622 case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 10535521Sas200622 /* 10545521Sas200622 * Files inherit an effective ACE. 10555521Sas200622 * 10565521Sas200622 * Dirs inherit an effective ACE. 10575521Sas200622 * The inherited ACE is inheritable unless the 10585521Sas200622 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 10595521Sas200622 */ 10605521Sas200622 num_inheritable++; 10615521Sas200622 10625521Sas200622 if (is_dir && ZACE_IS_CREATOR(zace) && 10635521Sas200622 (ZACE_IS_PROPAGATE(zace))) { 10645521Sas200622 num_inheritable++; 10655521Sas200622 } 10665521Sas200622 break; 10675521Sas200622 10685521Sas200622 case ACE_FILE_INHERIT_ACE: 10695521Sas200622 /* 10705521Sas200622 * Files inherit as an effective ACE. 10715521Sas200622 * 10725521Sas200622 * Dirs inherit an inherit-only ACE 10735521Sas200622 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 10745521Sas200622 * flag is also set. 10755521Sas200622 */ 10765521Sas200622 if (is_dir == 0) 10775521Sas200622 num_inheritable++; 10785521Sas200622 else if (ZACE_IS_PROPAGATE(zace)) 10795521Sas200622 num_inheritable++; 10805521Sas200622 break; 10815521Sas200622 10825521Sas200622 case ACE_DIRECTORY_INHERIT_ACE: 10835521Sas200622 /* 10845521Sas200622 * No effect on files 10855521Sas200622 * 10865521Sas200622 * Dirs inherit an effective ACE. 10875521Sas200622 * The inherited ACE is inheritable unless the 10885521Sas200622 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 10895521Sas200622 */ 10905521Sas200622 if (is_dir == 0) 10915521Sas200622 break; 10925521Sas200622 10935521Sas200622 num_inheritable++; 10945521Sas200622 10955521Sas200622 if (ZACE_IS_CREATOR(zace) && 10965521Sas200622 (ZACE_IS_PROPAGATE(zace))) 10975521Sas200622 num_inheritable++; 10985521Sas200622 break; 10995521Sas200622 11005521Sas200622 default: 11015521Sas200622 break; 11025521Sas200622 } 11035521Sas200622 } 11045521Sas200622 11055521Sas200622 return (num_inheritable); 11065521Sas200622 } 11075521Sas200622 11085521Sas200622 11095521Sas200622 /* 11105521Sas200622 * ACE Functions 11115521Sas200622 */ 11125521Sas200622 11135521Sas200622 /* 11145521Sas200622 * This is generic (ACL version 2) vs. object-specific 11155521Sas200622 * (ACL version 4) ACE types. 11165521Sas200622 */ 11175521Sas200622 boolean_t 11185521Sas200622 smb_ace_is_generic(int type) 11195521Sas200622 { 11205521Sas200622 switch (type) { 11215521Sas200622 case ACE_ACCESS_ALLOWED_ACE_TYPE: 11225521Sas200622 case ACE_ACCESS_DENIED_ACE_TYPE: 11235521Sas200622 case ACE_SYSTEM_AUDIT_ACE_TYPE: 11245521Sas200622 case ACE_SYSTEM_ALARM_ACE_TYPE: 11255521Sas200622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 11265521Sas200622 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 11275521Sas200622 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 11285521Sas200622 case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE: 11295521Sas200622 return (B_TRUE); 11305521Sas200622 11315521Sas200622 default: 11325521Sas200622 break; 11335521Sas200622 } 11345521Sas200622 11355521Sas200622 return (B_FALSE); 11365521Sas200622 } 11375521Sas200622 11385521Sas200622 boolean_t 11395521Sas200622 smb_ace_is_access(int type) 11405521Sas200622 { 11415521Sas200622 switch (type) { 11425521Sas200622 case ACE_ACCESS_ALLOWED_ACE_TYPE: 11435521Sas200622 case ACE_ACCESS_DENIED_ACE_TYPE: 11445521Sas200622 case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: 11455521Sas200622 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 11465521Sas200622 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 11475521Sas200622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 11485521Sas200622 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 11495521Sas200622 case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 11505521Sas200622 case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 11515521Sas200622 return (B_TRUE); 11525521Sas200622 11535521Sas200622 default: 11545521Sas200622 break; 11555521Sas200622 } 11565521Sas200622 11575521Sas200622 return (B_FALSE); 11585521Sas200622 } 11595521Sas200622 11605521Sas200622 boolean_t 11615521Sas200622 smb_ace_is_audit(int type) 11625521Sas200622 { 11635521Sas200622 switch (type) { 11645521Sas200622 case ACE_SYSTEM_AUDIT_ACE_TYPE: 11655521Sas200622 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 11665521Sas200622 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 11675521Sas200622 case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 11685521Sas200622 return (B_TRUE); 11695521Sas200622 11705521Sas200622 default: 11715521Sas200622 break; 11725521Sas200622 } 11735521Sas200622 11745521Sas200622 return (B_FALSE); 11755521Sas200622 } 11765521Sas200622 11775521Sas200622 /* 11785521Sas200622 * smb_ace_len 11795521Sas200622 * 11805521Sas200622 * Returns the length of the given ACE as it appears in an 11815521Sas200622 * ACL on the wire (i.e. a flat buffer which contains the SID) 11825521Sas200622 */ 11835521Sas200622 static uint16_t 11845521Sas200622 smb_ace_len(smb_ace_t *ace) 11855521Sas200622 { 11865521Sas200622 ASSERT(ace); 11875521Sas200622 ASSERT(ace->se_sid); 11885521Sas200622 11895521Sas200622 if (ace == NULL) 11905521Sas200622 return (0); 11915521Sas200622 11925521Sas200622 return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) + 1193*6432Sas200622 smb_sid_len(ace->se_sid)); 11945521Sas200622 } 11955521Sas200622 11965331Samw static void 11975331Samw smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir) 11985331Samw { 11995331Samw *zace = *dir_zace; 12005331Samw if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace))) 12015331Samw zace->a_flags &= ~ACE_INHERIT_FLAGS; 12025331Samw zace->a_flags |= ACE_INHERITED_ACE; 12035331Samw 12045331Samw /* 12055331Samw * Replace creator owner/group ACEs with 12065331Samw * actual owner/group ACEs. 12075331Samw */ 12085331Samw if (ZACE_IS_CREATOR_OWNER(dir_zace)) { 12095331Samw zace->a_who = (uid_t)-1; 12105331Samw zace->a_flags |= ACE_OWNER; 12115331Samw } else if (ZACE_IS_CREATOR_GROUP(dir_zace)) { 12125331Samw zace->a_who = (uid_t)-1; 12135331Samw zace->a_flags |= ACE_GROUP; 12145331Samw } 12155331Samw } 12165331Samw 12175521Sas200622 /* 12185521Sas200622 * smb_ace_mask_g2s 12195521Sas200622 * 12205521Sas200622 * Converts generic access bits in the given mask (if any) 12215521Sas200622 * to file specific bits. Generic access masks shouldn't be 12225521Sas200622 * stored in filesystem ACEs. 12235521Sas200622 */ 12245521Sas200622 static uint32_t 12255521Sas200622 smb_ace_mask_g2s(uint32_t mask) 12265521Sas200622 { 12275521Sas200622 if (mask & GENERIC_ALL) { 12285521Sas200622 mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE 12295521Sas200622 | GENERIC_EXECUTE); 12305521Sas200622 12315521Sas200622 mask |= FILE_ALL_ACCESS; 12325521Sas200622 return (mask); 12335521Sas200622 } 12345521Sas200622 12355521Sas200622 if (mask & GENERIC_READ) { 12365521Sas200622 mask &= ~GENERIC_READ; 12375521Sas200622 mask |= FILE_GENERIC_READ; 12385521Sas200622 } 12395521Sas200622 12405521Sas200622 if (mask & GENERIC_WRITE) { 12415521Sas200622 mask &= ~GENERIC_WRITE; 12425521Sas200622 mask |= FILE_GENERIC_WRITE; 12435521Sas200622 } 12445521Sas200622 12455521Sas200622 if (mask & GENERIC_EXECUTE) { 12465521Sas200622 mask &= ~GENERIC_EXECUTE; 12475521Sas200622 mask |= FILE_GENERIC_EXECUTE; 12485521Sas200622 } 12495521Sas200622 12505521Sas200622 return (mask); 12515521Sas200622 } 12525521Sas200622 12535331Samw static uint16_t 12545331Samw smb_ace_flags_tozfs(uint8_t c_flags, int isdir) 12555331Samw { 12565331Samw uint16_t z_flags = 0; 12575331Samw 12585331Samw if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG) 12595331Samw z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 12605331Samw 12615331Samw if (c_flags & FAILED_ACCESS_ACE_FLAG) 12625331Samw z_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 12635331Samw 12645331Samw if (c_flags & INHERITED_ACE) 12655331Samw z_flags |= ACE_INHERITED_ACE; 12665331Samw 12675331Samw /* 12685331Samw * ZFS doesn't like any inheritance flags to be set on a 12695331Samw * file's ACE, only directories. Windows doesn't care. 12705331Samw */ 12715331Samw if (isdir) 12725331Samw z_flags |= (c_flags & ACE_INHERIT_FLAGS); 12735331Samw 12745331Samw return (z_flags); 12755331Samw } 12765331Samw 12775331Samw static uint8_t 12785331Samw smb_ace_flags_fromzfs(uint16_t z_flags) 12795331Samw { 12805331Samw uint8_t c_flags; 12815331Samw 12825331Samw c_flags = z_flags & ACE_INHERIT_FLAGS; 12835331Samw 12845331Samw if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 12855331Samw c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG; 12865331Samw 12875331Samw if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG) 12885331Samw c_flags |= FAILED_ACCESS_ACE_FLAG; 12895331Samw 12905331Samw if (z_flags & ACE_INHERITED_ACE) 12915331Samw c_flags |= INHERITED_ACE; 12925331Samw 12935331Samw return (c_flags); 12945331Samw } 12955331Samw 12965521Sas200622 static boolean_t 12975521Sas200622 smb_ace_isvalid(smb_ace_t *ace, int which_acl) 12985331Samw { 12995521Sas200622 uint16_t min_len; 13005521Sas200622 13015521Sas200622 min_len = sizeof (smb_acehdr_t); 13025521Sas200622 13035521Sas200622 if (ace->se_hdr.se_bsize < min_len) 13045521Sas200622 return (B_FALSE); 13055521Sas200622 13065521Sas200622 if (smb_ace_is_access(ace->se_hdr.se_type) && 13075521Sas200622 (which_acl != SMB_DACL_SECINFO)) 13085521Sas200622 return (B_FALSE); 13095331Samw 13105521Sas200622 if (smb_ace_is_audit(ace->se_hdr.se_type) && 13115521Sas200622 (which_acl != SMB_SACL_SECINFO)) 13125521Sas200622 return (B_FALSE); 13135521Sas200622 13145521Sas200622 if (smb_ace_is_generic(ace->se_hdr.se_type)) { 1315*6432Sas200622 if (!smb_sid_isvalid(ace->se_sid)) 13165521Sas200622 return (B_FALSE); 13175521Sas200622 13185521Sas200622 min_len += sizeof (ace->se_mask); 1319*6432Sas200622 min_len += smb_sid_len(ace->se_sid); 13205521Sas200622 13215521Sas200622 if (ace->se_hdr.se_bsize < min_len) 13225521Sas200622 return (B_FALSE); 13235331Samw } 13245331Samw 13255521Sas200622 /* 13265521Sas200622 * object-specific ACE validation will be added later. 13275521Sas200622 */ 13285521Sas200622 return (B_TRUE); 13295331Samw } 1330