1*5331Samw /* 2*5331Samw * CDDL HEADER START 3*5331Samw * 4*5331Samw * The contents of this file are subject to the terms of the 5*5331Samw * Common Development and Distribution License (the "License"). 6*5331Samw * You may not use this file except in compliance with the License. 7*5331Samw * 8*5331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5331Samw * or http://www.opensolaris.org/os/licensing. 10*5331Samw * See the License for the specific language governing permissions 11*5331Samw * and limitations under the License. 12*5331Samw * 13*5331Samw * When distributing Covered Code, include this CDDL HEADER in each 14*5331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5331Samw * If applicable, add the following below this CDDL HEADER, with the 16*5331Samw * fields enclosed by brackets "[]" replaced with your own identifying 17*5331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 18*5331Samw * 19*5331Samw * CDDL HEADER END 20*5331Samw */ 21*5331Samw /* 22*5331Samw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*5331Samw * Use is subject to license terms. 24*5331Samw */ 25*5331Samw 26*5331Samw #pragma ident "%Z%%M% %I% %E% SMI" 27*5331Samw 28*5331Samw /* 29*5331Samw * Platform SDK: Security 30*5331Samw * 31*5331Samw * ACE Inheritance Rules 32*5331Samw * 33*5331Samw * The system propagates inheritable ACEs to child objects according to a 34*5331Samw * set of inheritance rules. The system places inherited ACEs in the child's 35*5331Samw * DACL according to the preferred order of ACEs in a DACL. For Windows 36*5331Samw * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs. 37*5331Samw * 38*5331Samw * The following table shows the ACEs inherited by container and noncontainer 39*5331Samw * child objects for different combinations of inheritance flags. These 40*5331Samw * inheritance rules work the same for both DACLs and SACLs. 41*5331Samw * 42*5331Samw * Parent ACE type Effect on Child ACL 43*5331Samw * ----------------------- ------------------- 44*5331Samw * OBJECT_INHERIT_ACE only Noncontainer child objects: 45*5331Samw * Inherited as an effective ACE. 46*5331Samw * Container child objects: 47*5331Samw * Containers inherit an inherit-only ACE 48*5331Samw * unless the NO_PROPAGATE_INHERIT_ACE bit 49*5331Samw * flag is also set. 50*5331Samw * 51*5331Samw * CONTAINER_INHERIT_ACE only Noncontainer child objects: 52*5331Samw * No effect on the child object. 53*5331Samw * Container child objects: 54*5331Samw * The child object inherits an effective ACE. 55*5331Samw * The inherited ACE is inheritable unless the 56*5331Samw * NO_PROPAGATE_INHERIT_ACE bit flag is also set. 57*5331Samw * 58*5331Samw * CONTAINER_INHERIT_ACE and 59*5331Samw * OBJECT_INHERIT_ACE Noncontainer child objects: 60*5331Samw * Inherited as an effective ACE. 61*5331Samw * Container child objects: 62*5331Samw * The child object inherits an effective ACE. 63*5331Samw * The inherited ACE is inheritable unless the 64*5331Samw * NO_PROPAGATE_INHERIT_ACE bit flag is also set 65*5331Samw * 66*5331Samw * No inheritance flags set No effect on child container or noncontainer 67*5331Samw * objects. 68*5331Samw * 69*5331Samw * If an inherited ACE is an effective ACE for the child object, the system 70*5331Samw * maps any generic rights to the specific rights for the child object. 71*5331Samw * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the 72*5331Samw * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic 73*5331Samw * rights or generic SIDs are left unchanged so that they can be mapped 74*5331Samw * appropriately when the ACE is inherited by the next generation of child 75*5331Samw * objects. 76*5331Samw * 77*5331Samw * For a case in which a container object inherits an ACE that is both 78*5331Samw * effective on the container and inheritable by its descendants, the 79*5331Samw * container may inherit two ACEs. This occurs if the inheritable ACE 80*5331Samw * contains generic information. The container inherits an inherit-only 81*5331Samw * ACE containing the generic information and an effective-only ACE in 82*5331Samw * which the generic information has been mapped. 83*5331Samw */ 84*5331Samw 85*5331Samw #include <sys/acl.h> 86*5331Samw #include <smbsrv/smb_incl.h> 87*5331Samw #include <smbsrv/ntsid.h> 88*5331Samw #include <smbsrv/smb_fsops.h> 89*5331Samw #include <smbsrv/smb_idmap.h> 90*5331Samw 91*5331Samw #define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE) 92*5331Samw 93*5331Samw #define ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER) 94*5331Samw #define ZACE_IS_OWNGRP(zace) \ 95*5331Samw ((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP)) 96*5331Samw 97*5331Samw #define ZACE_IS_USER(zace) \ 98*5331Samw (((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace))) 99*5331Samw #define ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP) 100*5331Samw #define ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE) 101*5331Samw 102*5331Samw #define ZACE_IS_PROPAGATE(zace) \ 103*5331Samw ((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0) 104*5331Samw 105*5331Samw #define ZACE_IS_CREATOR_OWNER(zace) \ 106*5331Samw (ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID)) 107*5331Samw 108*5331Samw #define ZACE_IS_CREATOR_GROUP(zace) \ 109*5331Samw (ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID)) 110*5331Samw 111*5331Samw #define ZACE_IS_CREATOR(zace) \ 112*5331Samw (ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace)) 113*5331Samw 114*5331Samw static int smb_ace_isvalid(smb_ace_hdr_t *ace, int which_acl); 115*5331Samw static int smb_ace_append_generic(smb_acl_t *acl, void *generic_ace); 116*5331Samw 117*5331Samw static int smb_ace_common_add( 118*5331Samw smb_acl_t *acl, 119*5331Samw uint8_t type, 120*5331Samw uint8_t flags, 121*5331Samw uint32_t access_mask, 122*5331Samw nt_sid_t *sid); 123*5331Samw 124*5331Samw static void smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir); 125*5331Samw static uint16_t smb_ace_flags_tozfs(uint8_t c_flags, int isdir); 126*5331Samw static uint8_t smb_ace_flags_fromzfs(uint16_t z_flags); 127*5331Samw static void smb_acl_init(smb_acl_t *acl, uint16_t size, uint8_t rev); 128*5331Samw 129*5331Samw static int 130*5331Samw smb_ace_isvalid(smb_ace_hdr_t *ace, int which_acl) 131*5331Samw { 132*5331Samw uint16_t min_len; 133*5331Samw smb_ace_t *p; 134*5331Samw 135*5331Samw min_len = sizeof (smb_ace_hdr_t); 136*5331Samw 137*5331Samw if (ace->se_size < min_len) 138*5331Samw return (0); 139*5331Samw 140*5331Samw if (smb_ace_is_access(ace->se_type) && 141*5331Samw (which_acl != SMB_DACL_SECINFO)) { 142*5331Samw return (0); 143*5331Samw } 144*5331Samw 145*5331Samw if (smb_ace_is_audit(ace->se_type) && 146*5331Samw (which_acl != SMB_SACL_SECINFO)) { 147*5331Samw return (0); 148*5331Samw } 149*5331Samw 150*5331Samw if (smb_ace_is_generic(ace->se_type)) { 151*5331Samw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 152*5331Samw p = (smb_ace_t *)ace; 153*5331Samw 154*5331Samw if (ace->se_size < sizeof (*p)) 155*5331Samw return (0); /* won't handle empty SubAuthority[] */ 156*5331Samw 157*5331Samw if (nt_sid_is_valid(&p->se_sid) == 0) 158*5331Samw return (0); 159*5331Samw 160*5331Samw min_len += sizeof (p->se_mask); 161*5331Samw min_len += nt_sid_length(&p->se_sid); 162*5331Samw 163*5331Samw if (ace->se_size < min_len) 164*5331Samw return (0); 165*5331Samw } 166*5331Samw 167*5331Samw /* 168*5331Samw * XXX object-specific ACE validation will be added later. 169*5331Samw */ 170*5331Samw return (1); 171*5331Samw } 172*5331Samw 173*5331Samw int 174*5331Samw smb_acl_isvalid(smb_acl_t *acl, int which_acl) 175*5331Samw { 176*5331Samw uint16_t min_len; 177*5331Samw unsigned char *scan; 178*5331Samw unsigned char *scan_end; 179*5331Samw smb_ace_hdr_t *ace; 180*5331Samw uint16_t count = 0; 181*5331Samw 182*5331Samw min_len = sizeof (smb_acl_t); 183*5331Samw 184*5331Samw if (acl->sl_size < min_len) 185*5331Samw return (0); 186*5331Samw 187*5331Samw if (acl->sl_revision != ACL_REVISION) { 188*5331Samw /* 189*5331Samw * XXX we are rejecting ACLs with object-specific ACEs for now 190*5331Samw */ 191*5331Samw return (0); 192*5331Samw } 193*5331Samw 194*5331Samw scan = (unsigned char *) &acl[0]; 195*5331Samw scan_end = scan + acl->sl_size; 196*5331Samw scan = (unsigned char *) &acl[1]; /* skip Acl header */ 197*5331Samw 198*5331Samw while (count < acl->sl_acecnt && scan < scan_end) { 199*5331Samw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 200*5331Samw ace = (smb_ace_hdr_t *)scan; 201*5331Samw 202*5331Samw if (scan + sizeof (smb_ace_hdr_t) >= scan_end) 203*5331Samw return (0); 204*5331Samw 205*5331Samw if (scan + ace->se_size > scan_end) 206*5331Samw return (0); /* overflow */ 207*5331Samw 208*5331Samw if (!smb_ace_isvalid(ace, which_acl)) 209*5331Samw return (0); 210*5331Samw 211*5331Samw scan += ace->se_size; 212*5331Samw count++; 213*5331Samw } 214*5331Samw 215*5331Samw return (1); 216*5331Samw } 217*5331Samw 218*5331Samw 219*5331Samw static void 220*5331Samw smb_acl_init(smb_acl_t *acl, uint16_t size, uint8_t rev) 221*5331Samw { 222*5331Samw bzero(acl, size); 223*5331Samw acl->sl_revision = rev; 224*5331Samw acl->sl_size = size; 225*5331Samw } 226*5331Samw 227*5331Samw uint16_t 228*5331Samw smb_acl_len(smb_acl_t *acl) 229*5331Samw { 230*5331Samw smb_ace_hdr_t *ace; 231*5331Samw unsigned char *scan_beg; 232*5331Samw unsigned char *scan_end; 233*5331Samw unsigned char *scan; 234*5331Samw uint16_t length; 235*5331Samw uint16_t count; 236*5331Samw 237*5331Samw scan_beg = (unsigned char *) &acl[0]; 238*5331Samw scan_end = scan_beg + acl->sl_size; 239*5331Samw scan = (unsigned char *) &acl[1]; 240*5331Samw length = sizeof (smb_acl_t); 241*5331Samw count = 0; 242*5331Samw 243*5331Samw while ((count < acl->sl_acecnt) && (scan < scan_end)) { 244*5331Samw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 245*5331Samw ace = (smb_ace_hdr_t *)scan; 246*5331Samw length += ace->se_size; 247*5331Samw scan += ace->se_size; 248*5331Samw count++; 249*5331Samw } 250*5331Samw 251*5331Samw return (length); 252*5331Samw } 253*5331Samw 254*5331Samw /* 255*5331Samw * Append the generic ACE to the ACL. This is used to put any 256*5331Samw * kind of ACE on the ACL so the argument is declared as a void*. We cast it 257*5331Samw * to an ACCESS_ALLOWED_ACE just because there is no sense of a generic ACE. 258*5331Samw */ 259*5331Samw static int 260*5331Samw smb_ace_append_generic(smb_acl_t *acl, void *generic_ace) 261*5331Samw { 262*5331Samw smb_ace_t *ace = (smb_ace_t *)generic_ace; 263*5331Samw uint16_t acl_len = smb_acl_len(acl); 264*5331Samw unsigned char *scan = (uchar_t *)acl; 265*5331Samw 266*5331Samw if ((acl_len + ace->se_header.se_size) > acl->sl_size) { 267*5331Samw /* no room in the acl for this ace */ 268*5331Samw return (0); 269*5331Samw } 270*5331Samw 271*5331Samw /* append the ace to the acl and inc ace count */ 272*5331Samw bcopy(ace, &scan[acl_len], ace->se_header.se_size); 273*5331Samw acl->sl_acecnt++; 274*5331Samw 275*5331Samw return (1); 276*5331Samw } 277*5331Samw 278*5331Samw /* 279*5331Samw * Helper for the ACL sort routine 280*5331Samw */ 281*5331Samw typedef struct smb_ace_entry { 282*5331Samw smb_ace_t *e_ace; 283*5331Samw list_node_t e_node; 284*5331Samw } smb_ace_entry_t; 285*5331Samw 286*5331Samw /* 287*5331Samw * ACE groups within a DACL 288*5331Samw * 289*5331Samw * This is from lower to higher ACE order priority 290*5331Samw */ 291*5331Samw #define SMB_AG_START 0 292*5331Samw #define SMB_AG_ALW_INHRT 0 293*5331Samw #define SMB_AG_DNY_INHRT 1 294*5331Samw #define SMB_AG_ALW_DRCT 2 295*5331Samw #define SMB_AG_DNY_DRCT 3 296*5331Samw #define SMB_AG_NUM 4 297*5331Samw 298*5331Samw /* 299*5331Samw * smb_acl_do_sort 300*5331Samw * 301*5331Samw * Sorts the given ACL, acl, and returns the result 302*5331Samw * in a newly allocated memory. 303*5331Samw * 304*5331Samw * The following is an excerpt from MSDN website. 305*5331Samw * 306*5331Samw * Order of ACEs in a DACL 307*5331Samw * 308*5331Samw * For Windows NT versions 4.0 and earlier, the preferred order of ACEs 309*5331Samw * is simple: In a DACL, all access-denied ACEs should precede any 310*5331Samw * access-allowed ACEs. 311*5331Samw * 312*5331Samw * For Windows 2000 or later, the proper order of ACEs is more complicated 313*5331Samw * because of the introduction of object-specific ACEs and automatic 314*5331Samw * inheritance. 315*5331Samw * 316*5331Samw * The following describes the preferred order: 317*5331Samw * 318*5331Samw * To ensure that noninherited ACEs have precedence over inherited ACEs, 319*5331Samw * place all noninherited ACEs in a group before any inherited ACEs. This 320*5331Samw * ordering ensures, for example, that a noninherited access-denied ACE 321*5331Samw * is enforced regardless of any inherited ACE that allows access. 322*5331Samw * Within the groups of noninherited ACEs and inherited ACEs, order ACEs 323*5331Samw * according to ACE type, as the following shows: 324*5331Samw * . Access-denied ACEs that apply to the object itself 325*5331Samw * . Access-denied ACEs that apply to a subobject of the 326*5331Samw * object, such as a property set or property 327*5331Samw * . Access-allowed ACEs that apply to the object itself 328*5331Samw * . Access-allowed ACEs that apply to a subobject of the object 329*5331Samw * 330*5331Samw * Of course, not all ACE types are required in an ACL. 331*5331Samw */ 332*5331Samw static smb_acl_t * 333*5331Samw smb_acl_do_sort(smb_acl_t *acl, list_t *ace_grps) 334*5331Samw { 335*5331Samw smb_acl_t *sorted_acl; 336*5331Samw smb_ace_entry_t *nae; 337*5331Samw int i; 338*5331Samw 339*5331Samw sorted_acl = kmem_alloc(acl->sl_size, KM_SLEEP); 340*5331Samw *sorted_acl = *acl; 341*5331Samw 342*5331Samw /* start with no ACE in the sorted ACL */ 343*5331Samw sorted_acl->sl_acecnt = 0; 344*5331Samw 345*5331Samw /* 346*5331Samw * start with highest priority ACE group and append 347*5331Samw * the ACEs to the ACL. 348*5331Samw */ 349*5331Samw for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { 350*5331Samw nae = list_head(&ace_grps[i]); 351*5331Samw while (nae) { 352*5331Samw if (!smb_ace_append_generic(sorted_acl, nae->e_ace)) { 353*5331Samw kmem_free(sorted_acl, acl->sl_size); 354*5331Samw return (NULL); 355*5331Samw } 356*5331Samw nae = list_next(&ace_grps[i], nae); 357*5331Samw } 358*5331Samw } 359*5331Samw 360*5331Samw return (sorted_acl); 361*5331Samw } 362*5331Samw 363*5331Samw /* 364*5331Samw * smb_acl_need_sort 365*5331Samw * 366*5331Samw * Here is the desired ACE order 367*5331Samw * 368*5331Samw * deny-direct, allow-direct, deny-inherited, allow-inherited 369*5331Samw * 370*5331Samw * If any ace has been encountered which belongs to a group 371*5331Samw * with lower priority of the specified ace_grp then the acl 372*5331Samw * should be sorted. 373*5331Samw */ 374*5331Samw static int 375*5331Samw smb_acl_need_sort(list_t *ace_grps, int ace_grp) 376*5331Samw { 377*5331Samw int i; 378*5331Samw 379*5331Samw for (i = SMB_AG_START; i < ace_grp; i++) 380*5331Samw if (!list_is_empty(&ace_grps[i])) 381*5331Samw return (1); 382*5331Samw 383*5331Samw return (0); 384*5331Samw } 385*5331Samw 386*5331Samw /* 387*5331Samw * smb_acl_sort 388*5331Samw * 389*5331Samw * Returns NULL upon failure. 390*5331Samw * Returns pointer to the passed (original) acl if no sort is required. 391*5331Samw * Returns pointer to a new acl upon successful sort in which case the 392*5331Samw * caller is responsible for freeing the allocated memory. 393*5331Samw */ 394*5331Samw smb_acl_t * 395*5331Samw smb_acl_sort(smb_acl_t *acl) 396*5331Samw { 397*5331Samw smb_acl_t *sorted_acl; 398*5331Samw smb_ace_t *ace; 399*5331Samw smb_ace_entry_t *ace_list; 400*5331Samw int ace_list_size; 401*5331Samw list_t ace_grps[SMB_AG_NUM]; 402*5331Samw int ag; 403*5331Samw int do_sort = 0; 404*5331Samw uint16_t i; 405*5331Samw uint8_t ace_flags; 406*5331Samw 407*5331Samw ASSERT(acl); 408*5331Samw 409*5331Samw if (acl->sl_acecnt == 0) { 410*5331Samw /* 411*5331Samw * ACL with no entry is a valid ACL and it means 412*5331Samw * no access for anybody. 413*5331Samw */ 414*5331Samw return (acl); 415*5331Samw } 416*5331Samw 417*5331Samw for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { 418*5331Samw list_create(&ace_grps[i], sizeof (smb_ace_entry_t), 419*5331Samw offsetof(smb_ace_entry_t, e_node)); 420*5331Samw } 421*5331Samw 422*5331Samw /* 423*5331Samw * Allocate the helper entries to group the ACEs based on 424*5331Samw * the desired priorities. 425*5331Samw */ 426*5331Samw ace_list_size = sizeof (smb_ace_entry_t) * acl->sl_acecnt; 427*5331Samw ace_list = kmem_alloc(ace_list_size, KM_SLEEP); 428*5331Samw 429*5331Samw for (i = 0; i < acl->sl_acecnt; ++i) { 430*5331Samw ace_list[i].e_ace = smb_ace_get(acl, i); 431*5331Samw ace = ace_list[i].e_ace; 432*5331Samw ASSERT(ace); 433*5331Samw 434*5331Samw ace_flags = ace->se_header.se_flags; 435*5331Samw 436*5331Samw switch (ace->se_header.se_type) { 437*5331Samw case ACCESS_DENIED_ACE_TYPE: 438*5331Samw if (ace_flags & INHERITED_ACE) { 439*5331Samw ag = SMB_AG_DNY_INHRT; 440*5331Samw do_sort |= smb_acl_need_sort(ace_grps, ag); 441*5331Samw } else { 442*5331Samw ag = SMB_AG_DNY_DRCT; 443*5331Samw do_sort |= smb_acl_need_sort(ace_grps, ag); 444*5331Samw } 445*5331Samw break; 446*5331Samw 447*5331Samw case ACCESS_ALLOWED_ACE_TYPE: 448*5331Samw if (ace_flags & INHERITED_ACE) { 449*5331Samw ag = SMB_AG_ALW_INHRT; 450*5331Samw } else { 451*5331Samw ag = SMB_AG_ALW_DRCT; 452*5331Samw do_sort |= smb_acl_need_sort(ace_grps, ag); 453*5331Samw } 454*5331Samw break; 455*5331Samw 456*5331Samw default: 457*5331Samw /* 458*5331Samw * This is the lowest priority group so we put 459*5331Samw * evertything unknown here. 460*5331Samw */ 461*5331Samw ag = SMB_AG_ALW_INHRT; 462*5331Samw break; 463*5331Samw } 464*5331Samw 465*5331Samw /* Put the element on the appropriate list */ 466*5331Samw list_insert_tail(&ace_grps[ag], &ace_list[i]); 467*5331Samw } 468*5331Samw 469*5331Samw if (do_sort) 470*5331Samw sorted_acl = smb_acl_do_sort(acl, ace_grps); 471*5331Samw else 472*5331Samw sorted_acl = acl; 473*5331Samw 474*5331Samw for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { 475*5331Samw void *ent; 476*5331Samw list_t *alist = &ace_grps[i]; 477*5331Samw 478*5331Samw while ((ent = list_head(alist)) != NULL) 479*5331Samw list_remove(alist, ent); 480*5331Samw list_destroy(alist); 481*5331Samw } 482*5331Samw 483*5331Samw kmem_free(ace_list, ace_list_size); 484*5331Samw 485*5331Samw return (sorted_acl); 486*5331Samw } 487*5331Samw 488*5331Samw static int 489*5331Samw smb_ace_common_add( 490*5331Samw smb_acl_t *acl, 491*5331Samw uint8_t type, 492*5331Samw uint8_t flags, 493*5331Samw uint32_t access_mask, 494*5331Samw nt_sid_t *sid) 495*5331Samw { 496*5331Samw smb_ace_t *ace; 497*5331Samw unsigned char *scan = (unsigned char *) acl; 498*5331Samw uint16_t used = smb_acl_len(acl); 499*5331Samw uint16_t sid_len = nt_sid_length(sid); 500*5331Samw uint16_t size; 501*5331Samw 502*5331Samw size = sizeof (ace->se_header) + sizeof (ace->se_mask) + sid_len; 503*5331Samw 504*5331Samw if (size + used > acl->sl_size) { 505*5331Samw /* won't fit */ 506*5331Samw return (0); 507*5331Samw } 508*5331Samw 509*5331Samw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 510*5331Samw ace = (smb_ace_t *)&scan[used]; 511*5331Samw 512*5331Samw ace->se_header.se_type = type; 513*5331Samw ace->se_header.se_flags = flags; 514*5331Samw ace->se_header.se_size = size; 515*5331Samw ace->se_mask = access_mask; 516*5331Samw bcopy(sid, &ace->se_sid, sid_len); 517*5331Samw 518*5331Samw acl->sl_acecnt++; 519*5331Samw 520*5331Samw return (1); 521*5331Samw } 522*5331Samw 523*5331Samw smb_ace_t * 524*5331Samw smb_ace_get(smb_acl_t *acl, uint16_t idx) 525*5331Samw { 526*5331Samw smb_ace_t *ace; 527*5331Samw unsigned char *scan_beg = (unsigned char *) &acl[0]; 528*5331Samw unsigned char *scan_end = scan_beg + acl->sl_size; 529*5331Samw unsigned char *scan = (unsigned char *) &acl[1]; 530*5331Samw uint16_t count = 0; 531*5331Samw 532*5331Samw if (idx >= acl->sl_acecnt) 533*5331Samw return (NULL); 534*5331Samw 535*5331Samw while (count <= idx && scan < scan_end) { 536*5331Samw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 537*5331Samw ace = (smb_ace_t *)scan; 538*5331Samw 539*5331Samw if (count == idx) { 540*5331Samw return (ace); 541*5331Samw } 542*5331Samw 543*5331Samw scan += ace->se_header.se_size; 544*5331Samw count++; 545*5331Samw } 546*5331Samw 547*5331Samw return (NULL); 548*5331Samw } 549*5331Samw 550*5331Samw int 551*5331Samw smb_acl_copy(uint16_t buflen, smb_acl_t *dst_acl, smb_acl_t *src_acl) 552*5331Samw { 553*5331Samw smb_ace_hdr_t *dst_ace; 554*5331Samw smb_ace_hdr_t *src_ace; 555*5331Samw unsigned char *scan = (unsigned char *) &src_acl[1]; 556*5331Samw unsigned char *dest_beg = (unsigned char *) &dst_acl[0]; 557*5331Samw unsigned char *dest_end; 558*5331Samw unsigned char *dest = (unsigned char *) &dst_acl[1]; 559*5331Samw uint16_t count = 0; 560*5331Samw uint16_t n_bytes; 561*5331Samw 562*5331Samw n_bytes = smb_acl_len(src_acl); 563*5331Samw if (n_bytes > buflen) 564*5331Samw return (0); 565*5331Samw 566*5331Samw dest_end = dest_beg + n_bytes; 567*5331Samw 568*5331Samw dst_acl->sl_revision = src_acl->sl_revision; 569*5331Samw dst_acl->sl_sbz1 = 0; 570*5331Samw dst_acl->sl_size = n_bytes; 571*5331Samw dst_acl->sl_acecnt = 0; 572*5331Samw dst_acl->sl_sbz2 = 0; 573*5331Samw 574*5331Samw while (count < src_acl->sl_acecnt && dest < dest_end) { 575*5331Samw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 576*5331Samw src_ace = (smb_ace_hdr_t *)scan; 577*5331Samw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 578*5331Samw dst_ace = (smb_ace_hdr_t *)dest; 579*5331Samw bcopy(src_ace, dst_ace, src_ace->se_size); 580*5331Samw dest += dst_ace->se_size; 581*5331Samw dst_acl->sl_acecnt++; 582*5331Samw scan += src_ace->se_size; 583*5331Samw count++; 584*5331Samw } 585*5331Samw 586*5331Samw /*LINTED E_PTRDIFF_OVERFLOW*/ 587*5331Samw return (dest - dest_beg); 588*5331Samw } 589*5331Samw 590*5331Samw /* 591*5331Samw * smb_ace_len 592*5331Samw * 593*5331Samw * Returns the length of an ACE with the given SID 594*5331Samw * 595*5331Samw * struct smb_ace { 596*5331Samw * smb_ace_hdr_t se_header; 597*5331Samw * uint32_t se_mask; 598*5331Samw * nt_sid_t se_sid; 599*5331Samw * }; 600*5331Samw */ 601*5331Samw uint16_t 602*5331Samw smb_ace_len(nt_sid_t *sid) 603*5331Samw { 604*5331Samw ASSERT(sid); 605*5331Samw 606*5331Samw return (sizeof (smb_ace_hdr_t) 607*5331Samw + sizeof (uint32_t) + nt_sid_length(sid)); 608*5331Samw } 609*5331Samw 610*5331Samw /* 611*5331Samw * smb_ace_mask_g2s 612*5331Samw * 613*5331Samw * Converts generic access bits in the given mask (if any) 614*5331Samw * to file specific bits. Generic access masks shouldn't be 615*5331Samw * stored in filesystem ACEs. 616*5331Samw */ 617*5331Samw uint32_t 618*5331Samw smb_ace_mask_g2s(DWORD mask) 619*5331Samw { 620*5331Samw if (mask & GENERIC_ALL) { 621*5331Samw mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE 622*5331Samw | GENERIC_EXECUTE); 623*5331Samw 624*5331Samw mask |= FILE_ALL_ACCESS; 625*5331Samw return (mask); 626*5331Samw } 627*5331Samw 628*5331Samw if (mask & GENERIC_READ) { 629*5331Samw mask &= ~GENERIC_READ; 630*5331Samw mask |= FILE_GENERIC_READ; 631*5331Samw } 632*5331Samw 633*5331Samw if (mask & GENERIC_WRITE) { 634*5331Samw mask &= ~GENERIC_WRITE; 635*5331Samw mask |= FILE_GENERIC_WRITE; 636*5331Samw } 637*5331Samw 638*5331Samw if (mask & GENERIC_EXECUTE) { 639*5331Samw mask &= ~GENERIC_EXECUTE; 640*5331Samw mask |= FILE_GENERIC_EXECUTE; 641*5331Samw } 642*5331Samw 643*5331Samw return (mask); 644*5331Samw } 645*5331Samw 646*5331Samw /* 647*5331Samw * smb_acl_getsids 648*5331Samw * 649*5331Samw * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs. 650*5331Samw */ 651*5331Samw static idmap_stat 652*5331Samw smb_acl_getsids(smb_idmap_batch_t *sib, acl_t *zacl, uid_t uid, gid_t gid) 653*5331Samw { 654*5331Samw ace_t *zace; 655*5331Samw idmap_stat idm_stat; 656*5331Samw smb_idmap_t *sim; 657*5331Samw uid_t id; 658*5331Samw int i, idtype; 659*5331Samw 660*5331Samw sim = sib->sib_maps; 661*5331Samw 662*5331Samw for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; 663*5331Samw zace++, i++, sim++) { 664*5331Samw switch (zace->a_flags & ACE_TYPE_FLAGS) { 665*5331Samw case ACE_OWNER: 666*5331Samw id = uid; 667*5331Samw idtype = SMB_IDMAP_USER; 668*5331Samw break; 669*5331Samw 670*5331Samw case (ACE_GROUP | ACE_IDENTIFIER_GROUP): 671*5331Samw /* owning group */ 672*5331Samw id = gid; 673*5331Samw idtype = SMB_IDMAP_GROUP; 674*5331Samw break; 675*5331Samw 676*5331Samw case ACE_IDENTIFIER_GROUP: 677*5331Samw /* regular group */ 678*5331Samw id = zace->a_who; 679*5331Samw idtype = SMB_IDMAP_GROUP; 680*5331Samw break; 681*5331Samw 682*5331Samw case ACE_EVERYONE: 683*5331Samw idtype = SMB_IDMAP_EVERYONE; 684*5331Samw break; 685*5331Samw 686*5331Samw default: 687*5331Samw /* user entry */ 688*5331Samw id = zace->a_who; 689*5331Samw idtype = SMB_IDMAP_USER; 690*5331Samw } 691*5331Samw 692*5331Samw idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim, 693*5331Samw id, idtype); 694*5331Samw 695*5331Samw if (idm_stat != IDMAP_SUCCESS) { 696*5331Samw return (idm_stat); 697*5331Samw } 698*5331Samw } 699*5331Samw 700*5331Samw idm_stat = smb_idmap_batch_getmappings(sib); 701*5331Samw return (idm_stat); 702*5331Samw } 703*5331Samw 704*5331Samw /* 705*5331Samw * smb_acl_grow 706*5331Samw * 707*5331Samw * Grow the acl size by given number of bytes in 'grow' 708*5331Samw * Returns pointer to the newly allocated memory. 709*5331Samw */ 710*5331Samw static smb_acl_t * 711*5331Samw smb_acl_grow(smb_acl_t *acl, uint16_t grow) 712*5331Samw { 713*5331Samw smb_acl_t *new_acl; 714*5331Samw uint16_t smb_aclsz; 715*5331Samw 716*5331Samw ASSERT(acl); 717*5331Samw 718*5331Samw smb_aclsz = acl->sl_size; 719*5331Samw new_acl = kmem_alloc(smb_aclsz + grow, KM_SLEEP); 720*5331Samw (void) memcpy(new_acl, acl, smb_aclsz); 721*5331Samw kmem_free(acl, smb_aclsz); 722*5331Samw new_acl->sl_size = smb_aclsz + grow; 723*5331Samw 724*5331Samw return (new_acl); 725*5331Samw } 726*5331Samw 727*5331Samw /* 728*5331Samw * smb_acl_from_zfs 729*5331Samw * 730*5331Samw * Converts given ZFS ACL to a Windows ACL. 731*5331Samw * 732*5331Samw * A pointer to allocated memory for the Win ACL will be 733*5331Samw * returned upon successful conversion. 734*5331Samw */ 735*5331Samw smb_acl_t * 736*5331Samw smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid) 737*5331Samw { 738*5331Samw ace_t *zace; 739*5331Samw int numaces; 740*5331Samw smb_acl_t *acl; 741*5331Samw uint16_t smb_aclsz; 742*5331Samw smb_idmap_batch_t sib; 743*5331Samw smb_idmap_t *sim; 744*5331Samw idmap_stat idm_stat; 745*5331Samw int status; 746*5331Samw 747*5331Samw idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, 748*5331Samw SMB_IDMAP_ID2SID); 749*5331Samw if (idm_stat != IDMAP_SUCCESS) 750*5331Samw return (NULL); 751*5331Samw 752*5331Samw if (smb_acl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) { 753*5331Samw smb_idmap_batch_destroy(&sib); 754*5331Samw return (NULL); 755*5331Samw } 756*5331Samw 757*5331Samw smb_aclsz = sizeof (smb_acl_t); 758*5331Samw 759*5331Samw acl = kmem_alloc(smb_aclsz, KM_SLEEP); 760*5331Samw smb_acl_init(acl, smb_aclsz, ACL_REVISION); 761*5331Samw 762*5331Samw sim = sib.sib_maps; 763*5331Samw for (numaces = 0, zace = zacl->acl_aclp; 764*5331Samw numaces < zacl->acl_cnt; 765*5331Samw zace++, numaces++, sim++) { 766*5331Samw ASSERT(sim->sim_sid); 767*5331Samw if (sim->sim_sid == NULL) { 768*5331Samw kmem_free(acl, acl->sl_size); 769*5331Samw acl = NULL; 770*5331Samw break; 771*5331Samw } 772*5331Samw 773*5331Samw /* Make room for this ACE */ 774*5331Samw acl = smb_acl_grow(acl, smb_ace_len(sim->sim_sid)); 775*5331Samw 776*5331Samw status = smb_ace_common_add(acl, 777*5331Samw zace->a_type, 778*5331Samw smb_ace_flags_fromzfs(zace->a_flags), 779*5331Samw zace->a_access_mask, 780*5331Samw sim->sim_sid); 781*5331Samw 782*5331Samw if (status == 0) { 783*5331Samw kmem_free(acl, acl->sl_size); 784*5331Samw acl = NULL; 785*5331Samw break; 786*5331Samw } 787*5331Samw } 788*5331Samw 789*5331Samw smb_idmap_batch_destroy(&sib); 790*5331Samw return (acl); 791*5331Samw } 792*5331Samw 793*5331Samw /* 794*5331Samw * SID for Everyone group: S-1-1-0. 795*5331Samw */ 796*5331Samw nt_sid_t everyone_sid = { 797*5331Samw NT_SID_REVISION, 798*5331Samw 1, 799*5331Samw NT_SECURITY_WORLD_AUTH, 800*5331Samw { 0 } 801*5331Samw }; 802*5331Samw 803*5331Samw /* 804*5331Samw * smb_acl_null_empty 805*5331Samw * 806*5331Samw * NULL DACL means everyone full-access 807*5331Samw * Empty DACL means everyone full-deny 808*5331Samw * 809*5331Samw * ZFS ACL must have at least one entry so smb server has 810*5331Samw * to simulate the aforementioned expected behavior by adding 811*5331Samw * an entry in case the requested DACL is null or empty. Adding 812*5331Samw * a everyone full-deny entry has proved to be problematic in 813*5331Samw * tests since a deny entry takes precedence over allow entries. 814*5331Samw * So, instead of adding a everyone full-deny, an owner ACE with 815*5331Samw * owner implicit permissions will be set. 816*5331Samw */ 817*5331Samw acl_t * 818*5331Samw smb_acl_null_empty(int null) 819*5331Samw { 820*5331Samw acl_t *zacl; 821*5331Samw ace_t *zace; 822*5331Samw 823*5331Samw zacl = smb_fsop_aclalloc(1, ACL_AUTO_INHERIT); 824*5331Samw zace = zacl->acl_aclp; 825*5331Samw 826*5331Samw zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 827*5331Samw if (null) { 828*5331Samw zace->a_access_mask = ACE_ALL_PERMS; 829*5331Samw zace->a_flags = ACE_EVERYONE; 830*5331Samw } else { 831*5331Samw zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | 832*5331Samw ACE_READ_ATTRIBUTES; 833*5331Samw zace->a_flags = ACE_OWNER; 834*5331Samw } 835*5331Samw 836*5331Samw return (zacl); 837*5331Samw } 838*5331Samw 839*5331Samw /* 840*5331Samw * smb_acl_to_zfs 841*5331Samw * 842*5331Samw * Converts given Windows ACL to a ZFS ACL. 843*5331Samw * 844*5331Samw * fs_acl will contain a pointer to the created ZFS ACL. 845*5331Samw * The allocated memory should be freed by calling 846*5331Samw * smb_fsop_aclfree(). 847*5331Samw * 848*5331Samw * Since the output parameter, fs_acl, is allocated in this 849*5331Samw * function, the caller has to make sure *fs_acl is NULL which 850*5331Samw * means it's not pointing to any memory. 851*5331Samw */ 852*5331Samw uint32_t 853*5331Samw smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) 854*5331Samw { 855*5331Samw smb_ace_t *ace; 856*5331Samw acl_t *zacl; 857*5331Samw ace_t *zace; 858*5331Samw smb_idmap_batch_t sib; 859*5331Samw smb_idmap_t *sim; 860*5331Samw idmap_stat idm_stat; 861*5331Samw int i, isdir; 862*5331Samw 863*5331Samw ASSERT(fs_acl); 864*5331Samw ASSERT(*fs_acl == NULL); 865*5331Samw 866*5331Samw if (acl && !smb_acl_isvalid(acl, which_acl)) 867*5331Samw return (NT_STATUS_INVALID_ACL); 868*5331Samw 869*5331Samw if ((acl == NULL) || (acl->sl_acecnt == 0)) { 870*5331Samw if (which_acl == SMB_DACL_SECINFO) { 871*5331Samw *fs_acl = smb_acl_null_empty(acl == NULL); 872*5331Samw } 873*5331Samw 874*5331Samw return (NT_STATUS_SUCCESS); 875*5331Samw } 876*5331Samw 877*5331Samw idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, 878*5331Samw SMB_IDMAP_SID2ID); 879*5331Samw if (idm_stat != IDMAP_SUCCESS) 880*5331Samw return (NT_STATUS_INTERNAL_ERROR); 881*5331Samw 882*5331Samw isdir = ((flags & ACL_IS_DIR) == ACL_IS_DIR); 883*5331Samw 884*5331Samw zacl = smb_fsop_aclalloc(acl->sl_acecnt, flags); 885*5331Samw 886*5331Samw zace = zacl->acl_aclp; 887*5331Samw sim = sib.sib_maps; 888*5331Samw 889*5331Samw for (i = 0; ace = smb_ace_get(acl, i); i++, zace++, sim++) { 890*5331Samw zace->a_type = ace->se_header.se_type & ACE_ALL_TYPES; 891*5331Samw zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); 892*5331Samw zace->a_flags = smb_ace_flags_tozfs(ace->se_header.se_flags, 893*5331Samw isdir); 894*5331Samw 895*5331Samw if (nt_sid_is_equal(&ace->se_sid, &everyone_sid)) 896*5331Samw zace->a_flags |= ACE_EVERYONE; 897*5331Samw else { 898*5331Samw sim->sim_id = &zace->a_who; 899*5331Samw idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, 900*5331Samw &ace->se_sid, -1); 901*5331Samw 902*5331Samw if (idm_stat != IDMAP_SUCCESS) { 903*5331Samw smb_fsop_aclfree(zacl); 904*5331Samw smb_idmap_batch_destroy(&sib); 905*5331Samw return (NT_STATUS_INTERNAL_ERROR); 906*5331Samw } 907*5331Samw } 908*5331Samw } 909*5331Samw 910*5331Samw idm_stat = smb_idmap_batch_getmappings(&sib); 911*5331Samw if (idm_stat != IDMAP_SUCCESS) { 912*5331Samw smb_fsop_aclfree(zacl); 913*5331Samw smb_idmap_batch_destroy(&sib); 914*5331Samw return (NT_STATUS_NONE_MAPPED); 915*5331Samw } 916*5331Samw 917*5331Samw /* 918*5331Samw * Set the ACEs group flag based on the type of ID returned. 919*5331Samw */ 920*5331Samw zace = zacl->acl_aclp; 921*5331Samw sim = sib.sib_maps; 922*5331Samw for (i = 0; i < acl->sl_acecnt; i++, zace++, sim++) { 923*5331Samw if (zace->a_flags & ACE_EVERYONE) 924*5331Samw continue; 925*5331Samw 926*5331Samw if (sim->sim_idtype == SMB_IDMAP_GROUP) 927*5331Samw zace->a_flags |= ACE_IDENTIFIER_GROUP; 928*5331Samw } 929*5331Samw 930*5331Samw smb_idmap_batch_destroy(&sib); 931*5331Samw 932*5331Samw *fs_acl = zacl; 933*5331Samw return (NT_STATUS_SUCCESS); 934*5331Samw } 935*5331Samw 936*5331Samw /* 937*5331Samw * smb_acl_inheritable 938*5331Samw * 939*5331Samw * Checks to see if there are any inheritable ACEs in the 940*5331Samw * given ZFS ACL. Returns the number of inheritable ACEs. 941*5331Samw * 942*5331Samw * The inherited ACL could be different based on the type of 943*5331Samw * new object (file/dir) specified by 'is_dir'. 944*5331Samw * 945*5331Samw * Note that the input ACL is a ZFS ACL not Windows ACL. 946*5331Samw * 947*5331Samw * Any ACE except creator owner/group: 948*5331Samw * 949*5331Samw * FI DI NP #F #D 950*5331Samw * ---- ---- ---- ---- ---- 951*5331Samw * - - ? 0 0 952*5331Samw * X - - 1 1 953*5331Samw * X - X 1 0 954*5331Samw * - X - 0 1 955*5331Samw * - X X 0 1 956*5331Samw * X X - 1 1 957*5331Samw * X X X 1 1 958*5331Samw * 959*5331Samw * Creator owner/group ACE: 960*5331Samw * 961*5331Samw * FI DI NP #F #D 962*5331Samw * ---- ---- ---- ---- ---- 963*5331Samw * - - ? 0 0 964*5331Samw * X - - 1r 1c 965*5331Samw * X - X 1r 0 966*5331Samw * - X - 0 2 967*5331Samw * - X X 0 1r 968*5331Samw * X X - 1r 2 969*5331Samw * X X X 1r 1r 970*5331Samw * 971*5331Samw * Legend: 972*5331Samw * 973*5331Samw * FI: File Inherit 974*5331Samw * DI: Dir Inherit 975*5331Samw * NP: No Propagate 976*5331Samw * #F: #ACE for a new file 977*5331Samw * #D: #ACE for a new dir 978*5331Samw * 979*5331Samw * X: bit is set 980*5331Samw * -: bit is not set 981*5331Samw * ?: don't care 982*5331Samw * 983*5331Samw * 1r: one owner/group ACE 984*5331Samw * 1c: one creator owner/group ACE 985*5331Samw */ 986*5331Samw static int 987*5331Samw smb_acl_inheritable(acl_t *zacl, int is_dir) 988*5331Samw { 989*5331Samw int numaces; 990*5331Samw int num_inheritable = 0; 991*5331Samw ace_t *zace; 992*5331Samw 993*5331Samw if (zacl == NULL) 994*5331Samw return (0); 995*5331Samw 996*5331Samw for (numaces = 0, zace = zacl->acl_aclp; 997*5331Samw numaces < zacl->acl_cnt; 998*5331Samw zace++, numaces++) { 999*5331Samw switch (zace->a_flags & ACE_FD_INHERIT_ACE) { 1000*5331Samw case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 1001*5331Samw /* 1002*5331Samw * Files inherit an effective ACE. 1003*5331Samw * 1004*5331Samw * Dirs inherit an effective ACE. 1005*5331Samw * The inherited ACE is inheritable unless the 1006*5331Samw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 1007*5331Samw */ 1008*5331Samw num_inheritable++; 1009*5331Samw 1010*5331Samw if (is_dir && ZACE_IS_CREATOR(zace) && 1011*5331Samw (ZACE_IS_PROPAGATE(zace))) { 1012*5331Samw num_inheritable++; 1013*5331Samw } 1014*5331Samw break; 1015*5331Samw 1016*5331Samw case ACE_FILE_INHERIT_ACE: 1017*5331Samw /* 1018*5331Samw * Files inherit as an effective ACE. 1019*5331Samw * 1020*5331Samw * Dirs inherit an inherit-only ACE 1021*5331Samw * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 1022*5331Samw * flag is also set. 1023*5331Samw */ 1024*5331Samw if (is_dir == 0) 1025*5331Samw num_inheritable++; 1026*5331Samw else if (ZACE_IS_PROPAGATE(zace)) 1027*5331Samw num_inheritable++; 1028*5331Samw break; 1029*5331Samw 1030*5331Samw case ACE_DIRECTORY_INHERIT_ACE: 1031*5331Samw /* 1032*5331Samw * No effect on files 1033*5331Samw * 1034*5331Samw * Dirs inherit an effective ACE. 1035*5331Samw * The inherited ACE is inheritable unless the 1036*5331Samw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 1037*5331Samw */ 1038*5331Samw if (is_dir == 0) 1039*5331Samw break; 1040*5331Samw 1041*5331Samw num_inheritable++; 1042*5331Samw 1043*5331Samw if (ZACE_IS_CREATOR(zace) && 1044*5331Samw (ZACE_IS_PROPAGATE(zace))) 1045*5331Samw num_inheritable++; 1046*5331Samw break; 1047*5331Samw 1048*5331Samw default: 1049*5331Samw break; 1050*5331Samw } 1051*5331Samw } 1052*5331Samw 1053*5331Samw return (num_inheritable); 1054*5331Samw } 1055*5331Samw 1056*5331Samw #define DEFAULT_DACL_ACENUM 2 1057*5331Samw /* 1058*5331Samw * Default ACL: 1059*5331Samw * owner: full access 1060*5331Samw * SYSTEM: full access 1061*5331Samw */ 1062*5331Samw static ace_t default_dacl[DEFAULT_DACL_ACENUM] = { 1063*5331Samw { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, 1064*5331Samw { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP, 1065*5331Samw ACE_ACCESS_ALLOWED_ACE_TYPE } 1066*5331Samw }; 1067*5331Samw 1068*5331Samw /* 1069*5331Samw * smb_acl_inherit 1070*5331Samw * 1071*5331Samw * Manufacture the inherited ACL from the given ACL considering 1072*5331Samw * the new object type (file/dir) specified by 'is_dir'. The 1073*5331Samw * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions. 1074*5331Samw * This function implements Windows inheritance rules. 1075*5331Samw * 1076*5331Samw * Note that the in/our ACLs are ZFS ACLs not Windows ACLs 1077*5331Samw */ 1078*5331Samw acl_t * 1079*5331Samw smb_acl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid) 1080*5331Samw { 1081*5331Samw boolean_t use_default = B_FALSE; 1082*5331Samw int num_inheritable = 0; 1083*5331Samw int numaces; 1084*5331Samw ace_t *dir_zace; 1085*5331Samw acl_t *new_zacl; 1086*5331Samw ace_t *new_zace; 1087*5331Samw 1088*5331Samw num_inheritable = smb_acl_inheritable(dir_zacl, is_dir); 1089*5331Samw 1090*5331Samw if (num_inheritable == 0) { 1091*5331Samw if (which_acl == SMB_DACL_SECINFO) { 1092*5331Samw /* No inheritable access ACEs -> default DACL */ 1093*5331Samw num_inheritable = DEFAULT_DACL_ACENUM; 1094*5331Samw use_default = B_TRUE; 1095*5331Samw } else { 1096*5331Samw return (NULL); 1097*5331Samw } 1098*5331Samw } 1099*5331Samw 1100*5331Samw new_zacl = smb_fsop_aclalloc(num_inheritable, ACL_AUTO_INHERIT); 1101*5331Samw new_zace = new_zacl->acl_aclp; 1102*5331Samw 1103*5331Samw if (use_default) { 1104*5331Samw bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl)); 1105*5331Samw new_zace->a_who = owner_uid; 1106*5331Samw return (new_zacl); 1107*5331Samw } 1108*5331Samw 1109*5331Samw for (numaces = 0, dir_zace = dir_zacl->acl_aclp; 1110*5331Samw numaces < dir_zacl->acl_cnt; 1111*5331Samw dir_zace++, numaces++) { 1112*5331Samw switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) { 1113*5331Samw case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE): 1114*5331Samw /* 1115*5331Samw * Files inherit an effective ACE. 1116*5331Samw * 1117*5331Samw * Dirs inherit an effective ACE. 1118*5331Samw * The inherited ACE is inheritable unless the 1119*5331Samw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set 1120*5331Samw */ 1121*5331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 1122*5331Samw new_zace++; 1123*5331Samw 1124*5331Samw if (is_dir && ZACE_IS_CREATOR(dir_zace) && 1125*5331Samw (ZACE_IS_PROPAGATE(dir_zace))) { 1126*5331Samw *new_zace = *dir_zace; 1127*5331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 1128*5331Samw ACE_INHERITED_ACE); 1129*5331Samw new_zace++; 1130*5331Samw } 1131*5331Samw break; 1132*5331Samw 1133*5331Samw case ACE_FILE_INHERIT_ACE: 1134*5331Samw /* 1135*5331Samw * Files inherit as an effective ACE. 1136*5331Samw * 1137*5331Samw * Dirs inherit an inherit-only ACE 1138*5331Samw * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit 1139*5331Samw * flag is also set. 1140*5331Samw */ 1141*5331Samw if (is_dir == 0) { 1142*5331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 1143*5331Samw new_zace++; 1144*5331Samw } else if (ZACE_IS_PROPAGATE(dir_zace)) { 1145*5331Samw *new_zace = *dir_zace; 1146*5331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 1147*5331Samw ACE_INHERITED_ACE); 1148*5331Samw new_zace++; 1149*5331Samw } 1150*5331Samw break; 1151*5331Samw 1152*5331Samw case ACE_DIRECTORY_INHERIT_ACE: 1153*5331Samw /* 1154*5331Samw * No effect on files 1155*5331Samw * 1156*5331Samw * Dirs inherit an effective ACE. 1157*5331Samw * The inherited ACE is inheritable unless the 1158*5331Samw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set. 1159*5331Samw */ 1160*5331Samw if (is_dir == 0) 1161*5331Samw break; 1162*5331Samw 1163*5331Samw smb_ace_inherit(dir_zace, new_zace, is_dir); 1164*5331Samw new_zace++; 1165*5331Samw 1166*5331Samw if (ZACE_IS_CREATOR(dir_zace) && 1167*5331Samw (ZACE_IS_PROPAGATE(dir_zace))) { 1168*5331Samw *new_zace = *dir_zace; 1169*5331Samw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE | 1170*5331Samw ACE_INHERITED_ACE); 1171*5331Samw new_zace++; 1172*5331Samw } 1173*5331Samw 1174*5331Samw break; 1175*5331Samw 1176*5331Samw default: 1177*5331Samw break; 1178*5331Samw } 1179*5331Samw } 1180*5331Samw 1181*5331Samw return (new_zacl); 1182*5331Samw } 1183*5331Samw 1184*5331Samw static void 1185*5331Samw smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir) 1186*5331Samw { 1187*5331Samw *zace = *dir_zace; 1188*5331Samw if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace))) 1189*5331Samw zace->a_flags &= ~ACE_INHERIT_FLAGS; 1190*5331Samw zace->a_flags |= ACE_INHERITED_ACE; 1191*5331Samw 1192*5331Samw /* 1193*5331Samw * Replace creator owner/group ACEs with 1194*5331Samw * actual owner/group ACEs. 1195*5331Samw */ 1196*5331Samw if (ZACE_IS_CREATOR_OWNER(dir_zace)) { 1197*5331Samw zace->a_who = (uid_t)-1; 1198*5331Samw zace->a_flags |= ACE_OWNER; 1199*5331Samw } else if (ZACE_IS_CREATOR_GROUP(dir_zace)) { 1200*5331Samw zace->a_who = (uid_t)-1; 1201*5331Samw zace->a_flags |= ACE_GROUP; 1202*5331Samw } 1203*5331Samw } 1204*5331Samw 1205*5331Samw static uint16_t 1206*5331Samw smb_ace_flags_tozfs(uint8_t c_flags, int isdir) 1207*5331Samw { 1208*5331Samw uint16_t z_flags = 0; 1209*5331Samw 1210*5331Samw if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG) 1211*5331Samw z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 1212*5331Samw 1213*5331Samw if (c_flags & FAILED_ACCESS_ACE_FLAG) 1214*5331Samw z_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 1215*5331Samw 1216*5331Samw if (c_flags & INHERITED_ACE) 1217*5331Samw z_flags |= ACE_INHERITED_ACE; 1218*5331Samw 1219*5331Samw /* 1220*5331Samw * ZFS doesn't like any inheritance flags to be set on a 1221*5331Samw * file's ACE, only directories. Windows doesn't care. 1222*5331Samw */ 1223*5331Samw if (isdir) 1224*5331Samw z_flags |= (c_flags & ACE_INHERIT_FLAGS); 1225*5331Samw 1226*5331Samw return (z_flags); 1227*5331Samw } 1228*5331Samw 1229*5331Samw static uint8_t 1230*5331Samw smb_ace_flags_fromzfs(uint16_t z_flags) 1231*5331Samw { 1232*5331Samw uint8_t c_flags; 1233*5331Samw 1234*5331Samw c_flags = z_flags & ACE_INHERIT_FLAGS; 1235*5331Samw 1236*5331Samw if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 1237*5331Samw c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG; 1238*5331Samw 1239*5331Samw if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG) 1240*5331Samw c_flags |= FAILED_ACCESS_ACE_FLAG; 1241*5331Samw 1242*5331Samw if (z_flags & ACE_INHERITED_ACE) 1243*5331Samw c_flags |= INHERITED_ACE; 1244*5331Samw 1245*5331Samw return (c_flags); 1246*5331Samw } 1247*5331Samw 1248*5331Samw /* 1249*5331Samw * This is generic (ACL version 2) vs. object-specific 1250*5331Samw * (ACL version 4) ACE types. 1251*5331Samw */ 1252*5331Samw int 1253*5331Samw smb_ace_is_generic(int type) 1254*5331Samw { 1255*5331Samw switch (type) { 1256*5331Samw case ACE_ACCESS_ALLOWED_ACE_TYPE: 1257*5331Samw case ACE_ACCESS_DENIED_ACE_TYPE: 1258*5331Samw case ACE_SYSTEM_AUDIT_ACE_TYPE: 1259*5331Samw case ACE_SYSTEM_ALARM_ACE_TYPE: 1260*5331Samw case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 1261*5331Samw case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 1262*5331Samw case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 1263*5331Samw case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE: 1264*5331Samw return (1); 1265*5331Samw 1266*5331Samw default: 1267*5331Samw break; 1268*5331Samw } 1269*5331Samw 1270*5331Samw return (0); 1271*5331Samw } 1272*5331Samw 1273*5331Samw int 1274*5331Samw smb_ace_is_access(int type) 1275*5331Samw { 1276*5331Samw switch (type) { 1277*5331Samw case ACE_ACCESS_ALLOWED_ACE_TYPE: 1278*5331Samw case ACE_ACCESS_DENIED_ACE_TYPE: 1279*5331Samw case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE: 1280*5331Samw case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1281*5331Samw case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1282*5331Samw case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE: 1283*5331Samw case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE: 1284*5331Samw case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: 1285*5331Samw case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: 1286*5331Samw return (1); 1287*5331Samw 1288*5331Samw default: 1289*5331Samw break; 1290*5331Samw } 1291*5331Samw 1292*5331Samw return (0); 1293*5331Samw } 1294*5331Samw 1295*5331Samw int 1296*5331Samw smb_ace_is_audit(int type) 1297*5331Samw { 1298*5331Samw switch (type) { 1299*5331Samw case ACE_SYSTEM_AUDIT_ACE_TYPE: 1300*5331Samw case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1301*5331Samw case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE: 1302*5331Samw case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: 1303*5331Samw return (1); 1304*5331Samw 1305*5331Samw default: 1306*5331Samw break; 1307*5331Samw } 1308*5331Samw 1309*5331Samw return (0); 1310*5331Samw } 1311