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 /* 225331Samw * Copyright 2007 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> 29*5521Sas200622 #include <acl/acl_common.h> 305331Samw #include <smbsrv/ntsid.h> 315331Samw #include <smbsrv/smb_fsops.h> 325331Samw #include <smbsrv/smb_idmap.h> 33*5521Sas200622 #include <smbsrv/smb_kproto.h> 34*5521Sas200622 #include <smbsrv/smbvar.h> 35*5521Sas200622 #include <smbsrv/ntstatus.h> 36*5521Sas200622 #include <smbsrv/ntaccess.h> 375331Samw 385331Samw #define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE) 395331Samw 405331Samw #define ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER) 415331Samw #define ZACE_IS_OWNGRP(zace) \ 425331Samw ((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP)) 435331Samw 445331Samw #define ZACE_IS_USER(zace) \ 455331Samw (((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace))) 465331Samw #define ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP) 475331Samw #define ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE) 485331Samw 495331Samw #define ZACE_IS_PROPAGATE(zace) \ 505331Samw ((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0) 515331Samw 525331Samw #define ZACE_IS_CREATOR_OWNER(zace) \ 535331Samw (ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID)) 545331Samw 555331Samw #define ZACE_IS_CREATOR_GROUP(zace) \ 565331Samw (ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID)) 575331Samw 585331Samw #define ZACE_IS_CREATOR(zace) \ 595331Samw (ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace)) 605331Samw 615331Samw /* 625331Samw * ACE groups within a DACL 635331Samw * 645331Samw * This is from lower to higher ACE order priority 655331Samw */ 665331Samw #define SMB_AG_START 0 675331Samw #define SMB_AG_ALW_INHRT 0 685331Samw #define SMB_AG_DNY_INHRT 1 695331Samw #define SMB_AG_ALW_DRCT 2 705331Samw #define SMB_AG_DNY_DRCT 3 715331Samw #define SMB_AG_NUM 4 725331Samw 735331Samw /* 74*5521Sas200622 * SID for Everyone group: S-1-1-0. 75*5521Sas200622 */ 76*5521Sas200622 nt_sid_t everyone_sid = { 77*5521Sas200622 NT_SID_REVISION, 78*5521Sas200622 1, 79*5521Sas200622 NT_SECURITY_WORLD_AUTH, 80*5521Sas200622 { 0 } 81*5521Sas200622 }; 82*5521Sas200622 83*5521Sas200622 #define DEFAULT_DACL_ACENUM 2 84*5521Sas200622 /* 85*5521Sas200622 * Default ACL: 86*5521Sas200622 * owner: full access 87*5521Sas200622 * SYSTEM: full access 88*5521Sas200622 */ 89*5521Sas200622 static ace_t default_dacl[DEFAULT_DACL_ACENUM] = { 90*5521Sas200622 { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, 91*5521Sas200622 { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP, 92*5521Sas200622 ACE_ACCESS_ALLOWED_ACE_TYPE } 93*5521Sas200622 }; 94*5521Sas200622 95*5521Sas200622 /* 96*5521Sas200622 * Note: 975331Samw * 98*5521Sas200622 * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format 99*5521Sas200622 * smb_fsacl_xxx functions work with acl_t which represents the Solaris native 100*5521Sas200622 * format 101*5521Sas200622 */ 102*5521Sas200622 103*5521Sas200622 static idmap_stat smb_acl_getsids(smb_idmap_batch_t *, acl_t *, uid_t, gid_t); 104*5521Sas200622 static acl_t *smb_acl_null_empty(boolean_t null); 105*5521Sas200622 106*5521Sas200622 static int smb_fsacl_inheritable(acl_t *, int); 107*5521Sas200622 108*5521Sas200622 109*5521Sas200622 static void smb_ace_inherit(ace_t *, ace_t *, int); 110*5521Sas200622 static boolean_t smb_ace_isvalid(smb_ace_t *, int); 111*5521Sas200622 static uint16_t smb_ace_len(smb_ace_t *); 112*5521Sas200622 static uint32_t smb_ace_mask_g2s(uint32_t); 113*5521Sas200622 static uint16_t smb_ace_flags_tozfs(uint8_t, int); 114*5521Sas200622 static uint8_t smb_ace_flags_fromzfs(uint16_t); 115*5521Sas200622 116*5521Sas200622 smb_acl_t * 117*5521Sas200622 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt) 118*5521Sas200622 { 119*5521Sas200622 smb_acl_t *acl; 120*5521Sas200622 int size; 121*5521Sas200622 122*5521Sas200622 size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t)); 123*5521Sas200622 acl = kmem_zalloc(size, KM_SLEEP); 124*5521Sas200622 acl->sl_revision = revision; 125*5521Sas200622 acl->sl_bsize = bsize; 126*5521Sas200622 acl->sl_acecnt = acecnt; 127*5521Sas200622 acl->sl_aces = (smb_ace_t *)(acl + 1); 128*5521Sas200622 129*5521Sas200622 list_create(&acl->sl_sorted, sizeof (smb_ace_t), 130*5521Sas200622 offsetof(smb_ace_t, se_sln)); 131*5521Sas200622 return (acl); 132*5521Sas200622 } 133*5521Sas200622 134*5521Sas200622 void 135*5521Sas200622 smb_acl_free(smb_acl_t *acl) 136*5521Sas200622 { 137*5521Sas200622 int i, size; 138*5521Sas200622 void *ace; 139*5521Sas200622 140*5521Sas200622 if (acl == NULL) 141*5521Sas200622 return; 142*5521Sas200622 143*5521Sas200622 for (i = 0; i < acl->sl_acecnt; i++) { 144*5521Sas200622 MEM_FREE("smbsrv", acl->sl_aces[i].se_sid); 145*5521Sas200622 } 146*5521Sas200622 147*5521Sas200622 while ((ace = list_head(&acl->sl_sorted)) != NULL) 148*5521Sas200622 list_remove(&acl->sl_sorted, ace); 149*5521Sas200622 list_destroy(&acl->sl_sorted); 150*5521Sas200622 151*5521Sas200622 size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t)); 152*5521Sas200622 kmem_free(acl, size); 153*5521Sas200622 } 154*5521Sas200622 155*5521Sas200622 /* 156*5521Sas200622 * smb_acl_len 157*5521Sas200622 * 158*5521Sas200622 * Returns the size of given ACL in bytes. Note that this 159*5521Sas200622 * is not an in-memory size, it's the ACL's size as it would 160*5521Sas200622 * appear on the wire 161*5521Sas200622 */ 162*5521Sas200622 uint16_t 163*5521Sas200622 smb_acl_len(smb_acl_t *acl) 164*5521Sas200622 { 165*5521Sas200622 if (acl == NULL) 166*5521Sas200622 return (0); 167*5521Sas200622 168*5521Sas200622 return (acl->sl_bsize); 169*5521Sas200622 } 170*5521Sas200622 171*5521Sas200622 boolean_t 172*5521Sas200622 smb_acl_isvalid(smb_acl_t *acl, int which_acl) 173*5521Sas200622 { 174*5521Sas200622 int i; 175*5521Sas200622 176*5521Sas200622 if (acl->sl_bsize < SMB_ACL_HDRSIZE) 177*5521Sas200622 return (B_FALSE); 178*5521Sas200622 179*5521Sas200622 if (acl->sl_revision != ACL_REVISION) { 180*5521Sas200622 /* 181*5521Sas200622 * we are rejecting ACLs with object-specific ACEs for now 182*5521Sas200622 */ 183*5521Sas200622 return (B_FALSE); 184*5521Sas200622 } 185*5521Sas200622 186*5521Sas200622 for (i = 0; i < acl->sl_acecnt; i++) { 187*5521Sas200622 if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl)) 188*5521Sas200622 return (B_FALSE); 189*5521Sas200622 } 190*5521Sas200622 191*5521Sas200622 return (B_TRUE); 192*5521Sas200622 } 193*5521Sas200622 194*5521Sas200622 /* 195*5521Sas200622 * smb_acl_sort 196*5521Sas200622 * 197*5521Sas200622 * Sorts the given ACL in place if it needs to be sorted. 1985331Samw * 1995331Samw * The following is an excerpt from MSDN website. 2005331Samw * 2015331Samw * Order of ACEs in a DACL 2025331Samw * 2035331Samw * For Windows NT versions 4.0 and earlier, the preferred order of ACEs 2045331Samw * is simple: In a DACL, all access-denied ACEs should precede any 2055331Samw * access-allowed ACEs. 2065331Samw * 2075331Samw * For Windows 2000 or later, the proper order of ACEs is more complicated 2085331Samw * because of the introduction of object-specific ACEs and automatic 2095331Samw * inheritance. 2105331Samw * 2115331Samw * The following describes the preferred order: 2125331Samw * 2135331Samw * To ensure that noninherited ACEs have precedence over inherited ACEs, 2145331Samw * place all noninherited ACEs in a group before any inherited ACEs. This 2155331Samw * ordering ensures, for example, that a noninherited access-denied ACE 2165331Samw * is enforced regardless of any inherited ACE that allows access. 2175331Samw * Within the groups of noninherited ACEs and inherited ACEs, order ACEs 2185331Samw * according to ACE type, as the following shows: 2195331Samw * . Access-denied ACEs that apply to the object itself 2205331Samw * . Access-denied ACEs that apply to a subobject of the 2215331Samw * object, such as a property set or property 2225331Samw * . Access-allowed ACEs that apply to the object itself 2235331Samw * . Access-allowed ACEs that apply to a subobject of the object 2245331Samw * 225*5521Sas200622 * So, here is the desired ACE order 2265331Samw * 2275331Samw * deny-direct, allow-direct, deny-inherited, allow-inherited 2285331Samw * 229*5521Sas200622 * Of course, not all ACE types are required in an ACL. 2305331Samw */ 231*5521Sas200622 void 2325331Samw smb_acl_sort(smb_acl_t *acl) 2335331Samw { 234*5521Sas200622 list_t ace_grps[SMB_AG_NUM]; 235*5521Sas200622 list_t *alist; 2365331Samw smb_ace_t *ace; 2375331Samw uint8_t ace_flags; 238*5521Sas200622 int ag, i; 2395331Samw 2405331Samw ASSERT(acl); 2415331Samw 2425331Samw if (acl->sl_acecnt == 0) { 2435331Samw /* 2445331Samw * ACL with no entry is a valid ACL and it means 2455331Samw * no access for anybody. 2465331Samw */ 247*5521Sas200622 return; 2485331Samw } 2495331Samw 2505331Samw for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { 251*5521Sas200622 list_create(&ace_grps[i], sizeof (smb_ace_t), 252*5521Sas200622 offsetof(smb_ace_t, se_sln)); 2535331Samw } 2545331Samw 255*5521Sas200622 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) { 256*5521Sas200622 ace_flags = ace->se_hdr.se_flags; 2575331Samw 258*5521Sas200622 switch (ace->se_hdr.se_type) { 2595331Samw case ACCESS_DENIED_ACE_TYPE: 260*5521Sas200622 ag = (ace_flags & INHERITED_ACE) ? 261*5521Sas200622 SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT; 2625331Samw break; 2635331Samw 2645331Samw case ACCESS_ALLOWED_ACE_TYPE: 265*5521Sas200622 ag = (ace_flags & INHERITED_ACE) ? 266*5521Sas200622 SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT; 2675331Samw break; 2685331Samw 2695331Samw default: 2705331Samw /* 2715331Samw * This is the lowest priority group so we put 2725331Samw * evertything unknown here. 2735331Samw */ 2745331Samw ag = SMB_AG_ALW_INHRT; 2755331Samw break; 2765331Samw } 2775331Samw 278*5521Sas200622 /* Add the ACE to the selected group */ 279*5521Sas200622 list_insert_tail(&ace_grps[ag], ace); 2805331Samw } 2815331Samw 282*5521Sas200622 /* 283*5521Sas200622 * start with highest priority ACE group and append 284*5521Sas200622 * the ACEs to the ACL. 285*5521Sas200622 */ 286*5521Sas200622 for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { 287*5521Sas200622 alist = &ace_grps[i]; 288*5521Sas200622 while ((ace = list_head(alist)) != NULL) { 289*5521Sas200622 list_remove(alist, ace); 290*5521Sas200622 list_insert_tail(&acl->sl_sorted, ace); 291*5521Sas200622 } 292*5521Sas200622 list_destroy(alist); 2935331Samw } 2945331Samw } 2955331Samw 296*5521Sas200622 /* 297*5521Sas200622 * smb_acl_from_zfs 298*5521Sas200622 * 299*5521Sas200622 * Converts given ZFS ACL to a Windows ACL. 300*5521Sas200622 * 301*5521Sas200622 * A pointer to allocated memory for the Win ACL will be 302*5521Sas200622 * returned upon successful conversion. 303*5521Sas200622 */ 304*5521Sas200622 smb_acl_t * 305*5521Sas200622 smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid) 3065331Samw { 307*5521Sas200622 ace_t *zace; 308*5521Sas200622 int numaces; 309*5521Sas200622 smb_acl_t *acl; 3105331Samw smb_ace_t *ace; 311*5521Sas200622 smb_idmap_batch_t sib; 312*5521Sas200622 smb_idmap_t *sim; 313*5521Sas200622 idmap_stat idm_stat; 3145331Samw 315*5521Sas200622 idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, 316*5521Sas200622 SMB_IDMAP_ID2SID); 317*5521Sas200622 if (idm_stat != IDMAP_SUCCESS) 3185331Samw return (NULL); 3195331Samw 320*5521Sas200622 if (smb_acl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) { 321*5521Sas200622 smb_idmap_batch_destroy(&sib); 322*5521Sas200622 return (NULL); 3235331Samw } 3245331Samw 325*5521Sas200622 acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt); 3265331Samw 327*5521Sas200622 sim = sib.sib_maps; 328*5521Sas200622 for (numaces = 0, zace = zacl->acl_aclp; 329*5521Sas200622 numaces < zacl->acl_cnt; 330*5521Sas200622 zace++, numaces++, sim++) { 331*5521Sas200622 ASSERT(sim->sim_sid); 332*5521Sas200622 if (sim->sim_sid == NULL) { 333*5521Sas200622 smb_acl_free(acl); 334*5521Sas200622 acl = NULL; 335*5521Sas200622 break; 336*5521Sas200622 } 3375331Samw 338*5521Sas200622 ace = &acl->sl_aces[numaces]; 339*5521Sas200622 ace->se_hdr.se_type = zace->a_type; 340*5521Sas200622 ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags); 341*5521Sas200622 ace->se_mask = zace->a_access_mask; 342*5521Sas200622 ace->se_sid = nt_sid_dup(sim->sim_sid); 343*5521Sas200622 ace->se_hdr.se_bsize = smb_ace_len(ace); 344*5521Sas200622 345*5521Sas200622 acl->sl_bsize += ace->se_hdr.se_bsize; 3465331Samw } 3475331Samw 348*5521Sas200622 smb_idmap_batch_destroy(&sib); 349*5521Sas200622 return (acl); 3505331Samw } 3515331Samw 3525331Samw /* 353*5521Sas200622 * smb_acl_to_zfs 3545331Samw * 355*5521Sas200622 * Converts given Windows ACL to a ZFS ACL. 3565331Samw * 357*5521Sas200622 * fs_acl will contain a pointer to the created ZFS ACL. 358*5521Sas200622 * The allocated memory should be freed by calling 359*5521Sas200622 * smb_fsacl_free(). 3605331Samw * 361*5521Sas200622 * Since the output parameter, fs_acl, is allocated in this 362*5521Sas200622 * function, the caller has to make sure *fs_acl is NULL which 363*5521Sas200622 * means it's not pointing to any memory. 3645331Samw */ 3655331Samw uint32_t 366*5521Sas200622 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) 3675331Samw { 368*5521Sas200622 smb_ace_t *ace; 369*5521Sas200622 acl_t *zacl; 370*5521Sas200622 ace_t *zace; 371*5521Sas200622 smb_idmap_batch_t sib; 372*5521Sas200622 smb_idmap_t *sim; 373*5521Sas200622 idmap_stat idm_stat; 374*5521Sas200622 int i, isdir; 3755331Samw 376*5521Sas200622 ASSERT(fs_acl); 377*5521Sas200622 ASSERT(*fs_acl == NULL); 378*5521Sas200622 379*5521Sas200622 if (acl && !smb_acl_isvalid(acl, which_acl)) 380*5521Sas200622 return (NT_STATUS_INVALID_ACL); 381*5521Sas200622 382*5521Sas200622 if ((acl == NULL) || (acl->sl_acecnt == 0)) { 383*5521Sas200622 if (which_acl == SMB_DACL_SECINFO) { 384*5521Sas200622 *fs_acl = smb_acl_null_empty(acl == NULL); 385*5521Sas200622 } 386*5521Sas200622 387*5521Sas200622 return (NT_STATUS_SUCCESS); 3885331Samw } 3895331Samw 390*5521Sas200622 idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, 391*5521Sas200622 SMB_IDMAP_SID2ID); 392*5521Sas200622 if (idm_stat != IDMAP_SUCCESS) 393*5521Sas200622 return (NT_STATUS_INTERNAL_ERROR); 394*5521Sas200622 395*5521Sas200622 isdir = ((flags & ACL_IS_DIR) == ACL_IS_DIR); 396*5521Sas200622 397*5521Sas200622 zacl = smb_fsacl_alloc(acl->sl_acecnt, flags); 398*5521Sas200622 399*5521Sas200622 zace = zacl->acl_aclp; 400*5521Sas200622 ace = acl->sl_aces; 401*5521Sas200622 sim = sib.sib_maps; 402*5521Sas200622 403*5521Sas200622 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 404*5521Sas200622 zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES; 405*5521Sas200622 zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); 406*5521Sas200622 zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags, 407*5521Sas200622 isdir); 408*5521Sas200622 409*5521Sas200622 if (nt_sid_is_equal(ace->se_sid, &everyone_sid)) 410*5521Sas200622 zace->a_flags |= ACE_EVERYONE; 411*5521Sas200622 else { 412*5521Sas200622 sim->sim_id = &zace->a_who; 413*5521Sas200622 idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, 414*5521Sas200622 ace->se_sid, -1); 415*5521Sas200622 416*5521Sas200622 if (idm_stat != IDMAP_SUCCESS) { 417*5521Sas200622 smb_fsacl_free(zacl); 418*5521Sas200622 smb_idmap_batch_destroy(&sib); 419*5521Sas200622 return (NT_STATUS_INTERNAL_ERROR); 420*5521Sas200622 } 421*5521Sas200622 } 4225331Samw } 4235331Samw 424*5521Sas200622 idm_stat = smb_idmap_batch_getmappings(&sib); 425*5521Sas200622 if (idm_stat != IDMAP_SUCCESS) { 426*5521Sas200622 smb_fsacl_free(zacl); 427*5521Sas200622 smb_idmap_batch_destroy(&sib); 428*5521Sas200622 return (NT_STATUS_NONE_MAPPED); 4295331Samw } 4305331Samw 431*5521Sas200622 /* 432*5521Sas200622 * Set the ACEs group flag based on the type of ID returned. 433*5521Sas200622 */ 434*5521Sas200622 zace = zacl->acl_aclp; 435*5521Sas200622 ace = acl->sl_aces; 436*5521Sas200622 sim = sib.sib_maps; 437*5521Sas200622 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 438*5521Sas200622 if (zace->a_flags & ACE_EVERYONE) 439*5521Sas200622 continue; 440*5521Sas200622 441*5521Sas200622 if (sim->sim_idtype == SMB_IDMAP_GROUP) 442*5521Sas200622 zace->a_flags |= ACE_IDENTIFIER_GROUP; 4435331Samw } 4445331Samw 445*5521Sas200622 smb_idmap_batch_destroy(&sib); 446*5521Sas200622 447*5521Sas200622 *fs_acl = zacl; 448*5521Sas200622 return (NT_STATUS_SUCCESS); 4495331Samw } 4505331Samw 4515331Samw /* 4525331Samw * smb_acl_getsids 4535331Samw * 4545331Samw * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs. 4555331Samw */ 4565331Samw static idmap_stat 4575331Samw smb_acl_getsids(smb_idmap_batch_t *sib, acl_t *zacl, uid_t uid, gid_t gid) 4585331Samw { 4595331Samw ace_t *zace; 4605331Samw idmap_stat idm_stat; 4615331Samw smb_idmap_t *sim; 4625331Samw uid_t id; 4635331Samw int i, idtype; 4645331Samw 4655331Samw sim = sib->sib_maps; 4665331Samw 4675331Samw for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; 4685331Samw zace++, i++, sim++) { 4695331Samw switch (zace->a_flags & ACE_TYPE_FLAGS) { 4705331Samw case ACE_OWNER: 4715331Samw id = uid; 4725331Samw idtype = SMB_IDMAP_USER; 4735331Samw break; 4745331Samw 4755331Samw case (ACE_GROUP | ACE_IDENTIFIER_GROUP): 4765331Samw /* owning group */ 4775331Samw id = gid; 4785331Samw idtype = SMB_IDMAP_GROUP; 4795331Samw break; 4805331Samw 4815331Samw case ACE_IDENTIFIER_GROUP: 4825331Samw /* regular group */ 4835331Samw id = zace->a_who; 4845331Samw idtype = SMB_IDMAP_GROUP; 4855331Samw break; 4865331Samw 4875331Samw case ACE_EVERYONE: 4885331Samw idtype = SMB_IDMAP_EVERYONE; 4895331Samw break; 4905331Samw 4915331Samw default: 4925331Samw /* user entry */ 4935331Samw id = zace->a_who; 4945331Samw idtype = SMB_IDMAP_USER; 4955331Samw } 4965331Samw 4975331Samw idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim, 4985331Samw id, idtype); 4995331Samw 5005331Samw if (idm_stat != IDMAP_SUCCESS) { 5015331Samw return (idm_stat); 5025331Samw } 5035331Samw } 5045331Samw 5055331Samw idm_stat = smb_idmap_batch_getmappings(sib); 5065331Samw return (idm_stat); 5075331Samw } 5085331Samw 5095331Samw /* 5105331Samw * smb_acl_null_empty 5115331Samw * 5125331Samw * NULL DACL means everyone full-access 5135331Samw * Empty DACL means everyone full-deny 5145331Samw * 5155331Samw * ZFS ACL must have at least one entry so smb server has 5165331Samw * to simulate the aforementioned expected behavior by adding 5175331Samw * an entry in case the requested DACL is null or empty. Adding 5185331Samw * a everyone full-deny entry has proved to be problematic in 5195331Samw * tests since a deny entry takes precedence over allow entries. 5205331Samw * So, instead of adding a everyone full-deny, an owner ACE with 5215331Samw * owner implicit permissions will be set. 5225331Samw */ 523*5521Sas200622 static acl_t * 524*5521Sas200622 smb_acl_null_empty(boolean_t null) 5255331Samw { 5265331Samw acl_t *zacl; 5275331Samw ace_t *zace; 5285331Samw 529*5521Sas200622 zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT); 5305331Samw zace = zacl->acl_aclp; 5315331Samw 5325331Samw zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 5335331Samw if (null) { 5345331Samw zace->a_access_mask = ACE_ALL_PERMS; 5355331Samw zace->a_flags = ACE_EVERYONE; 5365331Samw } else { 5375331Samw zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | 5385331Samw ACE_READ_ATTRIBUTES; 5395331Samw zace->a_flags = ACE_OWNER; 5405331Samw } 5415331Samw 5425331Samw return (zacl); 5435331Samw } 5445331Samw 5455331Samw /* 546*5521Sas200622 * FS ACL (acl_t) Functions 5475331Samw */ 548*5521Sas200622 acl_t * 549*5521Sas200622 smb_fsacl_alloc(int acenum, int flags) 5505331Samw { 551*5521Sas200622 acl_t *acl; 5525331Samw 553*5521Sas200622 acl = acl_alloc(ACE_T); 554*5521Sas200622 acl->acl_cnt = acenum; 555*5521Sas200622 acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP); 556*5521Sas200622 acl->acl_flags = flags; 557*5521Sas200622 return (acl); 558*5521Sas200622 } 5595331Samw 560*5521Sas200622 void 561*5521Sas200622 smb_fsacl_free(acl_t *acl) 562*5521Sas200622 { 563*5521Sas200622 if (acl) 564*5521Sas200622 acl_free(acl); 565*5521Sas200622 } 5665331Samw 567*5521Sas200622 /* 568*5521Sas200622 * smb_fsop_aclmerge 569*5521Sas200622 * 570*5521Sas200622 * smb_fsop_aclread/write routines which interact with filesystem 571*5521Sas200622 * work with single ACL. This routine merges given DACL and SACL 572*5521Sas200622 * which might have been created during CIFS to FS conversion into 573*5521Sas200622 * one single ACL. 574*5521Sas200622 */ 575*5521Sas200622 acl_t * 576*5521Sas200622 smb_fsacl_merge(acl_t *dacl, acl_t *sacl) 577*5521Sas200622 { 578*5521Sas200622 acl_t *acl; 579*5521Sas200622 int dacl_size; 5805331Samw 581*5521Sas200622 ASSERT(dacl); 582*5521Sas200622 ASSERT(sacl); 5835331Samw 584*5521Sas200622 acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags); 585*5521Sas200622 dacl_size = dacl->acl_cnt * dacl->acl_entry_size; 586*5521Sas200622 bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size); 587*5521Sas200622 bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size, 588*5521Sas200622 sacl->acl_cnt * sacl->acl_entry_size); 5895331Samw 590*5521Sas200622 return (acl); 5915331Samw } 5925331Samw 5935331Samw /* 594*5521Sas200622 * smb_fsacl_split 5955331Samw * 596*5521Sas200622 * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on 597*5521Sas200622 * the 'which_acl' parameter. Note that output dacl/sacl parameters could be 598*5521Sas200622 * NULL even if they're specified in 'which_acl', which means the target 599*5521Sas200622 * doesn't have any access and/or audit ACEs. 6005331Samw */ 601*5521Sas200622 void 602*5521Sas200622 smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl) 6035331Samw { 6045331Samw ace_t *zace; 605*5521Sas200622 ace_t *access_ace; 606*5521Sas200622 ace_t *audit_ace; 607*5521Sas200622 int naccess, naudit; 608*5521Sas200622 int get_dacl, get_sacl; 609*5521Sas200622 int i; 610*5521Sas200622 611*5521Sas200622 *dacl = *sacl = NULL; 612*5521Sas200622 naccess = naudit = 0; 613*5521Sas200622 get_dacl = (which_acl & SMB_DACL_SECINFO); 614*5521Sas200622 get_sacl = (which_acl & SMB_SACL_SECINFO); 6155331Samw 616*5521Sas200622 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { 617*5521Sas200622 if (get_dacl && smb_ace_is_access(zace->a_type)) 618*5521Sas200622 naccess++; 619*5521Sas200622 else if (get_sacl && smb_ace_is_audit(zace->a_type)) 620*5521Sas200622 naudit++; 621*5521Sas200622 } 6225331Samw 623*5521Sas200622 if (naccess) { 624*5521Sas200622 *dacl = smb_fsacl_alloc(naccess, zacl->acl_flags); 625*5521Sas200622 access_ace = (*dacl)->acl_aclp; 626*5521Sas200622 } 6275331Samw 628*5521Sas200622 if (naudit) { 629*5521Sas200622 *sacl = smb_fsacl_alloc(naudit, zacl->acl_flags); 630*5521Sas200622 audit_ace = (*sacl)->acl_aclp; 631*5521Sas200622 } 6325331Samw 633*5521Sas200622 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) { 634*5521Sas200622 if (get_dacl && smb_ace_is_access(zace->a_type)) { 635*5521Sas200622 *access_ace = *zace; 636*5521Sas200622 access_ace++; 637*5521Sas200622 } else if (get_sacl && smb_ace_is_audit(zace->a_type)) { 638*5521Sas200622 *audit_ace = *zace; 639*5521Sas200622 audit_ace++; 6405331Samw } 6415331Samw } 6425331Samw } 6435331Samw 6445331Samw /* 645*5521Sas200622 * ACE Inheritance Rules 646*5521Sas200622 * 647*5521Sas200622 * The system propagates inheritable ACEs to child objects according to a 648*5521Sas200622 * set of inheritance rules. The system places inherited ACEs in the child's 649*5521Sas200622 * DACL according to the preferred order of ACEs in a DACL. For Windows 650*5521Sas200622 * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs. 651*5521Sas200622 * 652*5521Sas200622 * The following table shows the ACEs inherited by container and noncontainer 653*5521Sas200622 * child objects for different combinations of inheritance flags. These 654*5521Sas200622 * inheritance rules work the same for both DACLs and SACLs. 655*5521Sas200622 * 656*5521Sas200622 * Parent ACE type Effect on Child ACL 657*5521Sas200622 * ----------------------- ------------------- 658*5521Sas200622 * OBJECT_INHERIT_ACE only Noncontainer child objects: 659*5521Sas200622 * Inherited as an effective ACE. 660*5521Sas200622 * Container child objects: 661*5521Sas200622 * Containers inherit an inherit-only ACE 662*5521Sas200622 * unless the NO_PROPAGATE_INHERIT_ACE bit 663*5521Sas200622 * flag is also set. 664*5521Sas200622 * 665*5521Sas200622 * CONTAINER_INHERIT_ACE only Noncontainer child objects: 666*5521Sas200622 * No effect on the child object. 667*5521Sas200622 * Container child objects: 668*5521Sas200622 * The child object inherits an effective ACE. 669*5521Sas200622 * The inherited ACE is inheritable unless the 670*5521Sas200622 * NO_PROPAGATE_INHERIT_ACE bit flag is also set. 671*5521Sas200622 * 672*5521Sas200622 * CONTAINER_INHERIT_ACE and 673*5521Sas200622 * OBJECT_INHERIT_ACE Noncontainer child objects: 674*5521Sas200622 * Inherited as an effective ACE. 675*5521Sas200622 * Container child objects: 676*5521Sas200622 * The child object inherits an effective ACE. 677*5521Sas200622 * The inherited ACE is inheritable unless the 678*5521Sas200622 * NO_PROPAGATE_INHERIT_ACE bit flag is also set 679*5521Sas200622 * 680*5521Sas200622 * No inheritance flags set No effect on child container or noncontainer 681*5521Sas200622 * objects. 682*5521Sas200622 * 683*5521Sas200622 * If an inherited ACE is an effective ACE for the child object, the system 684*5521Sas200622 * maps any generic rights to the specific rights for the child object. 685*5521Sas200622 * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the 686*5521Sas200622 * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic 687*5521Sas200622 * rights or generic SIDs are left unchanged so that they can be mapped 688*5521Sas200622 * appropriately when the ACE is inherited by the next generation of child 689*5521Sas200622 * objects. 690*5521Sas200622 * 691*5521Sas200622 * For a case in which a container object inherits an ACE that is both 692*5521Sas200622 * effective on the container and inheritable by its descendants, the 693*5521Sas200622 * container may inherit two ACEs. This occurs if the inheritable ACE 694*5521Sas200622 * contains generic information. The container inherits an inherit-only 695*5521Sas200622 * ACE containing the generic information and an effective-only ACE in 696*5521Sas200622 * which the generic information has been mapped. 6975331Samw */ 6985331Samw 6995331Samw /* 700*5521Sas200622 * smb_fsacl_inherit 7015331Samw * 7025331Samw * Manufacture the inherited ACL from the given ACL considering 7035331Samw * the new object type (file/dir) specified by 'is_dir'. The 7045331Samw * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions. 705*5521Sas200622 * This function implements Windows inheritance rules explained above. 7065331Samw * 707*5521Sas200622 * Note that the in/out ACLs are ZFS ACLs not Windows ACLs 7085331Samw */ 7095331Samw acl_t * 710*5521Sas200622 smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid) 7115331Samw { 7125331Samw boolean_t use_default = B_FALSE; 7135331Samw int num_inheritable = 0; 7145331Samw int numaces; 7155331Samw ace_t *dir_zace; 7165331Samw acl_t *new_zacl; 7175331Samw ace_t *new_zace; 7185331Samw 719*5521Sas200622 num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir); 7205331Samw 7215331Samw if (num_inheritable == 0) { 7225331Samw if (which_acl == SMB_DACL_SECINFO) { 7235331Samw /* No inheritable access ACEs -> default DACL */ 7245331Samw num_inheritable = DEFAULT_DACL_ACENUM; 7255331Samw use_default = B_TRUE; 7265331Samw } else { 7275331Samw return (NULL); 7285331Samw } 7295331Samw } 7305331Samw 731*5521Sas200622 new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT); 7325331Samw new_zace = new_zacl->acl_aclp; 7335331Samw 7345331Samw if (use_default) { 7355331Samw bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl)); 7365331Samw new_zace->a_who = owner_uid; 7375331Samw return (new_zacl); 7385331Samw } 7395331Samw 7405331Samw for (numaces = 0, dir_zace = dir_zacl->acl_aclp; 7415331Samw numaces < dir_zacl->acl_cnt; 7425331Samw dir_zace++, numaces++) { 7435331Samw switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) { 7445331Samw case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 7455331Samw /* 7465331Samw * Files inherit an effective ACE. 7475331Samw * 7485331Samw * Dirs inherit an effective ACE. 7495331Samw * The inherited ACE is inheritable unless the 7505331Samw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 7515331Samw */ 7525331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 7535331Samw new_zace++; 7545331Samw 7555331Samw if (is_dir && ZACE_IS_CREATOR(dir_zace) && 7565331Samw (ZACE_IS_PROPAGATE(dir_zace))) { 7575331Samw *new_zace = *dir_zace; 7585331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 7595331Samw ACE_INHERITED_ACE); 7605331Samw new_zace++; 7615331Samw } 7625331Samw break; 7635331Samw 7645331Samw case ACE_FILE_INHERIT_ACE: 7655331Samw /* 7665331Samw * Files inherit as an effective ACE. 7675331Samw * 7685331Samw * Dirs inherit an inherit-only ACE 7695331Samw * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 7705331Samw * flag is also set. 7715331Samw */ 7725331Samw if (is_dir == 0) { 7735331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 7745331Samw new_zace++; 7755331Samw } else if (ZACE_IS_PROPAGATE(dir_zace)) { 7765331Samw *new_zace = *dir_zace; 7775331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 7785331Samw ACE_INHERITED_ACE); 7795331Samw new_zace++; 7805331Samw } 7815331Samw break; 7825331Samw 7835331Samw case ACE_DIRECTORY_INHERIT_ACE: 7845331Samw /* 7855331Samw * No effect on files 7865331Samw * 7875331Samw * Dirs inherit an effective ACE. 7885331Samw * The inherited ACE is inheritable unless the 7895331Samw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 7905331Samw */ 7915331Samw if (is_dir == 0) 7925331Samw break; 7935331Samw 7945331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 7955331Samw new_zace++; 7965331Samw 7975331Samw if (ZACE_IS_CREATOR(dir_zace) && 7985331Samw (ZACE_IS_PROPAGATE(dir_zace))) { 7995331Samw *new_zace = *dir_zace; 8005331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 8015331Samw ACE_INHERITED_ACE); 8025331Samw new_zace++; 8035331Samw } 8045331Samw 8055331Samw break; 8065331Samw 8075331Samw default: 8085331Samw break; 8095331Samw } 8105331Samw } 8115331Samw 8125331Samw return (new_zacl); 8135331Samw } 8145331Samw 815*5521Sas200622 /* 816*5521Sas200622 * smb_fsacl_from_vsa 817*5521Sas200622 * 818*5521Sas200622 * Converts given vsecattr_t structure to a acl_t structure. 819*5521Sas200622 * 820*5521Sas200622 * The allocated memory for retuned acl_t should be freed by 821*5521Sas200622 * calling acl_free(). 822*5521Sas200622 */ 823*5521Sas200622 acl_t * 824*5521Sas200622 smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type) 825*5521Sas200622 { 826*5521Sas200622 int aclbsize = 0; /* size of acl list in bytes */ 827*5521Sas200622 int dfaclbsize = 0; /* size of default acl list in bytes */ 828*5521Sas200622 int numacls; 829*5521Sas200622 acl_t *acl_info; 830*5521Sas200622 831*5521Sas200622 ASSERT(vsecattr); 832*5521Sas200622 833*5521Sas200622 acl_info = acl_alloc(acl_type); 834*5521Sas200622 if (acl_info == NULL) 835*5521Sas200622 return (NULL); 836*5521Sas200622 837*5521Sas200622 acl_info->acl_flags = 0; 838*5521Sas200622 839*5521Sas200622 switch (acl_type) { 840*5521Sas200622 841*5521Sas200622 case ACLENT_T: 842*5521Sas200622 numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt; 843*5521Sas200622 aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t); 844*5521Sas200622 dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t); 845*5521Sas200622 846*5521Sas200622 acl_info->acl_cnt = numacls; 847*5521Sas200622 acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize, 848*5521Sas200622 KM_SLEEP); 849*5521Sas200622 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, 850*5521Sas200622 aclbsize); 851*5521Sas200622 (void) memcpy((char *)acl_info->acl_aclp + aclbsize, 852*5521Sas200622 vsecattr->vsa_dfaclentp, dfaclbsize); 853*5521Sas200622 854*5521Sas200622 if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) 855*5521Sas200622 acl_info->acl_flags |= ACL_IS_TRIVIAL; 856*5521Sas200622 857*5521Sas200622 break; 858*5521Sas200622 859*5521Sas200622 case ACE_T: 860*5521Sas200622 aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); 861*5521Sas200622 acl_info->acl_cnt = vsecattr->vsa_aclcnt; 862*5521Sas200622 acl_info->acl_flags = vsecattr->vsa_aclflags; 863*5521Sas200622 acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP); 864*5521Sas200622 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, 865*5521Sas200622 aclbsize); 866*5521Sas200622 if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) 867*5521Sas200622 acl_info->acl_flags |= ACL_IS_TRIVIAL; 868*5521Sas200622 869*5521Sas200622 break; 870*5521Sas200622 871*5521Sas200622 default: 872*5521Sas200622 acl_free(acl_info); 873*5521Sas200622 return (NULL); 874*5521Sas200622 } 875*5521Sas200622 876*5521Sas200622 if (aclbsize && vsecattr->vsa_aclentp) 877*5521Sas200622 kmem_free(vsecattr->vsa_aclentp, aclbsize); 878*5521Sas200622 if (dfaclbsize && vsecattr->vsa_dfaclentp) 879*5521Sas200622 kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize); 880*5521Sas200622 881*5521Sas200622 return (acl_info); 882*5521Sas200622 } 883*5521Sas200622 884*5521Sas200622 /* 885*5521Sas200622 * smb_fsacl_to_vsa 886*5521Sas200622 * 887*5521Sas200622 * Converts given acl_t structure to a vsecattr_t structure. 888*5521Sas200622 * 889*5521Sas200622 * IMPORTANT: 890*5521Sas200622 * Upon successful return the memory allocated for vsa_aclentp 891*5521Sas200622 * should be freed by calling kmem_free(). The size is returned 892*5521Sas200622 * in aclbsize. 893*5521Sas200622 */ 894*5521Sas200622 int 895*5521Sas200622 smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize) 896*5521Sas200622 { 897*5521Sas200622 int error = 0; 898*5521Sas200622 int numacls; 899*5521Sas200622 aclent_t *aclp; 900*5521Sas200622 901*5521Sas200622 ASSERT(acl_info); 902*5521Sas200622 ASSERT(vsecattr); 903*5521Sas200622 ASSERT(aclbsize); 904*5521Sas200622 905*5521Sas200622 bzero(vsecattr, sizeof (vsecattr_t)); 906*5521Sas200622 *aclbsize = 0; 907*5521Sas200622 908*5521Sas200622 switch (acl_info->acl_type) { 909*5521Sas200622 case ACLENT_T: 910*5521Sas200622 numacls = acl_info->acl_cnt; 911*5521Sas200622 /* 912*5521Sas200622 * Minimum ACL size is three entries so might as well 913*5521Sas200622 * bail out here. Also limit request size to prevent user 914*5521Sas200622 * from allocating too much kernel memory. Maximum size 915*5521Sas200622 * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES 916*5521Sas200622 * for the default ACL part. 917*5521Sas200622 */ 918*5521Sas200622 if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) { 919*5521Sas200622 error = EINVAL; 920*5521Sas200622 break; 921*5521Sas200622 } 922*5521Sas200622 923*5521Sas200622 vsecattr->vsa_mask = VSA_ACL; 924*5521Sas200622 925*5521Sas200622 vsecattr->vsa_aclcnt = numacls; 926*5521Sas200622 *aclbsize = numacls * sizeof (aclent_t); 927*5521Sas200622 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); 928*5521Sas200622 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, 929*5521Sas200622 *aclbsize); 930*5521Sas200622 931*5521Sas200622 /* Sort the acl list */ 932*5521Sas200622 ksort((caddr_t)vsecattr->vsa_aclentp, 933*5521Sas200622 vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls); 934*5521Sas200622 935*5521Sas200622 /* Break into acl and default acl lists */ 936*5521Sas200622 for (numacls = 0, aclp = vsecattr->vsa_aclentp; 937*5521Sas200622 numacls < vsecattr->vsa_aclcnt; 938*5521Sas200622 aclp++, numacls++) { 939*5521Sas200622 if (aclp->a_type & ACL_DEFAULT) 940*5521Sas200622 break; 941*5521Sas200622 } 942*5521Sas200622 943*5521Sas200622 /* Find where defaults start (if any) */ 944*5521Sas200622 if (numacls < vsecattr->vsa_aclcnt) { 945*5521Sas200622 vsecattr->vsa_mask |= VSA_DFACL; 946*5521Sas200622 vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls; 947*5521Sas200622 vsecattr->vsa_dfaclentp = aclp; 948*5521Sas200622 vsecattr->vsa_aclcnt = numacls; 949*5521Sas200622 } 950*5521Sas200622 951*5521Sas200622 /* Adjust if they're all defaults */ 952*5521Sas200622 if (vsecattr->vsa_aclcnt == 0) { 953*5521Sas200622 vsecattr->vsa_mask &= ~VSA_ACL; 954*5521Sas200622 vsecattr->vsa_aclentp = NULL; 955*5521Sas200622 } 956*5521Sas200622 957*5521Sas200622 /* Only directories can have defaults */ 958*5521Sas200622 if (vsecattr->vsa_dfaclcnt && 959*5521Sas200622 (acl_info->acl_flags & ACL_IS_DIR)) { 960*5521Sas200622 error = ENOTDIR; 961*5521Sas200622 } 962*5521Sas200622 963*5521Sas200622 break; 964*5521Sas200622 965*5521Sas200622 case ACE_T: 966*5521Sas200622 if (acl_info->acl_cnt < 1 || 967*5521Sas200622 acl_info->acl_cnt > MAX_ACL_ENTRIES) { 968*5521Sas200622 error = EINVAL; 969*5521Sas200622 break; 970*5521Sas200622 } 971*5521Sas200622 972*5521Sas200622 vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 973*5521Sas200622 vsecattr->vsa_aclcnt = acl_info->acl_cnt; 974*5521Sas200622 vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL; 975*5521Sas200622 *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); 976*5521Sas200622 vsecattr->vsa_aclentsz = *aclbsize; 977*5521Sas200622 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP); 978*5521Sas200622 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp, 979*5521Sas200622 *aclbsize); 980*5521Sas200622 981*5521Sas200622 break; 982*5521Sas200622 983*5521Sas200622 default: 984*5521Sas200622 error = EINVAL; 985*5521Sas200622 } 986*5521Sas200622 987*5521Sas200622 return (error); 988*5521Sas200622 } 989*5521Sas200622 990*5521Sas200622 /* 991*5521Sas200622 * smb_fsacl_inheritable 992*5521Sas200622 * 993*5521Sas200622 * Checks to see if there are any inheritable ACEs in the 994*5521Sas200622 * given ZFS ACL. Returns the number of inheritable ACEs. 995*5521Sas200622 * 996*5521Sas200622 * The inherited ACL could be different based on the type of 997*5521Sas200622 * new object (file/dir) specified by 'is_dir'. 998*5521Sas200622 * 999*5521Sas200622 * Note that the input ACL is a ZFS ACL not Windows ACL. 1000*5521Sas200622 * 1001*5521Sas200622 * Any ACE except creator owner/group: 1002*5521Sas200622 * 1003*5521Sas200622 * FI DI NP #F #D 1004*5521Sas200622 * ---- ---- ---- ---- ---- 1005*5521Sas200622 * - - ? 0 0 1006*5521Sas200622 * X - - 1 1 1007*5521Sas200622 * X - X 1 0 1008*5521Sas200622 * - X - 0 1 1009*5521Sas200622 * - X X 0 1 1010*5521Sas200622 * X X - 1 1 1011*5521Sas200622 * X X X 1 1 1012*5521Sas200622 * 1013*5521Sas200622 * Creator owner/group ACE: 1014*5521Sas200622 * 1015*5521Sas200622 * FI DI NP #F #D 1016*5521Sas200622 * ---- ---- ---- ---- ---- 1017*5521Sas200622 * - - ? 0 0 1018*5521Sas200622 * X - - 1r 1c 1019*5521Sas200622 * X - X 1r 0 1020*5521Sas200622 * - X - 0 2 1021*5521Sas200622 * - X X 0 1r 1022*5521Sas200622 * X X - 1r 2 1023*5521Sas200622 * X X X 1r 1r 1024*5521Sas200622 * 1025*5521Sas200622 * Legend: 1026*5521Sas200622 * 1027*5521Sas200622 * FI: File Inherit 1028*5521Sas200622 * DI: Dir Inherit 1029*5521Sas200622 * NP: No Propagate 1030*5521Sas200622 * #F: #ACE for a new file 1031*5521Sas200622 * #D: #ACE for a new dir 1032*5521Sas200622 * 1033*5521Sas200622 * X: bit is set 1034*5521Sas200622 * -: bit is not set 1035*5521Sas200622 * ?: don't care 1036*5521Sas200622 * 1037*5521Sas200622 * 1r: one owner/group ACE 1038*5521Sas200622 * 1c: one creator owner/group ACE 1039*5521Sas200622 */ 1040*5521Sas200622 static int 1041*5521Sas200622 smb_fsacl_inheritable(acl_t *zacl, int is_dir) 1042*5521Sas200622 { 1043*5521Sas200622 int numaces; 1044*5521Sas200622 int num_inheritable = 0; 1045*5521Sas200622 ace_t *zace; 1046*5521Sas200622 1047*5521Sas200622 if (zacl == NULL) 1048*5521Sas200622 return (0); 1049*5521Sas200622 1050*5521Sas200622 for (numaces = 0, zace = zacl->acl_aclp; 1051*5521Sas200622 numaces < zacl->acl_cnt; 1052*5521Sas200622 zace++, numaces++) { 1053*5521Sas200622 switch (zace->a_flags & ACE_FD_INHERIT_ACE) { 1054*5521Sas200622 case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 1055*5521Sas200622 /* 1056*5521Sas200622 * Files inherit an effective ACE. 1057*5521Sas200622 * 1058*5521Sas200622 * Dirs inherit an effective ACE. 1059*5521Sas200622 * The inherited ACE is inheritable unless the 1060*5521Sas200622 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 1061*5521Sas200622 */ 1062*5521Sas200622 num_inheritable++; 1063*5521Sas200622 1064*5521Sas200622 if (is_dir && ZACE_IS_CREATOR(zace) && 1065*5521Sas200622 (ZACE_IS_PROPAGATE(zace))) { 1066*5521Sas200622 num_inheritable++; 1067*5521Sas200622 } 1068*5521Sas200622 break; 1069*5521Sas200622 1070*5521Sas200622 case ACE_FILE_INHERIT_ACE: 1071*5521Sas200622 /* 1072*5521Sas200622 * Files inherit as an effective ACE. 1073*5521Sas200622 * 1074*5521Sas200622 * Dirs inherit an inherit-only ACE 1075*5521Sas200622 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 1076*5521Sas200622 * flag is also set. 1077*5521Sas200622 */ 1078*5521Sas200622 if (is_dir == 0) 1079*5521Sas200622 num_inheritable++; 1080*5521Sas200622 else if (ZACE_IS_PROPAGATE(zace)) 1081*5521Sas200622 num_inheritable++; 1082*5521Sas200622 break; 1083*5521Sas200622 1084*5521Sas200622 case ACE_DIRECTORY_INHERIT_ACE: 1085*5521Sas200622 /* 1086*5521Sas200622 * No effect on files 1087*5521Sas200622 * 1088*5521Sas200622 * Dirs inherit an effective ACE. 1089*5521Sas200622 * The inherited ACE is inheritable unless the 1090*5521Sas200622 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 1091*5521Sas200622 */ 1092*5521Sas200622 if (is_dir == 0) 1093*5521Sas200622 break; 1094*5521Sas200622 1095*5521Sas200622 num_inheritable++; 1096*5521Sas200622 1097*5521Sas200622 if (ZACE_IS_CREATOR(zace) && 1098*5521Sas200622 (ZACE_IS_PROPAGATE(zace))) 1099*5521Sas200622 num_inheritable++; 1100*5521Sas200622 break; 1101*5521Sas200622 1102*5521Sas200622 default: 1103*5521Sas200622 break; 1104*5521Sas200622 } 1105*5521Sas200622 } 1106*5521Sas200622 1107*5521Sas200622 return (num_inheritable); 1108*5521Sas200622 } 1109*5521Sas200622 1110*5521Sas200622 1111*5521Sas200622 /* 1112*5521Sas200622 * ACE Functions 1113*5521Sas200622 */ 1114*5521Sas200622 1115*5521Sas200622 /* 1116*5521Sas200622 * This is generic (ACL version 2) vs. object-specific 1117*5521Sas200622 * (ACL version 4) ACE types. 1118*5521Sas200622 */ 1119*5521Sas200622 boolean_t 1120*5521Sas200622 smb_ace_is_generic(int type) 1121*5521Sas200622 { 1122*5521Sas200622 switch (type) { 1123*5521Sas200622 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1124*5521Sas200622 case ACE_ACCESS_DENIED_ACE_TYPE: 1125*5521Sas200622 case ACE_SYSTEM_AUDIT_ACE_TYPE: 1126*5521Sas200622 case ACE_SYSTEM_ALARM_ACE_TYPE: 1127*5521Sas200622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 1128*5521Sas200622 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 1129*5521Sas200622 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 1130*5521Sas200622 case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE: 1131*5521Sas200622 return (B_TRUE); 1132*5521Sas200622 1133*5521Sas200622 default: 1134*5521Sas200622 break; 1135*5521Sas200622 } 1136*5521Sas200622 1137*5521Sas200622 return (B_FALSE); 1138*5521Sas200622 } 1139*5521Sas200622 1140*5521Sas200622 boolean_t 1141*5521Sas200622 smb_ace_is_access(int type) 1142*5521Sas200622 { 1143*5521Sas200622 switch (type) { 1144*5521Sas200622 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1145*5521Sas200622 case ACE_ACCESS_DENIED_ACE_TYPE: 1146*5521Sas200622 case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: 1147*5521Sas200622 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1148*5521Sas200622 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1149*5521Sas200622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 1150*5521Sas200622 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 1151*5521Sas200622 case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 1152*5521Sas200622 case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 1153*5521Sas200622 return (B_TRUE); 1154*5521Sas200622 1155*5521Sas200622 default: 1156*5521Sas200622 break; 1157*5521Sas200622 } 1158*5521Sas200622 1159*5521Sas200622 return (B_FALSE); 1160*5521Sas200622 } 1161*5521Sas200622 1162*5521Sas200622 boolean_t 1163*5521Sas200622 smb_ace_is_audit(int type) 1164*5521Sas200622 { 1165*5521Sas200622 switch (type) { 1166*5521Sas200622 case ACE_SYSTEM_AUDIT_ACE_TYPE: 1167*5521Sas200622 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1168*5521Sas200622 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 1169*5521Sas200622 case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 1170*5521Sas200622 return (B_TRUE); 1171*5521Sas200622 1172*5521Sas200622 default: 1173*5521Sas200622 break; 1174*5521Sas200622 } 1175*5521Sas200622 1176*5521Sas200622 return (B_FALSE); 1177*5521Sas200622 } 1178*5521Sas200622 1179*5521Sas200622 /* 1180*5521Sas200622 * smb_ace_len 1181*5521Sas200622 * 1182*5521Sas200622 * Returns the length of the given ACE as it appears in an 1183*5521Sas200622 * ACL on the wire (i.e. a flat buffer which contains the SID) 1184*5521Sas200622 */ 1185*5521Sas200622 static uint16_t 1186*5521Sas200622 smb_ace_len(smb_ace_t *ace) 1187*5521Sas200622 { 1188*5521Sas200622 ASSERT(ace); 1189*5521Sas200622 ASSERT(ace->se_sid); 1190*5521Sas200622 1191*5521Sas200622 if (ace == NULL) 1192*5521Sas200622 return (0); 1193*5521Sas200622 1194*5521Sas200622 return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) + 1195*5521Sas200622 nt_sid_length(ace->se_sid)); 1196*5521Sas200622 } 1197*5521Sas200622 11985331Samw static void 11995331Samw smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir) 12005331Samw { 12015331Samw *zace = *dir_zace; 12025331Samw if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace))) 12035331Samw zace->a_flags &= ~ACE_INHERIT_FLAGS; 12045331Samw zace->a_flags |= ACE_INHERITED_ACE; 12055331Samw 12065331Samw /* 12075331Samw * Replace creator owner/group ACEs with 12085331Samw * actual owner/group ACEs. 12095331Samw */ 12105331Samw if (ZACE_IS_CREATOR_OWNER(dir_zace)) { 12115331Samw zace->a_who = (uid_t)-1; 12125331Samw zace->a_flags |= ACE_OWNER; 12135331Samw } else if (ZACE_IS_CREATOR_GROUP(dir_zace)) { 12145331Samw zace->a_who = (uid_t)-1; 12155331Samw zace->a_flags |= ACE_GROUP; 12165331Samw } 12175331Samw } 12185331Samw 1219*5521Sas200622 /* 1220*5521Sas200622 * smb_ace_mask_g2s 1221*5521Sas200622 * 1222*5521Sas200622 * Converts generic access bits in the given mask (if any) 1223*5521Sas200622 * to file specific bits. Generic access masks shouldn't be 1224*5521Sas200622 * stored in filesystem ACEs. 1225*5521Sas200622 */ 1226*5521Sas200622 static uint32_t 1227*5521Sas200622 smb_ace_mask_g2s(uint32_t mask) 1228*5521Sas200622 { 1229*5521Sas200622 if (mask & GENERIC_ALL) { 1230*5521Sas200622 mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE 1231*5521Sas200622 | GENERIC_EXECUTE); 1232*5521Sas200622 1233*5521Sas200622 mask |= FILE_ALL_ACCESS; 1234*5521Sas200622 return (mask); 1235*5521Sas200622 } 1236*5521Sas200622 1237*5521Sas200622 if (mask & GENERIC_READ) { 1238*5521Sas200622 mask &= ~GENERIC_READ; 1239*5521Sas200622 mask |= FILE_GENERIC_READ; 1240*5521Sas200622 } 1241*5521Sas200622 1242*5521Sas200622 if (mask & GENERIC_WRITE) { 1243*5521Sas200622 mask &= ~GENERIC_WRITE; 1244*5521Sas200622 mask |= FILE_GENERIC_WRITE; 1245*5521Sas200622 } 1246*5521Sas200622 1247*5521Sas200622 if (mask & GENERIC_EXECUTE) { 1248*5521Sas200622 mask &= ~GENERIC_EXECUTE; 1249*5521Sas200622 mask |= FILE_GENERIC_EXECUTE; 1250*5521Sas200622 } 1251*5521Sas200622 1252*5521Sas200622 return (mask); 1253*5521Sas200622 } 1254*5521Sas200622 12555331Samw static uint16_t 12565331Samw smb_ace_flags_tozfs(uint8_t c_flags, int isdir) 12575331Samw { 12585331Samw uint16_t z_flags = 0; 12595331Samw 12605331Samw if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG) 12615331Samw z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 12625331Samw 12635331Samw if (c_flags & FAILED_ACCESS_ACE_FLAG) 12645331Samw z_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 12655331Samw 12665331Samw if (c_flags & INHERITED_ACE) 12675331Samw z_flags |= ACE_INHERITED_ACE; 12685331Samw 12695331Samw /* 12705331Samw * ZFS doesn't like any inheritance flags to be set on a 12715331Samw * file's ACE, only directories. Windows doesn't care. 12725331Samw */ 12735331Samw if (isdir) 12745331Samw z_flags |= (c_flags & ACE_INHERIT_FLAGS); 12755331Samw 12765331Samw return (z_flags); 12775331Samw } 12785331Samw 12795331Samw static uint8_t 12805331Samw smb_ace_flags_fromzfs(uint16_t z_flags) 12815331Samw { 12825331Samw uint8_t c_flags; 12835331Samw 12845331Samw c_flags = z_flags & ACE_INHERIT_FLAGS; 12855331Samw 12865331Samw if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 12875331Samw c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG; 12885331Samw 12895331Samw if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG) 12905331Samw c_flags |= FAILED_ACCESS_ACE_FLAG; 12915331Samw 12925331Samw if (z_flags & ACE_INHERITED_ACE) 12935331Samw c_flags |= INHERITED_ACE; 12945331Samw 12955331Samw return (c_flags); 12965331Samw } 12975331Samw 1298*5521Sas200622 static boolean_t 1299*5521Sas200622 smb_ace_isvalid(smb_ace_t *ace, int which_acl) 13005331Samw { 1301*5521Sas200622 uint16_t min_len; 1302*5521Sas200622 1303*5521Sas200622 min_len = sizeof (smb_acehdr_t); 1304*5521Sas200622 1305*5521Sas200622 if (ace->se_hdr.se_bsize < min_len) 1306*5521Sas200622 return (B_FALSE); 1307*5521Sas200622 1308*5521Sas200622 if (smb_ace_is_access(ace->se_hdr.se_type) && 1309*5521Sas200622 (which_acl != SMB_DACL_SECINFO)) 1310*5521Sas200622 return (B_FALSE); 13115331Samw 1312*5521Sas200622 if (smb_ace_is_audit(ace->se_hdr.se_type) && 1313*5521Sas200622 (which_acl != SMB_SACL_SECINFO)) 1314*5521Sas200622 return (B_FALSE); 1315*5521Sas200622 1316*5521Sas200622 if (smb_ace_is_generic(ace->se_hdr.se_type)) { 1317*5521Sas200622 if (nt_sid_is_valid(ace->se_sid) == 0) 1318*5521Sas200622 return (B_FALSE); 1319*5521Sas200622 1320*5521Sas200622 min_len += sizeof (ace->se_mask); 1321*5521Sas200622 min_len += nt_sid_length(ace->se_sid); 1322*5521Sas200622 1323*5521Sas200622 if (ace->se_hdr.se_bsize < min_len) 1324*5521Sas200622 return (B_FALSE); 13255331Samw } 13265331Samw 1327*5521Sas200622 /* 1328*5521Sas200622 * object-specific ACE validation will be added later. 1329*5521Sas200622 */ 1330*5521Sas200622 return (B_TRUE); 13315331Samw } 1332