1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5f48205beScasper * Common Development and Distribution License (the "License"). 6f48205beScasper * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 22f48205beScasper * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23fa9e4066Sahrens * Use is subject to license terms. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27fa9e4066Sahrens 28fa9e4066Sahrens #include <sys/types.h> 29fa9e4066Sahrens #include <sys/stat.h> 30*da6c28aaSamw #include <sys/avl.h> 31fa9e4066Sahrens #if defined(_KERNEL) 32fa9e4066Sahrens #include <sys/systm.h> 33*da6c28aaSamw #include <sys/sysmacros.h> 34*da6c28aaSamw #include <acl/acl_common.h> 35fa9e4066Sahrens #else 36fa9e4066Sahrens #include <errno.h> 37fa9e4066Sahrens #include <stdlib.h> 38*da6c28aaSamw #include <stddef.h> 39fa9e4066Sahrens #include <strings.h> 40*da6c28aaSamw #include <unistd.h> 41fa9e4066Sahrens #include <assert.h> 42*da6c28aaSamw #include <grp.h> 43*da6c28aaSamw #include <pwd.h> 44*da6c28aaSamw #include <acl_common.h> 45fa9e4066Sahrens #define ASSERT assert 46fa9e4066Sahrens #endif 47fa9e4066Sahrens 48*da6c28aaSamw #define ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \ 49*da6c28aaSamw ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \ 50*da6c28aaSamw ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL) 51*da6c28aaSamw 52*da6c28aaSamw 53*da6c28aaSamw #define ACL_SYNCHRONIZE_SET_DENY 0x0000001 54*da6c28aaSamw #define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002 55*da6c28aaSamw #define ACL_SYNCHRONIZE_ERR_DENY 0x0000004 56*da6c28aaSamw #define ACL_SYNCHRONIZE_ERR_ALLOW 0x0000008 57*da6c28aaSamw 58*da6c28aaSamw #define ACL_WRITE_OWNER_SET_DENY 0x0000010 59*da6c28aaSamw #define ACL_WRITE_OWNER_SET_ALLOW 0x0000020 60*da6c28aaSamw #define ACL_WRITE_OWNER_ERR_DENY 0x0000040 61*da6c28aaSamw #define ACL_WRITE_OWNER_ERR_ALLOW 0x0000080 62*da6c28aaSamw 63*da6c28aaSamw #define ACL_DELETE_SET_DENY 0x0000100 64*da6c28aaSamw #define ACL_DELETE_SET_ALLOW 0x0000200 65*da6c28aaSamw #define ACL_DELETE_ERR_DENY 0x0000400 66*da6c28aaSamw #define ACL_DELETE_ERR_ALLOW 0x0000800 67*da6c28aaSamw 68*da6c28aaSamw #define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000 69*da6c28aaSamw #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000 70*da6c28aaSamw #define ACL_WRITE_ATTRS_OWNER_ERR_DENY 0x0004000 71*da6c28aaSamw #define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW 0x0008000 72*da6c28aaSamw 73*da6c28aaSamw #define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000 74*da6c28aaSamw #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000 75*da6c28aaSamw #define ACL_WRITE_ATTRS_WRITER_ERR_DENY 0x0040000 76*da6c28aaSamw #define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW 0x0080000 77*da6c28aaSamw 78*da6c28aaSamw #define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000 79*da6c28aaSamw #define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000 80*da6c28aaSamw #define ACL_WRITE_NAMED_WRITER_ERR_DENY 0x0400000 81*da6c28aaSamw #define ACL_WRITE_NAMED_WRITER_ERR_ALLOW 0x0800000 82*da6c28aaSamw 83*da6c28aaSamw #define ACL_READ_NAMED_READER_SET_DENY 0x1000000 84*da6c28aaSamw #define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000 85*da6c28aaSamw #define ACL_READ_NAMED_READER_ERR_DENY 0x4000000 86*da6c28aaSamw #define ACL_READ_NAMED_READER_ERR_ALLOW 0x8000000 87*da6c28aaSamw 88*da6c28aaSamw 89*da6c28aaSamw #define ACE_VALID_MASK_BITS (\ 90*da6c28aaSamw ACE_READ_DATA | \ 91*da6c28aaSamw ACE_LIST_DIRECTORY | \ 92*da6c28aaSamw ACE_WRITE_DATA | \ 93*da6c28aaSamw ACE_ADD_FILE | \ 94*da6c28aaSamw ACE_APPEND_DATA | \ 95*da6c28aaSamw ACE_ADD_SUBDIRECTORY | \ 96*da6c28aaSamw ACE_READ_NAMED_ATTRS | \ 97*da6c28aaSamw ACE_WRITE_NAMED_ATTRS | \ 98*da6c28aaSamw ACE_EXECUTE | \ 99*da6c28aaSamw ACE_DELETE_CHILD | \ 100*da6c28aaSamw ACE_READ_ATTRIBUTES | \ 101*da6c28aaSamw ACE_WRITE_ATTRIBUTES | \ 102*da6c28aaSamw ACE_DELETE | \ 103*da6c28aaSamw ACE_READ_ACL | \ 104*da6c28aaSamw ACE_WRITE_ACL | \ 105*da6c28aaSamw ACE_WRITE_OWNER | \ 106*da6c28aaSamw ACE_SYNCHRONIZE) 107*da6c28aaSamw 108*da6c28aaSamw #define ACE_MASK_UNDEFINED 0x80000000 109*da6c28aaSamw 110*da6c28aaSamw #define ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \ 111*da6c28aaSamw ACE_DIRECTORY_INHERIT_ACE | \ 112*da6c28aaSamw ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \ 113*da6c28aaSamw ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \ 114*da6c28aaSamw ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE) 115*da6c28aaSamw 116*da6c28aaSamw /* 117*da6c28aaSamw * ACL conversion helpers 118*da6c28aaSamw */ 119*da6c28aaSamw 120*da6c28aaSamw typedef enum { 121*da6c28aaSamw ace_unused, 122*da6c28aaSamw ace_user_obj, 123*da6c28aaSamw ace_user, 124*da6c28aaSamw ace_group, /* includes GROUP and GROUP_OBJ */ 125*da6c28aaSamw ace_other_obj 126*da6c28aaSamw } ace_to_aent_state_t; 127*da6c28aaSamw 128*da6c28aaSamw typedef struct acevals { 129*da6c28aaSamw uid_t key; 130*da6c28aaSamw avl_node_t avl; 131*da6c28aaSamw uint32_t mask; 132*da6c28aaSamw uint32_t allowed; 133*da6c28aaSamw uint32_t denied; 134*da6c28aaSamw int aent_type; 135*da6c28aaSamw } acevals_t; 136*da6c28aaSamw 137*da6c28aaSamw typedef struct ace_list { 138*da6c28aaSamw acevals_t user_obj; 139*da6c28aaSamw avl_tree_t user; 140*da6c28aaSamw int numusers; 141*da6c28aaSamw acevals_t group_obj; 142*da6c28aaSamw avl_tree_t group; 143*da6c28aaSamw int numgroups; 144*da6c28aaSamw acevals_t other_obj; 145*da6c28aaSamw uint32_t acl_mask; 146*da6c28aaSamw int hasmask; 147*da6c28aaSamw int dfacl_flag; 148*da6c28aaSamw ace_to_aent_state_t state; 149*da6c28aaSamw int seen; /* bitmask of all aclent_t a_type values seen */ 150*da6c28aaSamw } ace_list_t; 151fa9e4066Sahrens 152fa9e4066Sahrens ace_t trivial_acl[] = { 153f48205beScasper {(uid_t)-1, 0, ACE_OWNER, ACE_ACCESS_DENIED_ACE_TYPE}, 154f48205beScasper {(uid_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES| 155fa9e4066Sahrens ACE_WRITE_NAMED_ATTRS, ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE}, 156f48205beScasper {(uid_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP, 157f48205beScasper ACE_ACCESS_DENIED_ACE_TYPE}, 158f48205beScasper {(uid_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP, 159f48205beScasper ACE_ACCESS_ALLOWED_ACE_TYPE}, 160f48205beScasper {(uid_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER| ACE_WRITE_ATTRIBUTES| 161fa9e4066Sahrens ACE_WRITE_NAMED_ATTRS, ACE_EVERYONE, ACE_ACCESS_DENIED_ACE_TYPE}, 162f48205beScasper {(uid_t)-1, ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS| 163fa9e4066Sahrens ACE_SYNCHRONIZE, ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE} 164fa9e4066Sahrens }; 165fa9e4066Sahrens 166fa9e4066Sahrens 167fa9e4066Sahrens void 168*da6c28aaSamw adjust_ace_pair_common(void *pair, size_t access_off, 169*da6c28aaSamw size_t pairsize, mode_t mode) 170fa9e4066Sahrens { 171*da6c28aaSamw char *datap = (char *)pair; 172*da6c28aaSamw uint32_t *amask0 = (uint32_t *)(uintptr_t)(datap + access_off); 173*da6c28aaSamw uint32_t *amask1 = (uint32_t *)(uintptr_t)(datap + pairsize + 174*da6c28aaSamw access_off); 175fa9e4066Sahrens if (mode & S_IROTH) 176*da6c28aaSamw *amask1 |= ACE_READ_DATA; 177fa9e4066Sahrens else 178*da6c28aaSamw *amask0 |= ACE_READ_DATA; 179fa9e4066Sahrens if (mode & S_IWOTH) 180*da6c28aaSamw *amask1 |= ACE_WRITE_DATA|ACE_APPEND_DATA; 181fa9e4066Sahrens else 182*da6c28aaSamw *amask0 |= ACE_WRITE_DATA|ACE_APPEND_DATA; 183fa9e4066Sahrens if (mode & S_IXOTH) 184*da6c28aaSamw *amask1 |= ACE_EXECUTE; 185fa9e4066Sahrens else 186*da6c28aaSamw *amask0 |= ACE_EXECUTE; 187*da6c28aaSamw } 188*da6c28aaSamw 189*da6c28aaSamw void 190*da6c28aaSamw adjust_ace_pair(ace_t *pair, mode_t mode) 191*da6c28aaSamw { 192*da6c28aaSamw adjust_ace_pair_common(pair, offsetof(ace_t, a_access_mask), 193*da6c28aaSamw sizeof (ace_t), mode); 194fa9e4066Sahrens } 195fa9e4066Sahrens 196fa9e4066Sahrens /* 197fa9e4066Sahrens * ace_trivial: 198fa9e4066Sahrens * determine whether an ace_t acl is trivial 199fa9e4066Sahrens * 200*da6c28aaSamw * Trivialness implies that the acl is composed of only 201fa9e4066Sahrens * owner, group, everyone entries. ACL can't 202fa9e4066Sahrens * have read_acl denied, and write_owner/write_acl/write_attributes 203fa9e4066Sahrens * can only be owner@ entry. 204fa9e4066Sahrens */ 205fa9e4066Sahrens int 206*da6c28aaSamw ace_trivial_common(void *acep, int aclcnt, 207*da6c28aaSamw uint64_t (*walk)(void *, uint64_t, int aclcnt, 208*da6c28aaSamw uint16_t *, uint16_t *, uint32_t *)) 209fa9e4066Sahrens { 210fa9e4066Sahrens int owner_seen = 0; 211fa9e4066Sahrens int group_seen = 0; 212fa9e4066Sahrens int everyone_seen = 0; 213*da6c28aaSamw uint16_t flags; 214*da6c28aaSamw uint32_t mask; 215*da6c28aaSamw uint16_t type; 216*da6c28aaSamw uint64_t cookie = 0; 217fa9e4066Sahrens 218*da6c28aaSamw while (cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask)) { 219*da6c28aaSamw switch (flags & ACE_TYPE_FLAGS) { 220fa9e4066Sahrens case ACE_OWNER: 221fa9e4066Sahrens if (group_seen || everyone_seen) 222fa9e4066Sahrens return (1); 223fa9e4066Sahrens owner_seen++; 224fa9e4066Sahrens break; 225fa9e4066Sahrens case ACE_GROUP|ACE_IDENTIFIER_GROUP: 226fa9e4066Sahrens if (everyone_seen || owner_seen == 0) 227fa9e4066Sahrens return (1); 228fa9e4066Sahrens group_seen++; 229fa9e4066Sahrens break; 230fa9e4066Sahrens 231fa9e4066Sahrens case ACE_EVERYONE: 232fa9e4066Sahrens if (owner_seen == 0 || group_seen == 0) 233fa9e4066Sahrens return (1); 234fa9e4066Sahrens everyone_seen++; 235fa9e4066Sahrens break; 236fa9e4066Sahrens default: 237fa9e4066Sahrens return (1); 238fa9e4066Sahrens 239fa9e4066Sahrens } 240fa9e4066Sahrens 241*da6c28aaSamw if (flags & (ACE_FILE_INHERIT_ACE| 242fa9e4066Sahrens ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE| 243fa9e4066Sahrens ACE_INHERIT_ONLY_ACE)) 244fa9e4066Sahrens return (1); 245fa9e4066Sahrens 246fa9e4066Sahrens /* 247fa9e4066Sahrens * Special check for some special bits 248fa9e4066Sahrens * 249de122929Smarks * Don't allow anybody to deny reading basic 250de122929Smarks * attributes or a files ACL. 251fa9e4066Sahrens */ 252*da6c28aaSamw if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) && 253*da6c28aaSamw (type == ACE_ACCESS_DENIED_ACE_TYPE)) 254fa9e4066Sahrens return (1); 255fa9e4066Sahrens 256fa9e4066Sahrens /* 257fa9e4066Sahrens * Allow on owner@ to allow 258fa9e4066Sahrens * write_acl/write_owner/write_attributes 259fa9e4066Sahrens */ 260*da6c28aaSamw if (type == ACE_ACCESS_ALLOWED_ACE_TYPE && 261*da6c28aaSamw (!(flags & ACE_OWNER) && (mask & 262fa9e4066Sahrens (ACE_WRITE_OWNER|ACE_WRITE_ACL|ACE_WRITE_ATTRIBUTES)))) 263fa9e4066Sahrens return (1); 264*da6c28aaSamw 265fa9e4066Sahrens } 266fa9e4066Sahrens 267fa9e4066Sahrens if ((owner_seen == 0) || (group_seen == 0) || (everyone_seen == 0)) 268*da6c28aaSamw return (1); 269fa9e4066Sahrens 270fa9e4066Sahrens return (0); 271fa9e4066Sahrens } 272fa9e4066Sahrens 273*da6c28aaSamw uint64_t 274*da6c28aaSamw ace_walk(void *datap, uint64_t cookie, int aclcnt, uint16_t *flags, 275*da6c28aaSamw uint16_t *type, uint32_t *mask) 276*da6c28aaSamw { 277*da6c28aaSamw ace_t *acep = datap; 278*da6c28aaSamw 279*da6c28aaSamw *flags = acep[cookie].a_flags; 280*da6c28aaSamw *type = acep[cookie].a_type; 281*da6c28aaSamw *mask = acep[cookie++].a_access_mask; 282*da6c28aaSamw 283*da6c28aaSamw if (cookie > aclcnt) 284*da6c28aaSamw return (0); 285*da6c28aaSamw else 286*da6c28aaSamw return (cookie); 287*da6c28aaSamw } 288*da6c28aaSamw 289*da6c28aaSamw int 290*da6c28aaSamw ace_trivial(ace_t *acep, int aclcnt) 291*da6c28aaSamw { 292*da6c28aaSamw return (ace_trivial_common(acep, aclcnt, ace_walk)); 293*da6c28aaSamw } 294fa9e4066Sahrens 295fa9e4066Sahrens /* 296fa9e4066Sahrens * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified. 297fa9e4066Sahrens * v = Ptr to array/vector of objs 298fa9e4066Sahrens * n = # objs in the array 299fa9e4066Sahrens * s = size of each obj (must be multiples of a word size) 300fa9e4066Sahrens * f = ptr to function to compare two objs 301fa9e4066Sahrens * returns (-1 = less than, 0 = equal, 1 = greater than 302fa9e4066Sahrens */ 303fa9e4066Sahrens void 304fa9e4066Sahrens ksort(caddr_t v, int n, int s, int (*f)()) 305fa9e4066Sahrens { 306fa9e4066Sahrens int g, i, j, ii; 307fa9e4066Sahrens unsigned int *p1, *p2; 308fa9e4066Sahrens unsigned int tmp; 309fa9e4066Sahrens 310fa9e4066Sahrens /* No work to do */ 311fa9e4066Sahrens if (v == NULL || n <= 1) 312fa9e4066Sahrens return; 313fa9e4066Sahrens 314fa9e4066Sahrens /* Sanity check on arguments */ 315fa9e4066Sahrens ASSERT(((uintptr_t)v & 0x3) == 0 && (s & 0x3) == 0); 316fa9e4066Sahrens ASSERT(s > 0); 317fa9e4066Sahrens for (g = n / 2; g > 0; g /= 2) { 318fa9e4066Sahrens for (i = g; i < n; i++) { 319fa9e4066Sahrens for (j = i - g; j >= 0 && 320*da6c28aaSamw (*f)(v + j * s, v + (j + g) * s) == 1; 321*da6c28aaSamw j -= g) { 322fa9e4066Sahrens p1 = (void *)(v + j * s); 323fa9e4066Sahrens p2 = (void *)(v + (j + g) * s); 324fa9e4066Sahrens for (ii = 0; ii < s / 4; ii++) { 325fa9e4066Sahrens tmp = *p1; 326fa9e4066Sahrens *p1++ = *p2; 327fa9e4066Sahrens *p2++ = tmp; 328fa9e4066Sahrens } 329fa9e4066Sahrens } 330fa9e4066Sahrens } 331fa9e4066Sahrens } 332fa9e4066Sahrens } 333fa9e4066Sahrens 334fa9e4066Sahrens /* 335fa9e4066Sahrens * Compare two acls, all fields. Returns: 336fa9e4066Sahrens * -1 (less than) 337fa9e4066Sahrens * 0 (equal) 338fa9e4066Sahrens * +1 (greater than) 339fa9e4066Sahrens */ 340fa9e4066Sahrens int 341fa9e4066Sahrens cmp2acls(void *a, void *b) 342fa9e4066Sahrens { 343fa9e4066Sahrens aclent_t *x = (aclent_t *)a; 344fa9e4066Sahrens aclent_t *y = (aclent_t *)b; 345fa9e4066Sahrens 346fa9e4066Sahrens /* Compare types */ 347fa9e4066Sahrens if (x->a_type < y->a_type) 348fa9e4066Sahrens return (-1); 349fa9e4066Sahrens if (x->a_type > y->a_type) 350fa9e4066Sahrens return (1); 351fa9e4066Sahrens /* Equal types; compare id's */ 352fa9e4066Sahrens if (x->a_id < y->a_id) 353fa9e4066Sahrens return (-1); 354fa9e4066Sahrens if (x->a_id > y->a_id) 355fa9e4066Sahrens return (1); 356fa9e4066Sahrens /* Equal ids; compare perms */ 357fa9e4066Sahrens if (x->a_perm < y->a_perm) 358fa9e4066Sahrens return (-1); 359fa9e4066Sahrens if (x->a_perm > y->a_perm) 360fa9e4066Sahrens return (1); 361fa9e4066Sahrens /* Totally equal */ 362fa9e4066Sahrens return (0); 363fa9e4066Sahrens } 364*da6c28aaSamw 365*da6c28aaSamw /*ARGSUSED*/ 366*da6c28aaSamw static void * 367*da6c28aaSamw cacl_realloc(void *ptr, size_t size, size_t new_size) 368*da6c28aaSamw { 369*da6c28aaSamw #if defined(_KERNEL) 370*da6c28aaSamw void *tmp; 371*da6c28aaSamw 372*da6c28aaSamw tmp = kmem_alloc(new_size, KM_SLEEP); 373*da6c28aaSamw (void) memcpy(tmp, ptr, (size < new_size) ? size : new_size); 374*da6c28aaSamw kmem_free(ptr, size); 375*da6c28aaSamw return (tmp); 376*da6c28aaSamw #else 377*da6c28aaSamw return (realloc(ptr, new_size)); 378*da6c28aaSamw #endif 379*da6c28aaSamw } 380*da6c28aaSamw 381*da6c28aaSamw static int 382*da6c28aaSamw cacl_malloc(void **ptr, size_t size) 383*da6c28aaSamw { 384*da6c28aaSamw #if defined(_KERNEL) 385*da6c28aaSamw *ptr = kmem_zalloc(size, KM_SLEEP); 386*da6c28aaSamw return (0); 387*da6c28aaSamw #else 388*da6c28aaSamw *ptr = calloc(1, size); 389*da6c28aaSamw if (*ptr == NULL) 390*da6c28aaSamw return (errno); 391*da6c28aaSamw 392*da6c28aaSamw return (0); 393*da6c28aaSamw #endif 394*da6c28aaSamw } 395*da6c28aaSamw 396*da6c28aaSamw /*ARGSUSED*/ 397*da6c28aaSamw static void 398*da6c28aaSamw cacl_free(void *ptr, size_t size) 399*da6c28aaSamw { 400*da6c28aaSamw #if defined(_KERNEL) 401*da6c28aaSamw kmem_free(ptr, size); 402*da6c28aaSamw #else 403*da6c28aaSamw free(ptr); 404*da6c28aaSamw #endif 405*da6c28aaSamw } 406*da6c28aaSamw 407*da6c28aaSamw acl_t * 408*da6c28aaSamw acl_alloc(enum acl_type type) 409*da6c28aaSamw { 410*da6c28aaSamw acl_t *aclp; 411*da6c28aaSamw 412*da6c28aaSamw if (cacl_malloc((void **)&aclp, sizeof (acl_t)) != 0) 413*da6c28aaSamw return (NULL); 414*da6c28aaSamw 415*da6c28aaSamw aclp->acl_aclp = NULL; 416*da6c28aaSamw aclp->acl_cnt = 0; 417*da6c28aaSamw 418*da6c28aaSamw switch (type) { 419*da6c28aaSamw case ACE_T: 420*da6c28aaSamw aclp->acl_type = ACE_T; 421*da6c28aaSamw aclp->acl_entry_size = sizeof (ace_t); 422*da6c28aaSamw break; 423*da6c28aaSamw case ACLENT_T: 424*da6c28aaSamw aclp->acl_type = ACLENT_T; 425*da6c28aaSamw aclp->acl_entry_size = sizeof (aclent_t); 426*da6c28aaSamw break; 427*da6c28aaSamw default: 428*da6c28aaSamw acl_free(aclp); 429*da6c28aaSamw aclp = NULL; 430*da6c28aaSamw } 431*da6c28aaSamw return (aclp); 432*da6c28aaSamw } 433*da6c28aaSamw 434*da6c28aaSamw /* 435*da6c28aaSamw * Free acl_t structure 436*da6c28aaSamw */ 437*da6c28aaSamw void 438*da6c28aaSamw acl_free(acl_t *aclp) 439*da6c28aaSamw { 440*da6c28aaSamw int acl_size; 441*da6c28aaSamw 442*da6c28aaSamw if (aclp == NULL) 443*da6c28aaSamw return; 444*da6c28aaSamw 445*da6c28aaSamw if (aclp->acl_aclp) { 446*da6c28aaSamw acl_size = aclp->acl_cnt * aclp->acl_entry_size; 447*da6c28aaSamw cacl_free(aclp->acl_aclp, acl_size); 448*da6c28aaSamw } 449*da6c28aaSamw 450*da6c28aaSamw cacl_free(aclp, sizeof (acl_t)); 451*da6c28aaSamw } 452*da6c28aaSamw 453*da6c28aaSamw static uint32_t 454*da6c28aaSamw access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow) 455*da6c28aaSamw { 456*da6c28aaSamw uint32_t access_mask = 0; 457*da6c28aaSamw int acl_produce; 458*da6c28aaSamw int synchronize_set = 0, write_owner_set = 0; 459*da6c28aaSamw int delete_set = 0, write_attrs_set = 0; 460*da6c28aaSamw int read_named_set = 0, write_named_set = 0; 461*da6c28aaSamw 462*da6c28aaSamw acl_produce = (ACL_SYNCHRONIZE_SET_ALLOW | 463*da6c28aaSamw ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 464*da6c28aaSamw ACL_WRITE_ATTRS_WRITER_SET_DENY); 465*da6c28aaSamw 466*da6c28aaSamw if (isallow) { 467*da6c28aaSamw synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW; 468*da6c28aaSamw write_owner_set = ACL_WRITE_OWNER_SET_ALLOW; 469*da6c28aaSamw delete_set = ACL_DELETE_SET_ALLOW; 470*da6c28aaSamw if (hasreadperm) 471*da6c28aaSamw read_named_set = ACL_READ_NAMED_READER_SET_ALLOW; 472*da6c28aaSamw if (haswriteperm) 473*da6c28aaSamw write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 474*da6c28aaSamw if (isowner) 475*da6c28aaSamw write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 476*da6c28aaSamw else if (haswriteperm) 477*da6c28aaSamw write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 478*da6c28aaSamw } else { 479*da6c28aaSamw 480*da6c28aaSamw synchronize_set = ACL_SYNCHRONIZE_SET_DENY; 481*da6c28aaSamw write_owner_set = ACL_WRITE_OWNER_SET_DENY; 482*da6c28aaSamw delete_set = ACL_DELETE_SET_DENY; 483*da6c28aaSamw if (hasreadperm) 484*da6c28aaSamw read_named_set = ACL_READ_NAMED_READER_SET_DENY; 485*da6c28aaSamw if (haswriteperm) 486*da6c28aaSamw write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY; 487*da6c28aaSamw if (isowner) 488*da6c28aaSamw write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY; 489*da6c28aaSamw else if (haswriteperm) 490*da6c28aaSamw write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY; 491*da6c28aaSamw else 492*da6c28aaSamw /* 493*da6c28aaSamw * If the entity is not the owner and does not 494*da6c28aaSamw * have write permissions ACE_WRITE_ATTRIBUTES will 495*da6c28aaSamw * always go in the DENY ACE. 496*da6c28aaSamw */ 497*da6c28aaSamw access_mask |= ACE_WRITE_ATTRIBUTES; 498*da6c28aaSamw } 499*da6c28aaSamw 500*da6c28aaSamw if (acl_produce & synchronize_set) 501*da6c28aaSamw access_mask |= ACE_SYNCHRONIZE; 502*da6c28aaSamw if (acl_produce & write_owner_set) 503*da6c28aaSamw access_mask |= ACE_WRITE_OWNER; 504*da6c28aaSamw if (acl_produce & delete_set) 505*da6c28aaSamw access_mask |= ACE_DELETE; 506*da6c28aaSamw if (acl_produce & write_attrs_set) 507*da6c28aaSamw access_mask |= ACE_WRITE_ATTRIBUTES; 508*da6c28aaSamw if (acl_produce & read_named_set) 509*da6c28aaSamw access_mask |= ACE_READ_NAMED_ATTRS; 510*da6c28aaSamw if (acl_produce & write_named_set) 511*da6c28aaSamw access_mask |= ACE_WRITE_NAMED_ATTRS; 512*da6c28aaSamw 513*da6c28aaSamw return (access_mask); 514*da6c28aaSamw } 515*da6c28aaSamw 516*da6c28aaSamw /* 517*da6c28aaSamw * Given an mode_t, convert it into an access_mask as used 518*da6c28aaSamw * by nfsace, assuming aclent_t -> nfsace semantics. 519*da6c28aaSamw */ 520*da6c28aaSamw static uint32_t 521*da6c28aaSamw mode_to_ace_access(mode_t mode, int isdir, int isowner, int isallow) 522*da6c28aaSamw { 523*da6c28aaSamw uint32_t access = 0; 524*da6c28aaSamw int haswriteperm = 0; 525*da6c28aaSamw int hasreadperm = 0; 526*da6c28aaSamw 527*da6c28aaSamw if (isallow) { 528*da6c28aaSamw haswriteperm = (mode & S_IWOTH); 529*da6c28aaSamw hasreadperm = (mode & S_IROTH); 530*da6c28aaSamw } else { 531*da6c28aaSamw haswriteperm = !(mode & S_IWOTH); 532*da6c28aaSamw hasreadperm = !(mode & S_IROTH); 533*da6c28aaSamw } 534*da6c28aaSamw 535*da6c28aaSamw /* 536*da6c28aaSamw * The following call takes care of correctly setting the following 537*da6c28aaSamw * mask bits in the access_mask: 538*da6c28aaSamw * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE, 539*da6c28aaSamw * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS 540*da6c28aaSamw */ 541*da6c28aaSamw access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow); 542*da6c28aaSamw 543*da6c28aaSamw if (isallow) { 544*da6c28aaSamw access |= ACE_READ_ACL | ACE_READ_ATTRIBUTES; 545*da6c28aaSamw if (isowner) 546*da6c28aaSamw access |= ACE_WRITE_ACL; 547*da6c28aaSamw } else { 548*da6c28aaSamw if (! isowner) 549*da6c28aaSamw access |= ACE_WRITE_ACL; 550*da6c28aaSamw } 551*da6c28aaSamw 552*da6c28aaSamw /* read */ 553*da6c28aaSamw if (mode & S_IROTH) { 554*da6c28aaSamw access |= ACE_READ_DATA; 555*da6c28aaSamw } 556*da6c28aaSamw /* write */ 557*da6c28aaSamw if (mode & S_IWOTH) { 558*da6c28aaSamw access |= ACE_WRITE_DATA | 559*da6c28aaSamw ACE_APPEND_DATA; 560*da6c28aaSamw if (isdir) 561*da6c28aaSamw access |= ACE_DELETE_CHILD; 562*da6c28aaSamw } 563*da6c28aaSamw /* exec */ 564*da6c28aaSamw if (mode & 01) { 565*da6c28aaSamw access |= ACE_EXECUTE; 566*da6c28aaSamw } 567*da6c28aaSamw 568*da6c28aaSamw return (access); 569*da6c28aaSamw } 570*da6c28aaSamw 571*da6c28aaSamw /* 572*da6c28aaSamw * Given an nfsace (presumably an ALLOW entry), make a 573*da6c28aaSamw * corresponding DENY entry at the address given. 574*da6c28aaSamw */ 575*da6c28aaSamw static void 576*da6c28aaSamw ace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner) 577*da6c28aaSamw { 578*da6c28aaSamw (void) memcpy(deny, allow, sizeof (ace_t)); 579*da6c28aaSamw 580*da6c28aaSamw deny->a_who = allow->a_who; 581*da6c28aaSamw 582*da6c28aaSamw deny->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 583*da6c28aaSamw deny->a_access_mask ^= ACE_POSIX_SUPPORTED_BITS; 584*da6c28aaSamw if (isdir) 585*da6c28aaSamw deny->a_access_mask ^= ACE_DELETE_CHILD; 586*da6c28aaSamw 587*da6c28aaSamw deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER | 588*da6c28aaSamw ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS | 589*da6c28aaSamw ACE_WRITE_NAMED_ATTRS); 590*da6c28aaSamw deny->a_access_mask |= access_mask_set((allow->a_access_mask & 591*da6c28aaSamw ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner, 592*da6c28aaSamw B_FALSE); 593*da6c28aaSamw } 594*da6c28aaSamw /* 595*da6c28aaSamw * Make an initial pass over an array of aclent_t's. Gather 596*da6c28aaSamw * information such as an ACL_MASK (if any), number of users, 597*da6c28aaSamw * number of groups, and whether the array needs to be sorted. 598*da6c28aaSamw */ 599*da6c28aaSamw static int 600*da6c28aaSamw ln_aent_preprocess(aclent_t *aclent, int n, 601*da6c28aaSamw int *hasmask, mode_t *mask, 602*da6c28aaSamw int *numuser, int *numgroup, int *needsort) 603*da6c28aaSamw { 604*da6c28aaSamw int error = 0; 605*da6c28aaSamw int i; 606*da6c28aaSamw int curtype = 0; 607*da6c28aaSamw 608*da6c28aaSamw *hasmask = 0; 609*da6c28aaSamw *mask = 07; 610*da6c28aaSamw *needsort = 0; 611*da6c28aaSamw *numuser = 0; 612*da6c28aaSamw *numgroup = 0; 613*da6c28aaSamw 614*da6c28aaSamw for (i = 0; i < n; i++) { 615*da6c28aaSamw if (aclent[i].a_type < curtype) 616*da6c28aaSamw *needsort = 1; 617*da6c28aaSamw else if (aclent[i].a_type > curtype) 618*da6c28aaSamw curtype = aclent[i].a_type; 619*da6c28aaSamw if (aclent[i].a_type & USER) 620*da6c28aaSamw (*numuser)++; 621*da6c28aaSamw if (aclent[i].a_type & (GROUP | GROUP_OBJ)) 622*da6c28aaSamw (*numgroup)++; 623*da6c28aaSamw if (aclent[i].a_type & CLASS_OBJ) { 624*da6c28aaSamw if (*hasmask) { 625*da6c28aaSamw error = EINVAL; 626*da6c28aaSamw goto out; 627*da6c28aaSamw } else { 628*da6c28aaSamw *hasmask = 1; 629*da6c28aaSamw *mask = aclent[i].a_perm; 630*da6c28aaSamw } 631*da6c28aaSamw } 632*da6c28aaSamw } 633*da6c28aaSamw 634*da6c28aaSamw if ((! *hasmask) && (*numuser + *numgroup > 1)) { 635*da6c28aaSamw error = EINVAL; 636*da6c28aaSamw goto out; 637*da6c28aaSamw } 638*da6c28aaSamw 639*da6c28aaSamw out: 640*da6c28aaSamw return (error); 641*da6c28aaSamw } 642*da6c28aaSamw 643*da6c28aaSamw /* 644*da6c28aaSamw * Convert an array of aclent_t into an array of nfsace entries, 645*da6c28aaSamw * following POSIX draft -> nfsv4 conversion semantics as outlined in 646*da6c28aaSamw * the IETF draft. 647*da6c28aaSamw */ 648*da6c28aaSamw static int 649*da6c28aaSamw ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir) 650*da6c28aaSamw { 651*da6c28aaSamw int error = 0; 652*da6c28aaSamw mode_t mask; 653*da6c28aaSamw int numuser, numgroup, needsort; 654*da6c28aaSamw int resultsize = 0; 655*da6c28aaSamw int i, groupi = 0, skip; 656*da6c28aaSamw ace_t *acep, *result = NULL; 657*da6c28aaSamw int hasmask; 658*da6c28aaSamw 659*da6c28aaSamw error = ln_aent_preprocess(aclent, n, &hasmask, &mask, 660*da6c28aaSamw &numuser, &numgroup, &needsort); 661*da6c28aaSamw if (error != 0) 662*da6c28aaSamw goto out; 663*da6c28aaSamw 664*da6c28aaSamw /* allow + deny for each aclent */ 665*da6c28aaSamw resultsize = n * 2; 666*da6c28aaSamw if (hasmask) { 667*da6c28aaSamw /* 668*da6c28aaSamw * stick extra deny on the group_obj and on each 669*da6c28aaSamw * user|group for the mask (the group_obj was added 670*da6c28aaSamw * into the count for numgroup) 671*da6c28aaSamw */ 672*da6c28aaSamw resultsize += numuser + numgroup; 673*da6c28aaSamw /* ... and don't count the mask itself */ 674*da6c28aaSamw resultsize -= 2; 675*da6c28aaSamw } 676*da6c28aaSamw 677*da6c28aaSamw /* sort the source if necessary */ 678*da6c28aaSamw if (needsort) 679*da6c28aaSamw ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls); 680*da6c28aaSamw 681*da6c28aaSamw if (cacl_malloc((void **)&result, resultsize * sizeof (ace_t)) != 0) 682*da6c28aaSamw goto out; 683*da6c28aaSamw 684*da6c28aaSamw acep = result; 685*da6c28aaSamw 686*da6c28aaSamw for (i = 0; i < n; i++) { 687*da6c28aaSamw /* 688*da6c28aaSamw * don't process CLASS_OBJ (mask); mask was grabbed in 689*da6c28aaSamw * ln_aent_preprocess() 690*da6c28aaSamw */ 691*da6c28aaSamw if (aclent[i].a_type & CLASS_OBJ) 692*da6c28aaSamw continue; 693*da6c28aaSamw 694*da6c28aaSamw /* If we need an ACL_MASK emulator, prepend it now */ 695*da6c28aaSamw if ((hasmask) && 696*da6c28aaSamw (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) { 697*da6c28aaSamw acep->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 698*da6c28aaSamw acep->a_flags = 0; 699*da6c28aaSamw if (aclent[i].a_type & GROUP_OBJ) { 700*da6c28aaSamw acep->a_who = (uid_t)-1; 701*da6c28aaSamw acep->a_flags |= 702*da6c28aaSamw (ACE_IDENTIFIER_GROUP|ACE_GROUP); 703*da6c28aaSamw } else if (aclent[i].a_type & USER) { 704*da6c28aaSamw acep->a_who = aclent[i].a_id; 705*da6c28aaSamw } else { 706*da6c28aaSamw acep->a_who = aclent[i].a_id; 707*da6c28aaSamw acep->a_flags |= ACE_IDENTIFIER_GROUP; 708*da6c28aaSamw } 709*da6c28aaSamw if (aclent[i].a_type & ACL_DEFAULT) { 710*da6c28aaSamw acep->a_flags |= ACE_INHERIT_ONLY_ACE | 711*da6c28aaSamw ACE_FILE_INHERIT_ACE | 712*da6c28aaSamw ACE_DIRECTORY_INHERIT_ACE; 713*da6c28aaSamw } 714*da6c28aaSamw /* 715*da6c28aaSamw * Set the access mask for the prepended deny 716*da6c28aaSamw * ace. To do this, we invert the mask (found 717*da6c28aaSamw * in ln_aent_preprocess()) then convert it to an 718*da6c28aaSamw * DENY ace access_mask. 719*da6c28aaSamw */ 720*da6c28aaSamw acep->a_access_mask = mode_to_ace_access((mask ^ 07), 721*da6c28aaSamw isdir, 0, 0); 722*da6c28aaSamw acep += 1; 723*da6c28aaSamw } 724*da6c28aaSamw 725*da6c28aaSamw /* handle a_perm -> access_mask */ 726*da6c28aaSamw acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm, 727*da6c28aaSamw isdir, aclent[i].a_type & USER_OBJ, 1); 728*da6c28aaSamw 729*da6c28aaSamw /* emulate a default aclent */ 730*da6c28aaSamw if (aclent[i].a_type & ACL_DEFAULT) { 731*da6c28aaSamw acep->a_flags |= ACE_INHERIT_ONLY_ACE | 732*da6c28aaSamw ACE_FILE_INHERIT_ACE | 733*da6c28aaSamw ACE_DIRECTORY_INHERIT_ACE; 734*da6c28aaSamw } 735*da6c28aaSamw 736*da6c28aaSamw /* 737*da6c28aaSamw * handle a_perm and a_id 738*da6c28aaSamw * 739*da6c28aaSamw * this must be done last, since it involves the 740*da6c28aaSamw * corresponding deny aces, which are handled 741*da6c28aaSamw * differently for each different a_type. 742*da6c28aaSamw */ 743*da6c28aaSamw if (aclent[i].a_type & USER_OBJ) { 744*da6c28aaSamw acep->a_who = (uid_t)-1; 745*da6c28aaSamw acep->a_flags |= ACE_OWNER; 746*da6c28aaSamw ace_make_deny(acep, acep + 1, isdir, B_TRUE); 747*da6c28aaSamw acep += 2; 748*da6c28aaSamw } else if (aclent[i].a_type & USER) { 749*da6c28aaSamw acep->a_who = aclent[i].a_id; 750*da6c28aaSamw ace_make_deny(acep, acep + 1, isdir, B_FALSE); 751*da6c28aaSamw acep += 2; 752*da6c28aaSamw } else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) { 753*da6c28aaSamw if (aclent[i].a_type & GROUP_OBJ) { 754*da6c28aaSamw acep->a_who = (uid_t)-1; 755*da6c28aaSamw acep->a_flags |= ACE_GROUP; 756*da6c28aaSamw } else { 757*da6c28aaSamw acep->a_who = aclent[i].a_id; 758*da6c28aaSamw } 759*da6c28aaSamw acep->a_flags |= ACE_IDENTIFIER_GROUP; 760*da6c28aaSamw /* 761*da6c28aaSamw * Set the corresponding deny for the group ace. 762*da6c28aaSamw * 763*da6c28aaSamw * The deny aces go after all of the groups, unlike 764*da6c28aaSamw * everything else, where they immediately follow 765*da6c28aaSamw * the allow ace. 766*da6c28aaSamw * 767*da6c28aaSamw * We calculate "skip", the number of slots to 768*da6c28aaSamw * skip ahead for the deny ace, here. 769*da6c28aaSamw * 770*da6c28aaSamw * The pattern is: 771*da6c28aaSamw * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3 772*da6c28aaSamw * thus, skip is 773*da6c28aaSamw * (2 * numgroup) - 1 - groupi 774*da6c28aaSamw * (2 * numgroup) to account for MD + A 775*da6c28aaSamw * - 1 to account for the fact that we're on the 776*da6c28aaSamw * access (A), not the mask (MD) 777*da6c28aaSamw * - groupi to account for the fact that we have 778*da6c28aaSamw * passed up groupi number of MD's. 779*da6c28aaSamw */ 780*da6c28aaSamw skip = (2 * numgroup) - 1 - groupi; 781*da6c28aaSamw ace_make_deny(acep, acep + skip, isdir, B_FALSE); 782*da6c28aaSamw /* 783*da6c28aaSamw * If we just did the last group, skip acep past 784*da6c28aaSamw * all of the denies; else, just move ahead one. 785*da6c28aaSamw */ 786*da6c28aaSamw if (++groupi >= numgroup) 787*da6c28aaSamw acep += numgroup + 1; 788*da6c28aaSamw else 789*da6c28aaSamw acep += 1; 790*da6c28aaSamw } else if (aclent[i].a_type & OTHER_OBJ) { 791*da6c28aaSamw acep->a_who = (uid_t)-1; 792*da6c28aaSamw acep->a_flags |= ACE_EVERYONE; 793*da6c28aaSamw ace_make_deny(acep, acep + 1, isdir, B_FALSE); 794*da6c28aaSamw acep += 2; 795*da6c28aaSamw } else { 796*da6c28aaSamw error = EINVAL; 797*da6c28aaSamw goto out; 798*da6c28aaSamw } 799*da6c28aaSamw } 800*da6c28aaSamw 801*da6c28aaSamw *acepp = result; 802*da6c28aaSamw *rescount = resultsize; 803*da6c28aaSamw 804*da6c28aaSamw out: 805*da6c28aaSamw if (error != 0) { 806*da6c28aaSamw if ((result != NULL) && (resultsize > 0)) { 807*da6c28aaSamw cacl_free(result, resultsize * sizeof (ace_t)); 808*da6c28aaSamw } 809*da6c28aaSamw } 810*da6c28aaSamw 811*da6c28aaSamw return (error); 812*da6c28aaSamw } 813*da6c28aaSamw 814*da6c28aaSamw static int 815*da6c28aaSamw convert_aent_to_ace(aclent_t *aclentp, int aclcnt, int isdir, 816*da6c28aaSamw ace_t **retacep, int *retacecnt) 817*da6c28aaSamw { 818*da6c28aaSamw ace_t *acep; 819*da6c28aaSamw ace_t *dfacep; 820*da6c28aaSamw int acecnt = 0; 821*da6c28aaSamw int dfacecnt = 0; 822*da6c28aaSamw int dfaclstart = 0; 823*da6c28aaSamw int dfaclcnt = 0; 824*da6c28aaSamw aclent_t *aclp; 825*da6c28aaSamw int i; 826*da6c28aaSamw int error; 827*da6c28aaSamw int acesz, dfacesz; 828*da6c28aaSamw 829*da6c28aaSamw ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls); 830*da6c28aaSamw 831*da6c28aaSamw for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) { 832*da6c28aaSamw if (aclp->a_type & ACL_DEFAULT) 833*da6c28aaSamw break; 834*da6c28aaSamw } 835*da6c28aaSamw 836*da6c28aaSamw if (i < aclcnt) { 837*da6c28aaSamw dfaclstart = i; 838*da6c28aaSamw dfaclcnt = aclcnt - i; 839*da6c28aaSamw } 840*da6c28aaSamw 841*da6c28aaSamw if (dfaclcnt && isdir == 0) { 842*da6c28aaSamw return (EINVAL); 843*da6c28aaSamw } 844*da6c28aaSamw 845*da6c28aaSamw error = ln_aent_to_ace(aclentp, i, &acep, &acecnt, isdir); 846*da6c28aaSamw if (error) 847*da6c28aaSamw return (error); 848*da6c28aaSamw 849*da6c28aaSamw if (dfaclcnt) { 850*da6c28aaSamw error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt, 851*da6c28aaSamw &dfacep, &dfacecnt, isdir); 852*da6c28aaSamw if (error) { 853*da6c28aaSamw if (acep) { 854*da6c28aaSamw cacl_free(acep, acecnt * sizeof (ace_t)); 855*da6c28aaSamw } 856*da6c28aaSamw return (error); 857*da6c28aaSamw } 858*da6c28aaSamw } 859*da6c28aaSamw 860*da6c28aaSamw if (dfacecnt != 0) { 861*da6c28aaSamw acesz = sizeof (ace_t) * acecnt; 862*da6c28aaSamw dfacesz = sizeof (ace_t) * dfacecnt; 863*da6c28aaSamw acep = cacl_realloc(acep, acesz, acesz + dfacesz); 864*da6c28aaSamw if (acep == NULL) 865*da6c28aaSamw return (ENOMEM); 866*da6c28aaSamw if (dfaclcnt) { 867*da6c28aaSamw (void) memcpy(acep + acecnt, dfacep, dfacesz); 868*da6c28aaSamw } 869*da6c28aaSamw } 870*da6c28aaSamw if (dfaclcnt) 871*da6c28aaSamw cacl_free(dfacep, dfacecnt * sizeof (ace_t)); 872*da6c28aaSamw 873*da6c28aaSamw *retacecnt = acecnt + dfacecnt; 874*da6c28aaSamw *retacep = acep; 875*da6c28aaSamw return (0); 876*da6c28aaSamw } 877*da6c28aaSamw 878*da6c28aaSamw static int 879*da6c28aaSamw ace_mask_to_mode(uint32_t mask, o_mode_t *modep, int isdir) 880*da6c28aaSamw { 881*da6c28aaSamw int error = 0; 882*da6c28aaSamw o_mode_t mode = 0; 883*da6c28aaSamw uint32_t bits, wantbits; 884*da6c28aaSamw 885*da6c28aaSamw /* read */ 886*da6c28aaSamw if (mask & ACE_READ_DATA) 887*da6c28aaSamw mode |= S_IROTH; 888*da6c28aaSamw 889*da6c28aaSamw /* write */ 890*da6c28aaSamw wantbits = (ACE_WRITE_DATA | ACE_APPEND_DATA); 891*da6c28aaSamw if (isdir) 892*da6c28aaSamw wantbits |= ACE_DELETE_CHILD; 893*da6c28aaSamw bits = mask & wantbits; 894*da6c28aaSamw if (bits != 0) { 895*da6c28aaSamw if (bits != wantbits) { 896*da6c28aaSamw error = ENOTSUP; 897*da6c28aaSamw goto out; 898*da6c28aaSamw } 899*da6c28aaSamw mode |= S_IWOTH; 900*da6c28aaSamw } 901*da6c28aaSamw 902*da6c28aaSamw /* exec */ 903*da6c28aaSamw if (mask & ACE_EXECUTE) { 904*da6c28aaSamw mode |= S_IXOTH; 905*da6c28aaSamw } 906*da6c28aaSamw 907*da6c28aaSamw *modep = mode; 908*da6c28aaSamw 909*da6c28aaSamw out: 910*da6c28aaSamw return (error); 911*da6c28aaSamw } 912*da6c28aaSamw 913*da6c28aaSamw static void 914*da6c28aaSamw acevals_init(acevals_t *vals, uid_t key) 915*da6c28aaSamw { 916*da6c28aaSamw bzero(vals, sizeof (*vals)); 917*da6c28aaSamw vals->allowed = ACE_MASK_UNDEFINED; 918*da6c28aaSamw vals->denied = ACE_MASK_UNDEFINED; 919*da6c28aaSamw vals->mask = ACE_MASK_UNDEFINED; 920*da6c28aaSamw vals->key = key; 921*da6c28aaSamw } 922*da6c28aaSamw 923*da6c28aaSamw static void 924*da6c28aaSamw ace_list_init(ace_list_t *al, int dfacl_flag) 925*da6c28aaSamw { 926*da6c28aaSamw acevals_init(&al->user_obj, NULL); 927*da6c28aaSamw acevals_init(&al->group_obj, NULL); 928*da6c28aaSamw acevals_init(&al->other_obj, NULL); 929*da6c28aaSamw al->numusers = 0; 930*da6c28aaSamw al->numgroups = 0; 931*da6c28aaSamw al->acl_mask = 0; 932*da6c28aaSamw al->hasmask = 0; 933*da6c28aaSamw al->state = ace_unused; 934*da6c28aaSamw al->seen = 0; 935*da6c28aaSamw al->dfacl_flag = dfacl_flag; 936*da6c28aaSamw } 937*da6c28aaSamw 938*da6c28aaSamw /* 939*da6c28aaSamw * Find or create an acevals holder for a given id and avl tree. 940*da6c28aaSamw * 941*da6c28aaSamw * Note that only one thread will ever touch these avl trees, so 942*da6c28aaSamw * there is no need for locking. 943*da6c28aaSamw */ 944*da6c28aaSamw static acevals_t * 945*da6c28aaSamw acevals_find(ace_t *ace, avl_tree_t *avl, int *num) 946*da6c28aaSamw { 947*da6c28aaSamw acevals_t key, *rc; 948*da6c28aaSamw avl_index_t where; 949*da6c28aaSamw 950*da6c28aaSamw key.key = ace->a_who; 951*da6c28aaSamw rc = avl_find(avl, &key, &where); 952*da6c28aaSamw if (rc != NULL) 953*da6c28aaSamw return (rc); 954*da6c28aaSamw 955*da6c28aaSamw /* this memory is freed by ln_ace_to_aent()->ace_list_free() */ 956*da6c28aaSamw if (cacl_malloc((void **)&rc, sizeof (acevals_t)) != 0) 957*da6c28aaSamw return (NULL); 958*da6c28aaSamw 959*da6c28aaSamw acevals_init(rc, ace->a_who); 960*da6c28aaSamw avl_insert(avl, rc, where); 961*da6c28aaSamw (*num)++; 962*da6c28aaSamw 963*da6c28aaSamw return (rc); 964*da6c28aaSamw } 965*da6c28aaSamw 966*da6c28aaSamw static int 967*da6c28aaSamw access_mask_check(ace_t *acep, int mask_bit, int isowner) 968*da6c28aaSamw { 969*da6c28aaSamw int set_deny, err_deny; 970*da6c28aaSamw int set_allow, err_allow; 971*da6c28aaSamw int acl_consume; 972*da6c28aaSamw int haswriteperm, hasreadperm; 973*da6c28aaSamw 974*da6c28aaSamw if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) { 975*da6c28aaSamw haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 0 : 1; 976*da6c28aaSamw hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 0 : 1; 977*da6c28aaSamw } else { 978*da6c28aaSamw haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 1 : 0; 979*da6c28aaSamw hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 1 : 0; 980*da6c28aaSamw } 981*da6c28aaSamw 982*da6c28aaSamw acl_consume = (ACL_SYNCHRONIZE_ERR_DENY | 983*da6c28aaSamw ACL_DELETE_ERR_DENY | 984*da6c28aaSamw ACL_WRITE_OWNER_ERR_DENY | 985*da6c28aaSamw ACL_WRITE_OWNER_ERR_ALLOW | 986*da6c28aaSamw ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 987*da6c28aaSamw ACL_WRITE_ATTRS_OWNER_ERR_DENY | 988*da6c28aaSamw ACL_WRITE_ATTRS_WRITER_SET_DENY | 989*da6c28aaSamw ACL_WRITE_ATTRS_WRITER_ERR_ALLOW | 990*da6c28aaSamw ACL_WRITE_NAMED_WRITER_ERR_DENY | 991*da6c28aaSamw ACL_READ_NAMED_READER_ERR_DENY); 992*da6c28aaSamw 993*da6c28aaSamw if (mask_bit == ACE_SYNCHRONIZE) { 994*da6c28aaSamw set_deny = ACL_SYNCHRONIZE_SET_DENY; 995*da6c28aaSamw err_deny = ACL_SYNCHRONIZE_ERR_DENY; 996*da6c28aaSamw set_allow = ACL_SYNCHRONIZE_SET_ALLOW; 997*da6c28aaSamw err_allow = ACL_SYNCHRONIZE_ERR_ALLOW; 998*da6c28aaSamw } else if (mask_bit == ACE_WRITE_OWNER) { 999*da6c28aaSamw set_deny = ACL_WRITE_OWNER_SET_DENY; 1000*da6c28aaSamw err_deny = ACL_WRITE_OWNER_ERR_DENY; 1001*da6c28aaSamw set_allow = ACL_WRITE_OWNER_SET_ALLOW; 1002*da6c28aaSamw err_allow = ACL_WRITE_OWNER_ERR_ALLOW; 1003*da6c28aaSamw } else if (mask_bit == ACE_DELETE) { 1004*da6c28aaSamw set_deny = ACL_DELETE_SET_DENY; 1005*da6c28aaSamw err_deny = ACL_DELETE_ERR_DENY; 1006*da6c28aaSamw set_allow = ACL_DELETE_SET_ALLOW; 1007*da6c28aaSamw err_allow = ACL_DELETE_ERR_ALLOW; 1008*da6c28aaSamw } else if (mask_bit == ACE_WRITE_ATTRIBUTES) { 1009*da6c28aaSamw if (isowner) { 1010*da6c28aaSamw set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY; 1011*da6c28aaSamw err_deny = ACL_WRITE_ATTRS_OWNER_ERR_DENY; 1012*da6c28aaSamw set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 1013*da6c28aaSamw err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW; 1014*da6c28aaSamw } else if (haswriteperm) { 1015*da6c28aaSamw set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY; 1016*da6c28aaSamw err_deny = ACL_WRITE_ATTRS_WRITER_ERR_DENY; 1017*da6c28aaSamw set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 1018*da6c28aaSamw err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW; 1019*da6c28aaSamw } else { 1020*da6c28aaSamw if ((acep->a_access_mask & mask_bit) && 1021*da6c28aaSamw (acep->a_type & ACE_ACCESS_ALLOWED_ACE_TYPE)) { 1022*da6c28aaSamw return (ENOTSUP); 1023*da6c28aaSamw } 1024*da6c28aaSamw return (0); 1025*da6c28aaSamw } 1026*da6c28aaSamw } else if (mask_bit == ACE_READ_NAMED_ATTRS) { 1027*da6c28aaSamw if (!hasreadperm) 1028*da6c28aaSamw return (0); 1029*da6c28aaSamw 1030*da6c28aaSamw set_deny = ACL_READ_NAMED_READER_SET_DENY; 1031*da6c28aaSamw err_deny = ACL_READ_NAMED_READER_ERR_DENY; 1032*da6c28aaSamw set_allow = ACL_READ_NAMED_READER_SET_ALLOW; 1033*da6c28aaSamw err_allow = ACL_READ_NAMED_READER_ERR_ALLOW; 1034*da6c28aaSamw } else if (mask_bit == ACE_WRITE_NAMED_ATTRS) { 1035*da6c28aaSamw if (!haswriteperm) 1036*da6c28aaSamw return (0); 1037*da6c28aaSamw 1038*da6c28aaSamw set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY; 1039*da6c28aaSamw err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY; 1040*da6c28aaSamw set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 1041*da6c28aaSamw err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW; 1042*da6c28aaSamw } else { 1043*da6c28aaSamw return (EINVAL); 1044*da6c28aaSamw } 1045*da6c28aaSamw 1046*da6c28aaSamw if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) { 1047*da6c28aaSamw if (acl_consume & set_deny) { 1048*da6c28aaSamw if (!(acep->a_access_mask & mask_bit)) { 1049*da6c28aaSamw return (ENOTSUP); 1050*da6c28aaSamw } 1051*da6c28aaSamw } else if (acl_consume & err_deny) { 1052*da6c28aaSamw if (acep->a_access_mask & mask_bit) { 1053*da6c28aaSamw return (ENOTSUP); 1054*da6c28aaSamw } 1055*da6c28aaSamw } 1056*da6c28aaSamw } else { 1057*da6c28aaSamw /* ACE_ACCESS_ALLOWED_ACE_TYPE */ 1058*da6c28aaSamw if (acl_consume & set_allow) { 1059*da6c28aaSamw if (!(acep->a_access_mask & mask_bit)) { 1060*da6c28aaSamw return (ENOTSUP); 1061*da6c28aaSamw } 1062*da6c28aaSamw } else if (acl_consume & err_allow) { 1063*da6c28aaSamw if (acep->a_access_mask & mask_bit) { 1064*da6c28aaSamw return (ENOTSUP); 1065*da6c28aaSamw } 1066*da6c28aaSamw } 1067*da6c28aaSamw } 1068*da6c28aaSamw return (0); 1069*da6c28aaSamw } 1070*da6c28aaSamw 1071*da6c28aaSamw static int 1072*da6c28aaSamw ace_to_aent_legal(ace_t *acep) 1073*da6c28aaSamw { 1074*da6c28aaSamw int error = 0; 1075*da6c28aaSamw int isowner; 1076*da6c28aaSamw 1077*da6c28aaSamw /* only ALLOW or DENY */ 1078*da6c28aaSamw if ((acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE) && 1079*da6c28aaSamw (acep->a_type != ACE_ACCESS_DENIED_ACE_TYPE)) { 1080*da6c28aaSamw error = ENOTSUP; 1081*da6c28aaSamw goto out; 1082*da6c28aaSamw } 1083*da6c28aaSamw 1084*da6c28aaSamw /* check for invalid flags */ 1085*da6c28aaSamw if (acep->a_flags & ~(ACE_VALID_FLAG_BITS)) { 1086*da6c28aaSamw error = EINVAL; 1087*da6c28aaSamw goto out; 1088*da6c28aaSamw } 1089*da6c28aaSamw 1090*da6c28aaSamw /* some flags are illegal */ 1091*da6c28aaSamw if (acep->a_flags & (ACE_SUCCESSFUL_ACCESS_ACE_FLAG | 1092*da6c28aaSamw ACE_FAILED_ACCESS_ACE_FLAG | 1093*da6c28aaSamw ACE_NO_PROPAGATE_INHERIT_ACE)) { 1094*da6c28aaSamw error = ENOTSUP; 1095*da6c28aaSamw goto out; 1096*da6c28aaSamw } 1097*da6c28aaSamw 1098*da6c28aaSamw /* check for invalid masks */ 1099*da6c28aaSamw if (acep->a_access_mask & ~(ACE_VALID_MASK_BITS)) { 1100*da6c28aaSamw error = EINVAL; 1101*da6c28aaSamw goto out; 1102*da6c28aaSamw } 1103*da6c28aaSamw 1104*da6c28aaSamw if ((acep->a_flags & ACE_OWNER)) { 1105*da6c28aaSamw isowner = 1; 1106*da6c28aaSamw } else { 1107*da6c28aaSamw isowner = 0; 1108*da6c28aaSamw } 1109*da6c28aaSamw 1110*da6c28aaSamw error = access_mask_check(acep, ACE_SYNCHRONIZE, isowner); 1111*da6c28aaSamw if (error) 1112*da6c28aaSamw goto out; 1113*da6c28aaSamw 1114*da6c28aaSamw error = access_mask_check(acep, ACE_WRITE_OWNER, isowner); 1115*da6c28aaSamw if (error) 1116*da6c28aaSamw goto out; 1117*da6c28aaSamw 1118*da6c28aaSamw error = access_mask_check(acep, ACE_DELETE, isowner); 1119*da6c28aaSamw if (error) 1120*da6c28aaSamw goto out; 1121*da6c28aaSamw 1122*da6c28aaSamw error = access_mask_check(acep, ACE_WRITE_ATTRIBUTES, isowner); 1123*da6c28aaSamw if (error) 1124*da6c28aaSamw goto out; 1125*da6c28aaSamw 1126*da6c28aaSamw error = access_mask_check(acep, ACE_READ_NAMED_ATTRS, isowner); 1127*da6c28aaSamw if (error) 1128*da6c28aaSamw goto out; 1129*da6c28aaSamw 1130*da6c28aaSamw error = access_mask_check(acep, ACE_WRITE_NAMED_ATTRS, isowner); 1131*da6c28aaSamw if (error) 1132*da6c28aaSamw goto out; 1133*da6c28aaSamw 1134*da6c28aaSamw /* more detailed checking of masks */ 1135*da6c28aaSamw if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 1136*da6c28aaSamw if (! (acep->a_access_mask & ACE_READ_ATTRIBUTES)) { 1137*da6c28aaSamw error = ENOTSUP; 1138*da6c28aaSamw goto out; 1139*da6c28aaSamw } 1140*da6c28aaSamw if ((acep->a_access_mask & ACE_WRITE_DATA) && 1141*da6c28aaSamw (! (acep->a_access_mask & ACE_APPEND_DATA))) { 1142*da6c28aaSamw error = ENOTSUP; 1143*da6c28aaSamw goto out; 1144*da6c28aaSamw } 1145*da6c28aaSamw if ((! (acep->a_access_mask & ACE_WRITE_DATA)) && 1146*da6c28aaSamw (acep->a_access_mask & ACE_APPEND_DATA)) { 1147*da6c28aaSamw error = ENOTSUP; 1148*da6c28aaSamw goto out; 1149*da6c28aaSamw } 1150*da6c28aaSamw } 1151*da6c28aaSamw 1152*da6c28aaSamw /* ACL enforcement */ 1153*da6c28aaSamw if ((acep->a_access_mask & ACE_READ_ACL) && 1154*da6c28aaSamw (acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE)) { 1155*da6c28aaSamw error = ENOTSUP; 1156*da6c28aaSamw goto out; 1157*da6c28aaSamw } 1158*da6c28aaSamw if (acep->a_access_mask & ACE_WRITE_ACL) { 1159*da6c28aaSamw if ((acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) && 1160*da6c28aaSamw (isowner)) { 1161*da6c28aaSamw error = ENOTSUP; 1162*da6c28aaSamw goto out; 1163*da6c28aaSamw } 1164*da6c28aaSamw if ((acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) && 1165*da6c28aaSamw (! isowner)) { 1166*da6c28aaSamw error = ENOTSUP; 1167*da6c28aaSamw goto out; 1168*da6c28aaSamw } 1169*da6c28aaSamw } 1170*da6c28aaSamw 1171*da6c28aaSamw out: 1172*da6c28aaSamw return (error); 1173*da6c28aaSamw } 1174*da6c28aaSamw 1175*da6c28aaSamw static int 1176*da6c28aaSamw ace_allow_to_mode(uint32_t mask, o_mode_t *modep, int isdir) 1177*da6c28aaSamw { 1178*da6c28aaSamw /* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */ 1179*da6c28aaSamw if ((mask & (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) != 1180*da6c28aaSamw (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) { 1181*da6c28aaSamw return (ENOTSUP); 1182*da6c28aaSamw } 1183*da6c28aaSamw 1184*da6c28aaSamw return (ace_mask_to_mode(mask, modep, isdir)); 1185*da6c28aaSamw } 1186*da6c28aaSamw 1187*da6c28aaSamw static int 1188*da6c28aaSamw acevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list, 1189*da6c28aaSamw uid_t owner, gid_t group, int isdir) 1190*da6c28aaSamw { 1191*da6c28aaSamw int error; 1192*da6c28aaSamw uint32_t flips = ACE_POSIX_SUPPORTED_BITS; 1193*da6c28aaSamw 1194*da6c28aaSamw if (isdir) 1195*da6c28aaSamw flips |= ACE_DELETE_CHILD; 1196*da6c28aaSamw if (vals->allowed != (vals->denied ^ flips)) { 1197*da6c28aaSamw error = ENOTSUP; 1198*da6c28aaSamw goto out; 1199*da6c28aaSamw } 1200*da6c28aaSamw if ((list->hasmask) && (list->acl_mask != vals->mask) && 1201*da6c28aaSamw (vals->aent_type & (USER | GROUP | GROUP_OBJ))) { 1202*da6c28aaSamw error = ENOTSUP; 1203*da6c28aaSamw goto out; 1204*da6c28aaSamw } 1205*da6c28aaSamw error = ace_allow_to_mode(vals->allowed, &dest->a_perm, isdir); 1206*da6c28aaSamw if (error != 0) 1207*da6c28aaSamw goto out; 1208*da6c28aaSamw dest->a_type = vals->aent_type; 1209*da6c28aaSamw if (dest->a_type & (USER | GROUP)) { 1210*da6c28aaSamw dest->a_id = vals->key; 1211*da6c28aaSamw } else if (dest->a_type & USER_OBJ) { 1212*da6c28aaSamw dest->a_id = owner; 1213*da6c28aaSamw } else if (dest->a_type & GROUP_OBJ) { 1214*da6c28aaSamw dest->a_id = group; 1215*da6c28aaSamw } else if (dest->a_type & OTHER_OBJ) { 1216*da6c28aaSamw dest->a_id = 0; 1217*da6c28aaSamw } else { 1218*da6c28aaSamw error = EINVAL; 1219*da6c28aaSamw goto out; 1220*da6c28aaSamw } 1221*da6c28aaSamw 1222*da6c28aaSamw out: 1223*da6c28aaSamw return (error); 1224*da6c28aaSamw } 1225*da6c28aaSamw 1226*da6c28aaSamw 1227*da6c28aaSamw static int 1228*da6c28aaSamw ace_list_to_aent(ace_list_t *list, aclent_t **aclentp, int *aclcnt, 1229*da6c28aaSamw uid_t owner, gid_t group, int isdir) 1230*da6c28aaSamw { 1231*da6c28aaSamw int error = 0; 1232*da6c28aaSamw aclent_t *aent, *result = NULL; 1233*da6c28aaSamw acevals_t *vals; 1234*da6c28aaSamw int resultcount; 1235*da6c28aaSamw 1236*da6c28aaSamw if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) != 1237*da6c28aaSamw (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) { 1238*da6c28aaSamw error = ENOTSUP; 1239*da6c28aaSamw goto out; 1240*da6c28aaSamw } 1241*da6c28aaSamw if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) { 1242*da6c28aaSamw error = ENOTSUP; 1243*da6c28aaSamw goto out; 1244*da6c28aaSamw } 1245*da6c28aaSamw 1246*da6c28aaSamw resultcount = 3 + list->numusers + list->numgroups; 1247*da6c28aaSamw /* 1248*da6c28aaSamw * This must be the same condition as below, when we add the CLASS_OBJ 1249*da6c28aaSamw * (aka ACL mask) 1250*da6c28aaSamw */ 1251*da6c28aaSamw if ((list->hasmask) || (! list->dfacl_flag)) 1252*da6c28aaSamw resultcount += 1; 1253*da6c28aaSamw 1254*da6c28aaSamw if (cacl_malloc((void **)&result, 1255*da6c28aaSamw resultcount * sizeof (aclent_t)) != 0) { 1256*da6c28aaSamw error = ENOMEM; 1257*da6c28aaSamw goto out; 1258*da6c28aaSamw } 1259*da6c28aaSamw aent = result; 1260*da6c28aaSamw 1261*da6c28aaSamw /* USER_OBJ */ 1262*da6c28aaSamw if (!(list->user_obj.aent_type & USER_OBJ)) { 1263*da6c28aaSamw error = EINVAL; 1264*da6c28aaSamw goto out; 1265*da6c28aaSamw } 1266*da6c28aaSamw 1267*da6c28aaSamw error = acevals_to_aent(&list->user_obj, aent, list, owner, group, 1268*da6c28aaSamw isdir); 1269*da6c28aaSamw 1270*da6c28aaSamw if (error != 0) 1271*da6c28aaSamw goto out; 1272*da6c28aaSamw ++aent; 1273*da6c28aaSamw /* USER */ 1274*da6c28aaSamw vals = NULL; 1275*da6c28aaSamw for (vals = avl_first(&list->user); vals != NULL; 1276*da6c28aaSamw vals = AVL_NEXT(&list->user, vals)) { 1277*da6c28aaSamw if (!(vals->aent_type & USER)) { 1278*da6c28aaSamw error = EINVAL; 1279*da6c28aaSamw goto out; 1280*da6c28aaSamw } 1281*da6c28aaSamw error = acevals_to_aent(vals, aent, list, owner, group, 1282*da6c28aaSamw isdir); 1283*da6c28aaSamw if (error != 0) 1284*da6c28aaSamw goto out; 1285*da6c28aaSamw ++aent; 1286*da6c28aaSamw } 1287*da6c28aaSamw /* GROUP_OBJ */ 1288*da6c28aaSamw if (!(list->group_obj.aent_type & GROUP_OBJ)) { 1289*da6c28aaSamw error = EINVAL; 1290*da6c28aaSamw goto out; 1291*da6c28aaSamw } 1292*da6c28aaSamw error = acevals_to_aent(&list->group_obj, aent, list, owner, group, 1293*da6c28aaSamw isdir); 1294*da6c28aaSamw if (error != 0) 1295*da6c28aaSamw goto out; 1296*da6c28aaSamw ++aent; 1297*da6c28aaSamw /* GROUP */ 1298*da6c28aaSamw vals = NULL; 1299*da6c28aaSamw for (vals = avl_first(&list->group); vals != NULL; 1300*da6c28aaSamw vals = AVL_NEXT(&list->group, vals)) { 1301*da6c28aaSamw if (!(vals->aent_type & GROUP)) { 1302*da6c28aaSamw error = EINVAL; 1303*da6c28aaSamw goto out; 1304*da6c28aaSamw } 1305*da6c28aaSamw error = acevals_to_aent(vals, aent, list, owner, group, 1306*da6c28aaSamw isdir); 1307*da6c28aaSamw if (error != 0) 1308*da6c28aaSamw goto out; 1309*da6c28aaSamw ++aent; 1310*da6c28aaSamw } 1311*da6c28aaSamw /* 1312*da6c28aaSamw * CLASS_OBJ (aka ACL_MASK) 1313*da6c28aaSamw * 1314*da6c28aaSamw * An ACL_MASK is not fabricated if the ACL is a default ACL. 1315*da6c28aaSamw * This is to follow UFS's behavior. 1316*da6c28aaSamw */ 1317*da6c28aaSamw if ((list->hasmask) || (! list->dfacl_flag)) { 1318*da6c28aaSamw if (list->hasmask) { 1319*da6c28aaSamw uint32_t flips = ACE_POSIX_SUPPORTED_BITS; 1320*da6c28aaSamw if (isdir) 1321*da6c28aaSamw flips |= ACE_DELETE_CHILD; 1322*da6c28aaSamw error = ace_mask_to_mode(list->acl_mask ^ flips, 1323*da6c28aaSamw &aent->a_perm, isdir); 1324*da6c28aaSamw if (error != 0) 1325*da6c28aaSamw goto out; 1326*da6c28aaSamw } else { 1327*da6c28aaSamw /* fabricate the ACL_MASK from the group permissions */ 1328*da6c28aaSamw error = ace_mask_to_mode(list->group_obj.allowed, 1329*da6c28aaSamw &aent->a_perm, isdir); 1330*da6c28aaSamw if (error != 0) 1331*da6c28aaSamw goto out; 1332*da6c28aaSamw } 1333*da6c28aaSamw aent->a_id = 0; 1334*da6c28aaSamw aent->a_type = CLASS_OBJ | list->dfacl_flag; 1335*da6c28aaSamw ++aent; 1336*da6c28aaSamw } 1337*da6c28aaSamw /* OTHER_OBJ */ 1338*da6c28aaSamw if (!(list->other_obj.aent_type & OTHER_OBJ)) { 1339*da6c28aaSamw error = EINVAL; 1340*da6c28aaSamw goto out; 1341*da6c28aaSamw } 1342*da6c28aaSamw error = acevals_to_aent(&list->other_obj, aent, list, owner, group, 1343*da6c28aaSamw isdir); 1344*da6c28aaSamw if (error != 0) 1345*da6c28aaSamw goto out; 1346*da6c28aaSamw ++aent; 1347*da6c28aaSamw 1348*da6c28aaSamw *aclentp = result; 1349*da6c28aaSamw *aclcnt = resultcount; 1350*da6c28aaSamw 1351*da6c28aaSamw out: 1352*da6c28aaSamw if (error != 0) { 1353*da6c28aaSamw if (result != NULL) 1354*da6c28aaSamw cacl_free(result, resultcount * sizeof (aclent_t)); 1355*da6c28aaSamw } 1356*da6c28aaSamw 1357*da6c28aaSamw return (error); 1358*da6c28aaSamw } 1359*da6c28aaSamw 1360*da6c28aaSamw 1361*da6c28aaSamw /* 1362*da6c28aaSamw * free all data associated with an ace_list 1363*da6c28aaSamw */ 1364*da6c28aaSamw static void 1365*da6c28aaSamw ace_list_free(ace_list_t *al) 1366*da6c28aaSamw { 1367*da6c28aaSamw acevals_t *node; 1368*da6c28aaSamw void *cookie; 1369*da6c28aaSamw 1370*da6c28aaSamw if (al == NULL) 1371*da6c28aaSamw return; 1372*da6c28aaSamw 1373*da6c28aaSamw cookie = NULL; 1374*da6c28aaSamw while ((node = avl_destroy_nodes(&al->user, &cookie)) != NULL) 1375*da6c28aaSamw cacl_free(node, sizeof (acevals_t)); 1376*da6c28aaSamw cookie = NULL; 1377*da6c28aaSamw while ((node = avl_destroy_nodes(&al->group, &cookie)) != NULL) 1378*da6c28aaSamw cacl_free(node, sizeof (acevals_t)); 1379*da6c28aaSamw 1380*da6c28aaSamw avl_destroy(&al->user); 1381*da6c28aaSamw avl_destroy(&al->group); 1382*da6c28aaSamw 1383*da6c28aaSamw /* free the container itself */ 1384*da6c28aaSamw cacl_free(al, sizeof (ace_list_t)); 1385*da6c28aaSamw } 1386*da6c28aaSamw 1387*da6c28aaSamw static int 1388*da6c28aaSamw acevals_compare(const void *va, const void *vb) 1389*da6c28aaSamw { 1390*da6c28aaSamw const acevals_t *a = va, *b = vb; 1391*da6c28aaSamw 1392*da6c28aaSamw if (a->key == b->key) 1393*da6c28aaSamw return (0); 1394*da6c28aaSamw 1395*da6c28aaSamw if (a->key > b->key) 1396*da6c28aaSamw return (1); 1397*da6c28aaSamw 1398*da6c28aaSamw else 1399*da6c28aaSamw return (-1); 1400*da6c28aaSamw } 1401*da6c28aaSamw 1402*da6c28aaSamw /* 1403*da6c28aaSamw * Convert a list of ace_t entries to equivalent regular and default 1404*da6c28aaSamw * aclent_t lists. Return error (ENOTSUP) when conversion is not possible. 1405*da6c28aaSamw */ 1406*da6c28aaSamw static int 1407*da6c28aaSamw ln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group, 1408*da6c28aaSamw aclent_t **aclentp, int *aclcnt, aclent_t **dfaclentp, int *dfaclcnt, 1409*da6c28aaSamw int isdir) 1410*da6c28aaSamw { 1411*da6c28aaSamw int error = 0; 1412*da6c28aaSamw ace_t *acep; 1413*da6c28aaSamw uint32_t bits; 1414*da6c28aaSamw int i; 1415*da6c28aaSamw ace_list_t *normacl = NULL, *dfacl = NULL, *acl; 1416*da6c28aaSamw acevals_t *vals; 1417*da6c28aaSamw 1418*da6c28aaSamw *aclentp = NULL; 1419*da6c28aaSamw *aclcnt = 0; 1420*da6c28aaSamw *dfaclentp = NULL; 1421*da6c28aaSamw *dfaclcnt = 0; 1422*da6c28aaSamw 1423*da6c28aaSamw /* we need at least user_obj, group_obj, and other_obj */ 1424*da6c28aaSamw if (n < 6) { 1425*da6c28aaSamw error = ENOTSUP; 1426*da6c28aaSamw goto out; 1427*da6c28aaSamw } 1428*da6c28aaSamw if (ace == NULL) { 1429*da6c28aaSamw error = EINVAL; 1430*da6c28aaSamw goto out; 1431*da6c28aaSamw } 1432*da6c28aaSamw 1433*da6c28aaSamw error = cacl_malloc((void **)&normacl, sizeof (ace_list_t)); 1434*da6c28aaSamw if (error != 0) 1435*da6c28aaSamw goto out; 1436*da6c28aaSamw 1437*da6c28aaSamw avl_create(&normacl->user, acevals_compare, sizeof (acevals_t), 1438*da6c28aaSamw offsetof(acevals_t, avl)); 1439*da6c28aaSamw avl_create(&normacl->group, acevals_compare, sizeof (acevals_t), 1440*da6c28aaSamw offsetof(acevals_t, avl)); 1441*da6c28aaSamw 1442*da6c28aaSamw ace_list_init(normacl, 0); 1443*da6c28aaSamw 1444*da6c28aaSamw error = cacl_malloc((void **)&dfacl, sizeof (ace_list_t)); 1445*da6c28aaSamw if (error != 0) 1446*da6c28aaSamw goto out; 1447*da6c28aaSamw 1448*da6c28aaSamw avl_create(&dfacl->user, acevals_compare, sizeof (acevals_t), 1449*da6c28aaSamw offsetof(acevals_t, avl)); 1450*da6c28aaSamw avl_create(&dfacl->group, acevals_compare, sizeof (acevals_t), 1451*da6c28aaSamw offsetof(acevals_t, avl)); 1452*da6c28aaSamw ace_list_init(dfacl, ACL_DEFAULT); 1453*da6c28aaSamw 1454*da6c28aaSamw /* process every ace_t... */ 1455*da6c28aaSamw for (i = 0; i < n; i++) { 1456*da6c28aaSamw acep = &ace[i]; 1457*da6c28aaSamw 1458*da6c28aaSamw /* rule out certain cases quickly */ 1459*da6c28aaSamw error = ace_to_aent_legal(acep); 1460*da6c28aaSamw if (error != 0) 1461*da6c28aaSamw goto out; 1462*da6c28aaSamw 1463*da6c28aaSamw /* 1464*da6c28aaSamw * Turn off these bits in order to not have to worry about 1465*da6c28aaSamw * them when doing the checks for compliments. 1466*da6c28aaSamw */ 1467*da6c28aaSamw acep->a_access_mask &= ~(ACE_WRITE_OWNER | ACE_DELETE | 1468*da6c28aaSamw ACE_SYNCHRONIZE | ACE_WRITE_ATTRIBUTES | 1469*da6c28aaSamw ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS); 1470*da6c28aaSamw 1471*da6c28aaSamw /* see if this should be a regular or default acl */ 1472*da6c28aaSamw bits = acep->a_flags & 1473*da6c28aaSamw (ACE_INHERIT_ONLY_ACE | 1474*da6c28aaSamw ACE_FILE_INHERIT_ACE | 1475*da6c28aaSamw ACE_DIRECTORY_INHERIT_ACE); 1476*da6c28aaSamw if (bits != 0) { 1477*da6c28aaSamw /* all or nothing on these inherit bits */ 1478*da6c28aaSamw if (bits != (ACE_INHERIT_ONLY_ACE | 1479*da6c28aaSamw ACE_FILE_INHERIT_ACE | 1480*da6c28aaSamw ACE_DIRECTORY_INHERIT_ACE)) { 1481*da6c28aaSamw error = ENOTSUP; 1482*da6c28aaSamw goto out; 1483*da6c28aaSamw } 1484*da6c28aaSamw acl = dfacl; 1485*da6c28aaSamw } else { 1486*da6c28aaSamw acl = normacl; 1487*da6c28aaSamw } 1488*da6c28aaSamw 1489*da6c28aaSamw if ((acep->a_flags & ACE_OWNER)) { 1490*da6c28aaSamw if (acl->state > ace_user_obj) { 1491*da6c28aaSamw error = ENOTSUP; 1492*da6c28aaSamw goto out; 1493*da6c28aaSamw } 1494*da6c28aaSamw acl->state = ace_user_obj; 1495*da6c28aaSamw acl->seen |= USER_OBJ; 1496*da6c28aaSamw vals = &acl->user_obj; 1497*da6c28aaSamw vals->aent_type = USER_OBJ | acl->dfacl_flag; 1498*da6c28aaSamw } else if ((acep->a_flags & ACE_EVERYONE)) { 1499*da6c28aaSamw acl->state = ace_other_obj; 1500*da6c28aaSamw acl->seen |= OTHER_OBJ; 1501*da6c28aaSamw vals = &acl->other_obj; 1502*da6c28aaSamw vals->aent_type = OTHER_OBJ | acl->dfacl_flag; 1503*da6c28aaSamw } else if (acep->a_flags & ACE_IDENTIFIER_GROUP) { 1504*da6c28aaSamw if (acl->state > ace_group) { 1505*da6c28aaSamw error = ENOTSUP; 1506*da6c28aaSamw goto out; 1507*da6c28aaSamw } 1508*da6c28aaSamw if ((acep->a_flags & ACE_GROUP)) { 1509*da6c28aaSamw acl->seen |= GROUP_OBJ; 1510*da6c28aaSamw vals = &acl->group_obj; 1511*da6c28aaSamw vals->aent_type = GROUP_OBJ | acl->dfacl_flag; 1512*da6c28aaSamw } else { 1513*da6c28aaSamw acl->seen |= GROUP; 1514*da6c28aaSamw vals = acevals_find(acep, &acl->group, 1515*da6c28aaSamw &acl->numgroups); 1516*da6c28aaSamw if (vals == NULL) { 1517*da6c28aaSamw error = ENOMEM; 1518*da6c28aaSamw goto out; 1519*da6c28aaSamw } 1520*da6c28aaSamw vals->aent_type = GROUP | acl->dfacl_flag; 1521*da6c28aaSamw } 1522*da6c28aaSamw acl->state = ace_group; 1523*da6c28aaSamw } else { 1524*da6c28aaSamw if (acl->state > ace_user) { 1525*da6c28aaSamw error = ENOTSUP; 1526*da6c28aaSamw goto out; 1527*da6c28aaSamw } 1528*da6c28aaSamw acl->state = ace_user; 1529*da6c28aaSamw acl->seen |= USER; 1530*da6c28aaSamw vals = acevals_find(acep, &acl->user, 1531*da6c28aaSamw &acl->numusers); 1532*da6c28aaSamw if (vals == NULL) { 1533*da6c28aaSamw error = ENOMEM; 1534*da6c28aaSamw goto out; 1535*da6c28aaSamw } 1536*da6c28aaSamw vals->aent_type = USER | acl->dfacl_flag; 1537*da6c28aaSamw } 1538*da6c28aaSamw 1539*da6c28aaSamw if (!(acl->state > ace_unused)) { 1540*da6c28aaSamw error = EINVAL; 1541*da6c28aaSamw goto out; 1542*da6c28aaSamw } 1543*da6c28aaSamw 1544*da6c28aaSamw if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 1545*da6c28aaSamw /* no more than one allowed per aclent_t */ 1546*da6c28aaSamw if (vals->allowed != ACE_MASK_UNDEFINED) { 1547*da6c28aaSamw error = ENOTSUP; 1548*da6c28aaSamw goto out; 1549*da6c28aaSamw } 1550*da6c28aaSamw vals->allowed = acep->a_access_mask; 1551*da6c28aaSamw } else { 1552*da6c28aaSamw /* 1553*da6c28aaSamw * it's a DENY; if there was a previous DENY, it 1554*da6c28aaSamw * must have been an ACL_MASK. 1555*da6c28aaSamw */ 1556*da6c28aaSamw if (vals->denied != ACE_MASK_UNDEFINED) { 1557*da6c28aaSamw /* ACL_MASK is for USER and GROUP only */ 1558*da6c28aaSamw if ((acl->state != ace_user) && 1559*da6c28aaSamw (acl->state != ace_group)) { 1560*da6c28aaSamw error = ENOTSUP; 1561*da6c28aaSamw goto out; 1562*da6c28aaSamw } 1563*da6c28aaSamw 1564*da6c28aaSamw if (! acl->hasmask) { 1565*da6c28aaSamw acl->hasmask = 1; 1566*da6c28aaSamw acl->acl_mask = vals->denied; 1567*da6c28aaSamw /* check for mismatched ACL_MASK emulations */ 1568*da6c28aaSamw } else if (acl->acl_mask != vals->denied) { 1569*da6c28aaSamw error = ENOTSUP; 1570*da6c28aaSamw goto out; 1571*da6c28aaSamw } 1572*da6c28aaSamw vals->mask = vals->denied; 1573*da6c28aaSamw } 1574*da6c28aaSamw vals->denied = acep->a_access_mask; 1575*da6c28aaSamw } 1576*da6c28aaSamw } 1577*da6c28aaSamw 1578*da6c28aaSamw /* done collating; produce the aclent_t lists */ 1579*da6c28aaSamw if (normacl->state != ace_unused) { 1580*da6c28aaSamw error = ace_list_to_aent(normacl, aclentp, aclcnt, 1581*da6c28aaSamw owner, group, isdir); 1582*da6c28aaSamw if (error != 0) { 1583*da6c28aaSamw goto out; 1584*da6c28aaSamw } 1585*da6c28aaSamw } 1586*da6c28aaSamw if (dfacl->state != ace_unused) { 1587*da6c28aaSamw error = ace_list_to_aent(dfacl, dfaclentp, dfaclcnt, 1588*da6c28aaSamw owner, group, isdir); 1589*da6c28aaSamw if (error != 0) { 1590*da6c28aaSamw goto out; 1591*da6c28aaSamw } 1592*da6c28aaSamw } 1593*da6c28aaSamw 1594*da6c28aaSamw out: 1595*da6c28aaSamw if (normacl != NULL) 1596*da6c28aaSamw ace_list_free(normacl); 1597*da6c28aaSamw if (dfacl != NULL) 1598*da6c28aaSamw ace_list_free(dfacl); 1599*da6c28aaSamw 1600*da6c28aaSamw return (error); 1601*da6c28aaSamw } 1602*da6c28aaSamw 1603*da6c28aaSamw static int 1604*da6c28aaSamw convert_ace_to_aent(ace_t *acebufp, int acecnt, int isdir, 1605*da6c28aaSamw uid_t owner, gid_t group, aclent_t **retaclentp, int *retaclcnt) 1606*da6c28aaSamw { 1607*da6c28aaSamw int error = 0; 1608*da6c28aaSamw aclent_t *aclentp, *dfaclentp; 1609*da6c28aaSamw int aclcnt, dfaclcnt; 1610*da6c28aaSamw int aclsz, dfaclsz; 1611*da6c28aaSamw 1612*da6c28aaSamw error = ln_ace_to_aent(acebufp, acecnt, owner, group, 1613*da6c28aaSamw &aclentp, &aclcnt, &dfaclentp, &dfaclcnt, isdir); 1614*da6c28aaSamw 1615*da6c28aaSamw if (error) 1616*da6c28aaSamw return (error); 1617*da6c28aaSamw 1618*da6c28aaSamw 1619*da6c28aaSamw if (dfaclcnt != 0) { 1620*da6c28aaSamw /* 1621*da6c28aaSamw * Slap aclentp and dfaclentp into a single array. 1622*da6c28aaSamw */ 1623*da6c28aaSamw aclsz = sizeof (aclent_t) * aclcnt; 1624*da6c28aaSamw dfaclsz = sizeof (aclent_t) * dfaclcnt; 1625*da6c28aaSamw aclentp = cacl_realloc(aclentp, aclsz, aclsz + dfaclsz); 1626*da6c28aaSamw if (aclentp != NULL) { 1627*da6c28aaSamw (void) memcpy(aclentp + aclcnt, dfaclentp, dfaclsz); 1628*da6c28aaSamw } else { 1629*da6c28aaSamw error = ENOMEM; 1630*da6c28aaSamw } 1631*da6c28aaSamw } 1632*da6c28aaSamw 1633*da6c28aaSamw if (aclentp) { 1634*da6c28aaSamw *retaclentp = aclentp; 1635*da6c28aaSamw *retaclcnt = aclcnt + dfaclcnt; 1636*da6c28aaSamw } 1637*da6c28aaSamw 1638*da6c28aaSamw if (dfaclentp) 1639*da6c28aaSamw cacl_free(dfaclentp, dfaclsz); 1640*da6c28aaSamw 1641*da6c28aaSamw return (error); 1642*da6c28aaSamw } 1643*da6c28aaSamw 1644*da6c28aaSamw 1645*da6c28aaSamw int 1646*da6c28aaSamw acl_translate(acl_t *aclp, int target_flavor, int isdir, uid_t owner, 1647*da6c28aaSamw gid_t group) 1648*da6c28aaSamw { 1649*da6c28aaSamw int aclcnt; 1650*da6c28aaSamw void *acldata; 1651*da6c28aaSamw int error; 1652*da6c28aaSamw 1653*da6c28aaSamw /* 1654*da6c28aaSamw * See if we need to translate 1655*da6c28aaSamw */ 1656*da6c28aaSamw if ((target_flavor == _ACL_ACE_ENABLED && aclp->acl_type == ACE_T) || 1657*da6c28aaSamw (target_flavor == _ACL_ACLENT_ENABLED && 1658*da6c28aaSamw aclp->acl_type == ACLENT_T)) 1659*da6c28aaSamw return (0); 1660*da6c28aaSamw 1661*da6c28aaSamw if (target_flavor == -1) { 1662*da6c28aaSamw error = EINVAL; 1663*da6c28aaSamw goto out; 1664*da6c28aaSamw } 1665*da6c28aaSamw 1666*da6c28aaSamw if (target_flavor == _ACL_ACE_ENABLED && 1667*da6c28aaSamw aclp->acl_type == ACLENT_T) { 1668*da6c28aaSamw error = convert_aent_to_ace(aclp->acl_aclp, 1669*da6c28aaSamw aclp->acl_cnt, isdir, (ace_t **)&acldata, &aclcnt); 1670*da6c28aaSamw if (error) 1671*da6c28aaSamw goto out; 1672*da6c28aaSamw 1673*da6c28aaSamw } else if (target_flavor == _ACL_ACLENT_ENABLED && 1674*da6c28aaSamw aclp->acl_type == ACE_T) { 1675*da6c28aaSamw error = convert_ace_to_aent(aclp->acl_aclp, aclp->acl_cnt, 1676*da6c28aaSamw isdir, owner, group, (aclent_t **)&acldata, &aclcnt); 1677*da6c28aaSamw if (error) 1678*da6c28aaSamw goto out; 1679*da6c28aaSamw } else { 1680*da6c28aaSamw error = ENOTSUP; 1681*da6c28aaSamw goto out; 1682*da6c28aaSamw } 1683*da6c28aaSamw 1684*da6c28aaSamw /* 1685*da6c28aaSamw * replace old acl with newly translated acl 1686*da6c28aaSamw */ 1687*da6c28aaSamw cacl_free(aclp->acl_aclp, aclp->acl_cnt * aclp->acl_entry_size); 1688*da6c28aaSamw aclp->acl_aclp = acldata; 1689*da6c28aaSamw aclp->acl_cnt = aclcnt; 1690*da6c28aaSamw if (target_flavor == _ACL_ACE_ENABLED) { 1691*da6c28aaSamw aclp->acl_type = ACE_T; 1692*da6c28aaSamw aclp->acl_entry_size = sizeof (ace_t); 1693*da6c28aaSamw } else { 1694*da6c28aaSamw aclp->acl_type = ACLENT_T; 1695*da6c28aaSamw aclp->acl_entry_size = sizeof (aclent_t); 1696*da6c28aaSamw } 1697*da6c28aaSamw return (0); 1698*da6c28aaSamw 1699*da6c28aaSamw out: 1700*da6c28aaSamw 1701*da6c28aaSamw #if !defined(_KERNEL) 1702*da6c28aaSamw errno = error; 1703*da6c28aaSamw return (-1); 1704*da6c28aaSamw #else 1705*da6c28aaSamw return (error); 1706*da6c28aaSamw #endif 1707*da6c28aaSamw } 1708