1*fa9e4066Sahrens /* 2*fa9e4066Sahrens * CDDL HEADER START 3*fa9e4066Sahrens * 4*fa9e4066Sahrens * The contents of this file are subject to the terms of the 5*fa9e4066Sahrens * Common Development and Distribution License, Version 1.0 only 6*fa9e4066Sahrens * (the "License"). You may not use this file except in compliance 7*fa9e4066Sahrens * with the License. 8*fa9e4066Sahrens * 9*fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 11*fa9e4066Sahrens * See the License for the specific language governing permissions 12*fa9e4066Sahrens * and limitations under the License. 13*fa9e4066Sahrens * 14*fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15*fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 17*fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18*fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19*fa9e4066Sahrens * 20*fa9e4066Sahrens * CDDL HEADER END 21*fa9e4066Sahrens */ 22*fa9e4066Sahrens /* 23*fa9e4066Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*fa9e4066Sahrens * Use is subject to license terms. 25*fa9e4066Sahrens */ 26*fa9e4066Sahrens 27*fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28*fa9e4066Sahrens 29*fa9e4066Sahrens #include <stdlib.h> 30*fa9e4066Sahrens #include <string.h> 31*fa9e4066Sahrens #include <unistd.h> 32*fa9e4066Sahrens #include <limits.h> 33*fa9e4066Sahrens #include <grp.h> 34*fa9e4066Sahrens #include <pwd.h> 35*fa9e4066Sahrens #include <sys/types.h> 36*fa9e4066Sahrens #include <sys/acl.h> 37*fa9e4066Sahrens #include <errno.h> 38*fa9e4066Sahrens #include <sys/stat.h> 39*fa9e4066Sahrens #include <locale.h> 40*fa9e4066Sahrens #include <aclutils.h> 41*fa9e4066Sahrens #include <acl_common.h> 42*fa9e4066Sahrens 43*fa9e4066Sahrens #define ACL_PATH 0 44*fa9e4066Sahrens #define ACL_FD 1 45*fa9e4066Sahrens 46*fa9e4066Sahrens #define ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \ 47*fa9e4066Sahrens ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \ 48*fa9e4066Sahrens ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL) 49*fa9e4066Sahrens 50*fa9e4066Sahrens 51*fa9e4066Sahrens #define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002 52*fa9e4066Sahrens #define ACL_SYNCHRONIZE_SET_DENY 0x0000001 53*fa9e4066Sahrens 54*fa9e4066Sahrens #define ACL_WRITE_OWNER_SET_ALLOW 0x0000020 55*fa9e4066Sahrens #define ACL_WRITE_OWNER_SET_DENY 0x0000010 56*fa9e4066Sahrens 57*fa9e4066Sahrens #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000 58*fa9e4066Sahrens #define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000 59*fa9e4066Sahrens 60*fa9e4066Sahrens #define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000 61*fa9e4066Sahrens 62*fa9e4066Sahrens #define ACL_DELETE_SET_ALLOW 0x0000200 63*fa9e4066Sahrens #define ACL_DELETE_SET_DENY 0x0000100 64*fa9e4066Sahrens 65*fa9e4066Sahrens #define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000 66*fa9e4066Sahrens 67*fa9e4066Sahrens #define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000 68*fa9e4066Sahrens #define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000 69*fa9e4066Sahrens 70*fa9e4066Sahrens #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000 71*fa9e4066Sahrens #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000 72*fa9e4066Sahrens 73*fa9e4066Sahrens #define ACL_WRITE_OWNER_ERR_DENY 0x0000040 74*fa9e4066Sahrens #define ACL_READ_NAMED_READER_SET_DENY 0x1000000 75*fa9e4066Sahrens #define ACL_WRITE_NAMED_WRITER_SET_ALLO W0x0200000 76*fa9e4066Sahrens typedef union { 77*fa9e4066Sahrens const char *file; 78*fa9e4066Sahrens int fd; 79*fa9e4066Sahrens } acl_inp; 80*fa9e4066Sahrens 81*fa9e4066Sahrens acl_t * 82*fa9e4066Sahrens acl_alloc(enum acl_type type) 83*fa9e4066Sahrens { 84*fa9e4066Sahrens acl_t *aclp; 85*fa9e4066Sahrens 86*fa9e4066Sahrens aclp = malloc(sizeof (acl_t)); 87*fa9e4066Sahrens 88*fa9e4066Sahrens if (aclp == NULL) 89*fa9e4066Sahrens return (NULL); 90*fa9e4066Sahrens 91*fa9e4066Sahrens aclp->acl_aclp = NULL; 92*fa9e4066Sahrens aclp->acl_cnt = 0; 93*fa9e4066Sahrens 94*fa9e4066Sahrens switch (type) { 95*fa9e4066Sahrens case ACE_T: 96*fa9e4066Sahrens aclp->acl_type = ACE_T; 97*fa9e4066Sahrens aclp->acl_entry_size = sizeof (ace_t); 98*fa9e4066Sahrens break; 99*fa9e4066Sahrens case ACLENT_T: 100*fa9e4066Sahrens aclp->acl_type = ACLENT_T; 101*fa9e4066Sahrens aclp->acl_entry_size = sizeof (aclent_t); 102*fa9e4066Sahrens break; 103*fa9e4066Sahrens default: 104*fa9e4066Sahrens acl_free(aclp); 105*fa9e4066Sahrens aclp = NULL; 106*fa9e4066Sahrens } 107*fa9e4066Sahrens return (aclp); 108*fa9e4066Sahrens } 109*fa9e4066Sahrens 110*fa9e4066Sahrens /* 111*fa9e4066Sahrens * Free acl_t structure 112*fa9e4066Sahrens */ 113*fa9e4066Sahrens void 114*fa9e4066Sahrens acl_free(acl_t *aclp) 115*fa9e4066Sahrens { 116*fa9e4066Sahrens if (aclp == NULL) 117*fa9e4066Sahrens return; 118*fa9e4066Sahrens 119*fa9e4066Sahrens if (aclp->acl_aclp) 120*fa9e4066Sahrens free(aclp->acl_aclp); 121*fa9e4066Sahrens free(aclp); 122*fa9e4066Sahrens } 123*fa9e4066Sahrens 124*fa9e4066Sahrens /* 125*fa9e4066Sahrens * Determine whether a file has a trivial ACL 126*fa9e4066Sahrens * returns: 0 = trivial 127*fa9e4066Sahrens * 1 = nontrivial 128*fa9e4066Sahrens * <0 some other system failure, such as ENOENT or EPERM 129*fa9e4066Sahrens */ 130*fa9e4066Sahrens int 131*fa9e4066Sahrens acl_trivial(const char *filename) 132*fa9e4066Sahrens { 133*fa9e4066Sahrens int acl_flavor; 134*fa9e4066Sahrens int aclcnt; 135*fa9e4066Sahrens int cntcmd; 136*fa9e4066Sahrens int val = 0; 137*fa9e4066Sahrens ace_t *acep; 138*fa9e4066Sahrens 139*fa9e4066Sahrens acl_flavor = pathconf(filename, _PC_ACL_ENABLED); 140*fa9e4066Sahrens if (acl_flavor == -1) 141*fa9e4066Sahrens return (-1); 142*fa9e4066Sahrens 143*fa9e4066Sahrens if (acl_flavor == _ACL_ACE_ENABLED) 144*fa9e4066Sahrens cntcmd = ACE_GETACLCNT; 145*fa9e4066Sahrens else 146*fa9e4066Sahrens cntcmd = GETACLCNT; 147*fa9e4066Sahrens 148*fa9e4066Sahrens aclcnt = acl(filename, cntcmd, 0, NULL); 149*fa9e4066Sahrens if (aclcnt > 0) { 150*fa9e4066Sahrens if (acl_flavor == _ACL_ACE_ENABLED) { 151*fa9e4066Sahrens if (aclcnt != 6) 152*fa9e4066Sahrens val = 1; 153*fa9e4066Sahrens else { 154*fa9e4066Sahrens acep = malloc(sizeof (ace_t) * aclcnt); 155*fa9e4066Sahrens if (acep == NULL) 156*fa9e4066Sahrens return (-1); 157*fa9e4066Sahrens if (acl(filename, ACE_GETACL, 158*fa9e4066Sahrens aclcnt, acep) < 0) { 159*fa9e4066Sahrens free(acep); 160*fa9e4066Sahrens return (-1); 161*fa9e4066Sahrens } 162*fa9e4066Sahrens 163*fa9e4066Sahrens val = ace_trivial(acep, aclcnt); 164*fa9e4066Sahrens free(acep); 165*fa9e4066Sahrens } 166*fa9e4066Sahrens } else if (aclcnt > MIN_ACL_ENTRIES) 167*fa9e4066Sahrens val = 1; 168*fa9e4066Sahrens } 169*fa9e4066Sahrens return (val); 170*fa9e4066Sahrens } 171*fa9e4066Sahrens 172*fa9e4066Sahrens static uint32_t 173*fa9e4066Sahrens access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow) 174*fa9e4066Sahrens { 175*fa9e4066Sahrens uint32_t access_mask = 0; 176*fa9e4066Sahrens int acl_produce; 177*fa9e4066Sahrens int synchronize_set = 0, write_owner_set = 0; 178*fa9e4066Sahrens int delete_set = 0, write_attrs_set = 0; 179*fa9e4066Sahrens int read_named_set = 0, write_named_set = 0; 180*fa9e4066Sahrens 181*fa9e4066Sahrens acl_produce = (ACL_SYNCHRONIZE_SET_ALLOW | 182*fa9e4066Sahrens ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 183*fa9e4066Sahrens ACL_WRITE_ATTRS_WRITER_SET_DENY); 184*fa9e4066Sahrens 185*fa9e4066Sahrens if (isallow) { 186*fa9e4066Sahrens synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW; 187*fa9e4066Sahrens write_owner_set = ACL_WRITE_OWNER_SET_ALLOW; 188*fa9e4066Sahrens delete_set = ACL_DELETE_SET_ALLOW; 189*fa9e4066Sahrens if (hasreadperm) 190*fa9e4066Sahrens read_named_set = ACL_READ_NAMED_READER_SET_ALLOW; 191*fa9e4066Sahrens if (haswriteperm) 192*fa9e4066Sahrens write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 193*fa9e4066Sahrens if (isowner) 194*fa9e4066Sahrens write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 195*fa9e4066Sahrens else if (haswriteperm) 196*fa9e4066Sahrens write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 197*fa9e4066Sahrens } else { 198*fa9e4066Sahrens 199*fa9e4066Sahrens synchronize_set = ACL_SYNCHRONIZE_SET_DENY; 200*fa9e4066Sahrens write_owner_set = ACL_WRITE_OWNER_SET_DENY; 201*fa9e4066Sahrens delete_set = ACL_DELETE_SET_DENY; 202*fa9e4066Sahrens if (hasreadperm) 203*fa9e4066Sahrens read_named_set = ACL_READ_NAMED_READER_SET_DENY; 204*fa9e4066Sahrens if (haswriteperm) 205*fa9e4066Sahrens write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY; 206*fa9e4066Sahrens if (isowner) 207*fa9e4066Sahrens write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY; 208*fa9e4066Sahrens else if (haswriteperm) 209*fa9e4066Sahrens write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY; 210*fa9e4066Sahrens else 211*fa9e4066Sahrens /* 212*fa9e4066Sahrens * If the entity is not the owner and does not 213*fa9e4066Sahrens * have write permissions ACE_WRITE_ATTRIBUTES will 214*fa9e4066Sahrens * always go in the DENY ACE. 215*fa9e4066Sahrens */ 216*fa9e4066Sahrens access_mask |= ACE_WRITE_ATTRIBUTES; 217*fa9e4066Sahrens } 218*fa9e4066Sahrens 219*fa9e4066Sahrens if (acl_produce & synchronize_set) 220*fa9e4066Sahrens access_mask |= ACE_SYNCHRONIZE; 221*fa9e4066Sahrens if (acl_produce & write_owner_set) 222*fa9e4066Sahrens access_mask |= ACE_WRITE_OWNER; 223*fa9e4066Sahrens if (acl_produce & delete_set) 224*fa9e4066Sahrens access_mask |= ACE_DELETE; 225*fa9e4066Sahrens if (acl_produce & write_attrs_set) 226*fa9e4066Sahrens access_mask |= ACE_WRITE_ATTRIBUTES; 227*fa9e4066Sahrens if (acl_produce & read_named_set) 228*fa9e4066Sahrens access_mask |= ACE_READ_NAMED_ATTRS; 229*fa9e4066Sahrens if (acl_produce & write_named_set) 230*fa9e4066Sahrens access_mask |= ACE_WRITE_NAMED_ATTRS; 231*fa9e4066Sahrens 232*fa9e4066Sahrens return (access_mask); 233*fa9e4066Sahrens } 234*fa9e4066Sahrens 235*fa9e4066Sahrens /* 236*fa9e4066Sahrens * Given an mode_t, convert it into an access_mask as used 237*fa9e4066Sahrens * by nfsace, assuming aclent_t -> nfsace semantics. 238*fa9e4066Sahrens */ 239*fa9e4066Sahrens static uint32_t 240*fa9e4066Sahrens mode_to_ace_access(mode_t mode, int isdir, int isowner, int isallow) 241*fa9e4066Sahrens { 242*fa9e4066Sahrens uint32_t access = 0; 243*fa9e4066Sahrens int haswriteperm = 0; 244*fa9e4066Sahrens int hasreadperm = 0; 245*fa9e4066Sahrens 246*fa9e4066Sahrens if (isallow) { 247*fa9e4066Sahrens haswriteperm = (mode & 02); 248*fa9e4066Sahrens hasreadperm = (mode & 04); 249*fa9e4066Sahrens } else { 250*fa9e4066Sahrens haswriteperm = !(mode & 02); 251*fa9e4066Sahrens hasreadperm = !(mode & 04); 252*fa9e4066Sahrens } 253*fa9e4066Sahrens 254*fa9e4066Sahrens /* 255*fa9e4066Sahrens * The following call takes care of correctly setting the following 256*fa9e4066Sahrens * mask bits in the access_mask: 257*fa9e4066Sahrens * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE, 258*fa9e4066Sahrens * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS 259*fa9e4066Sahrens */ 260*fa9e4066Sahrens access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow); 261*fa9e4066Sahrens 262*fa9e4066Sahrens if (isallow) { 263*fa9e4066Sahrens access |= ACE_READ_ACL | ACE_READ_ATTRIBUTES; 264*fa9e4066Sahrens if (isowner) 265*fa9e4066Sahrens access |= ACE_WRITE_ACL; 266*fa9e4066Sahrens } else { 267*fa9e4066Sahrens if (! isowner) 268*fa9e4066Sahrens access |= ACE_WRITE_ACL; 269*fa9e4066Sahrens } 270*fa9e4066Sahrens 271*fa9e4066Sahrens /* read */ 272*fa9e4066Sahrens if (mode & 04) { 273*fa9e4066Sahrens access |= ACE_READ_DATA; 274*fa9e4066Sahrens } 275*fa9e4066Sahrens /* write */ 276*fa9e4066Sahrens if (mode & 02) { 277*fa9e4066Sahrens access |= ACE_WRITE_DATA | 278*fa9e4066Sahrens ACE_APPEND_DATA; 279*fa9e4066Sahrens if (isdir) 280*fa9e4066Sahrens access |= ACE_DELETE_CHILD; 281*fa9e4066Sahrens } 282*fa9e4066Sahrens /* exec */ 283*fa9e4066Sahrens if (mode & 01) { 284*fa9e4066Sahrens access |= ACE_EXECUTE; 285*fa9e4066Sahrens } 286*fa9e4066Sahrens 287*fa9e4066Sahrens return (access); 288*fa9e4066Sahrens } 289*fa9e4066Sahrens 290*fa9e4066Sahrens /* 291*fa9e4066Sahrens * Given an nfsace (presumably an ALLOW entry), make a 292*fa9e4066Sahrens * corresponding DENY entry at the address given. 293*fa9e4066Sahrens */ 294*fa9e4066Sahrens static void 295*fa9e4066Sahrens ace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner) 296*fa9e4066Sahrens { 297*fa9e4066Sahrens (void) memcpy(deny, allow, sizeof (ace_t)); 298*fa9e4066Sahrens 299*fa9e4066Sahrens deny->a_who = allow->a_who; 300*fa9e4066Sahrens 301*fa9e4066Sahrens deny->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 302*fa9e4066Sahrens deny->a_access_mask ^= ACE_POSIX_SUPPORTED_BITS; 303*fa9e4066Sahrens if (isdir) 304*fa9e4066Sahrens deny->a_access_mask ^= ACE_DELETE_CHILD; 305*fa9e4066Sahrens 306*fa9e4066Sahrens deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER | 307*fa9e4066Sahrens ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS | 308*fa9e4066Sahrens ACE_WRITE_NAMED_ATTRS); 309*fa9e4066Sahrens deny->a_access_mask |= access_mask_set((allow->a_access_mask & 310*fa9e4066Sahrens ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner, 311*fa9e4066Sahrens B_FALSE); 312*fa9e4066Sahrens } 313*fa9e4066Sahrens /* 314*fa9e4066Sahrens * Make an initial pass over an array of aclent_t's. Gather 315*fa9e4066Sahrens * information such as an ACL_MASK (if any), number of users, 316*fa9e4066Sahrens * number of groups, and whether the array needs to be sorted. 317*fa9e4066Sahrens */ 318*fa9e4066Sahrens static int 319*fa9e4066Sahrens ln_aent_preprocess(aclent_t *aclent, int n, 320*fa9e4066Sahrens int *hasmask, mode_t *mask, 321*fa9e4066Sahrens int *numuser, int *numgroup, int *needsort) 322*fa9e4066Sahrens { 323*fa9e4066Sahrens int error = 0; 324*fa9e4066Sahrens int i; 325*fa9e4066Sahrens int curtype = 0; 326*fa9e4066Sahrens 327*fa9e4066Sahrens *hasmask = 0; 328*fa9e4066Sahrens *mask = 07; 329*fa9e4066Sahrens *needsort = 0; 330*fa9e4066Sahrens *numuser = 0; 331*fa9e4066Sahrens *numgroup = 0; 332*fa9e4066Sahrens 333*fa9e4066Sahrens for (i = 0; i < n; i++) { 334*fa9e4066Sahrens if (aclent[i].a_type < curtype) 335*fa9e4066Sahrens *needsort = 1; 336*fa9e4066Sahrens else if (aclent[i].a_type > curtype) 337*fa9e4066Sahrens curtype = aclent[i].a_type; 338*fa9e4066Sahrens if (aclent[i].a_type & USER) 339*fa9e4066Sahrens (*numuser)++; 340*fa9e4066Sahrens if (aclent[i].a_type & (GROUP | GROUP_OBJ)) 341*fa9e4066Sahrens (*numgroup)++; 342*fa9e4066Sahrens if (aclent[i].a_type & CLASS_OBJ) { 343*fa9e4066Sahrens if (*hasmask) { 344*fa9e4066Sahrens error = EINVAL; 345*fa9e4066Sahrens goto out; 346*fa9e4066Sahrens } else { 347*fa9e4066Sahrens *hasmask = 1; 348*fa9e4066Sahrens *mask = aclent[i].a_perm; 349*fa9e4066Sahrens } 350*fa9e4066Sahrens } 351*fa9e4066Sahrens } 352*fa9e4066Sahrens 353*fa9e4066Sahrens if ((! *hasmask) && (*numuser + *numgroup > 1)) { 354*fa9e4066Sahrens error = EINVAL; 355*fa9e4066Sahrens goto out; 356*fa9e4066Sahrens } 357*fa9e4066Sahrens 358*fa9e4066Sahrens out: 359*fa9e4066Sahrens return (error); 360*fa9e4066Sahrens } 361*fa9e4066Sahrens 362*fa9e4066Sahrens /* 363*fa9e4066Sahrens * Convert an array of aclent_t into an array of nfsace entries, 364*fa9e4066Sahrens * following POSIX draft -> nfsv4 conversion semantics as outlined in 365*fa9e4066Sahrens * the IETF draft. 366*fa9e4066Sahrens */ 367*fa9e4066Sahrens static int 368*fa9e4066Sahrens ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir) 369*fa9e4066Sahrens { 370*fa9e4066Sahrens int error = 0; 371*fa9e4066Sahrens mode_t mask; 372*fa9e4066Sahrens int numuser, numgroup, needsort; 373*fa9e4066Sahrens int resultsize = 0; 374*fa9e4066Sahrens int i, groupi = 0, skip; 375*fa9e4066Sahrens ace_t *acep, *result = NULL; 376*fa9e4066Sahrens int hasmask; 377*fa9e4066Sahrens 378*fa9e4066Sahrens error = ln_aent_preprocess(aclent, n, &hasmask, &mask, 379*fa9e4066Sahrens &numuser, &numgroup, &needsort); 380*fa9e4066Sahrens if (error != 0) 381*fa9e4066Sahrens goto out; 382*fa9e4066Sahrens 383*fa9e4066Sahrens /* allow + deny for each aclent */ 384*fa9e4066Sahrens resultsize = n * 2; 385*fa9e4066Sahrens if (hasmask) { 386*fa9e4066Sahrens /* 387*fa9e4066Sahrens * stick extra deny on the group_obj and on each 388*fa9e4066Sahrens * user|group for the mask (the group_obj was added 389*fa9e4066Sahrens * into the count for numgroup) 390*fa9e4066Sahrens */ 391*fa9e4066Sahrens resultsize += numuser + numgroup; 392*fa9e4066Sahrens /* ... and don't count the mask itself */ 393*fa9e4066Sahrens resultsize -= 2; 394*fa9e4066Sahrens } 395*fa9e4066Sahrens 396*fa9e4066Sahrens /* sort the source if necessary */ 397*fa9e4066Sahrens if (needsort) 398*fa9e4066Sahrens ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls); 399*fa9e4066Sahrens 400*fa9e4066Sahrens result = acep = calloc(1, resultsize * sizeof (ace_t)); 401*fa9e4066Sahrens if (result == NULL) 402*fa9e4066Sahrens goto out; 403*fa9e4066Sahrens 404*fa9e4066Sahrens for (i = 0; i < n; i++) { 405*fa9e4066Sahrens /* 406*fa9e4066Sahrens * don't process CLASS_OBJ (mask); mask was grabbed in 407*fa9e4066Sahrens * ln_aent_preprocess() 408*fa9e4066Sahrens */ 409*fa9e4066Sahrens if (aclent[i].a_type & CLASS_OBJ) 410*fa9e4066Sahrens continue; 411*fa9e4066Sahrens 412*fa9e4066Sahrens /* If we need an ACL_MASK emulator, prepend it now */ 413*fa9e4066Sahrens if ((hasmask) && 414*fa9e4066Sahrens (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) { 415*fa9e4066Sahrens acep->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 416*fa9e4066Sahrens acep->a_flags = 0; 417*fa9e4066Sahrens if (aclent[i].a_type & GROUP_OBJ) { 418*fa9e4066Sahrens acep->a_who = -1; 419*fa9e4066Sahrens acep->a_flags |= 420*fa9e4066Sahrens (ACE_IDENTIFIER_GROUP|ACE_GROUP); 421*fa9e4066Sahrens } else if (aclent[i].a_type & USER) { 422*fa9e4066Sahrens acep->a_who = aclent[i].a_id; 423*fa9e4066Sahrens } else { 424*fa9e4066Sahrens acep->a_who = aclent[i].a_id; 425*fa9e4066Sahrens acep->a_flags |= ACE_IDENTIFIER_GROUP; 426*fa9e4066Sahrens } 427*fa9e4066Sahrens if (aclent[i].a_type & ACL_DEFAULT) { 428*fa9e4066Sahrens acep->a_flags |= ACE_INHERIT_ONLY_ACE | 429*fa9e4066Sahrens ACE_FILE_INHERIT_ACE | 430*fa9e4066Sahrens ACE_DIRECTORY_INHERIT_ACE; 431*fa9e4066Sahrens } 432*fa9e4066Sahrens /* 433*fa9e4066Sahrens * Set the access mask for the prepended deny 434*fa9e4066Sahrens * ace. To do this, we invert the mask (found 435*fa9e4066Sahrens * in ln_aent_preprocess()) then convert it to an 436*fa9e4066Sahrens * DENY ace access_mask. 437*fa9e4066Sahrens */ 438*fa9e4066Sahrens acep->a_access_mask = mode_to_ace_access((mask ^ 07), 439*fa9e4066Sahrens isdir, 0, 0); 440*fa9e4066Sahrens acep += 1; 441*fa9e4066Sahrens } 442*fa9e4066Sahrens 443*fa9e4066Sahrens /* handle a_perm -> access_mask */ 444*fa9e4066Sahrens acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm, 445*fa9e4066Sahrens isdir, aclent[i].a_type & USER_OBJ, 1); 446*fa9e4066Sahrens 447*fa9e4066Sahrens /* emulate a default aclent */ 448*fa9e4066Sahrens if (aclent[i].a_type & ACL_DEFAULT) { 449*fa9e4066Sahrens acep->a_flags |= ACE_INHERIT_ONLY_ACE | 450*fa9e4066Sahrens ACE_FILE_INHERIT_ACE | 451*fa9e4066Sahrens ACE_DIRECTORY_INHERIT_ACE; 452*fa9e4066Sahrens } 453*fa9e4066Sahrens 454*fa9e4066Sahrens /* 455*fa9e4066Sahrens * handle a_perm and a_id 456*fa9e4066Sahrens * 457*fa9e4066Sahrens * this must be done last, since it involves the 458*fa9e4066Sahrens * corresponding deny aces, which are handled 459*fa9e4066Sahrens * differently for each different a_type. 460*fa9e4066Sahrens */ 461*fa9e4066Sahrens if (aclent[i].a_type & USER_OBJ) { 462*fa9e4066Sahrens acep->a_who = -1; 463*fa9e4066Sahrens acep->a_flags |= ACE_OWNER; 464*fa9e4066Sahrens ace_make_deny(acep, acep + 1, isdir, B_TRUE); 465*fa9e4066Sahrens acep += 2; 466*fa9e4066Sahrens } else if (aclent[i].a_type & USER) { 467*fa9e4066Sahrens acep->a_who = aclent[i].a_id; 468*fa9e4066Sahrens ace_make_deny(acep, acep + 1, isdir, B_FALSE); 469*fa9e4066Sahrens acep += 2; 470*fa9e4066Sahrens } else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) { 471*fa9e4066Sahrens if (aclent[i].a_type & GROUP_OBJ) { 472*fa9e4066Sahrens acep->a_who = -1; 473*fa9e4066Sahrens acep->a_flags |= ACE_GROUP; 474*fa9e4066Sahrens } else { 475*fa9e4066Sahrens acep->a_who = aclent[i].a_id; 476*fa9e4066Sahrens } 477*fa9e4066Sahrens acep->a_flags |= ACE_IDENTIFIER_GROUP; 478*fa9e4066Sahrens /* 479*fa9e4066Sahrens * Set the corresponding deny for the group ace. 480*fa9e4066Sahrens * 481*fa9e4066Sahrens * The deny aces go after all of the groups, unlike 482*fa9e4066Sahrens * everything else, where they immediately follow 483*fa9e4066Sahrens * the allow ace. 484*fa9e4066Sahrens * 485*fa9e4066Sahrens * We calculate "skip", the number of slots to 486*fa9e4066Sahrens * skip ahead for the deny ace, here. 487*fa9e4066Sahrens * 488*fa9e4066Sahrens * The pattern is: 489*fa9e4066Sahrens * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3 490*fa9e4066Sahrens * thus, skip is 491*fa9e4066Sahrens * (2 * numgroup) - 1 - groupi 492*fa9e4066Sahrens * (2 * numgroup) to account for MD + A 493*fa9e4066Sahrens * - 1 to account for the fact that we're on the 494*fa9e4066Sahrens * access (A), not the mask (MD) 495*fa9e4066Sahrens * - groupi to account for the fact that we have 496*fa9e4066Sahrens * passed up groupi number of MD's. 497*fa9e4066Sahrens */ 498*fa9e4066Sahrens skip = (2 * numgroup) - 1 - groupi; 499*fa9e4066Sahrens ace_make_deny(acep, acep + skip, isdir, B_FALSE); 500*fa9e4066Sahrens /* 501*fa9e4066Sahrens * If we just did the last group, skip acep past 502*fa9e4066Sahrens * all of the denies; else, just move ahead one. 503*fa9e4066Sahrens */ 504*fa9e4066Sahrens if (++groupi >= numgroup) 505*fa9e4066Sahrens acep += numgroup + 1; 506*fa9e4066Sahrens else 507*fa9e4066Sahrens acep += 1; 508*fa9e4066Sahrens } else if (aclent[i].a_type & OTHER_OBJ) { 509*fa9e4066Sahrens acep->a_who = -1; 510*fa9e4066Sahrens acep->a_flags |= ACE_EVERYONE; 511*fa9e4066Sahrens ace_make_deny(acep, acep + 1, isdir, B_FALSE); 512*fa9e4066Sahrens acep += 2; 513*fa9e4066Sahrens } else { 514*fa9e4066Sahrens error = EINVAL; 515*fa9e4066Sahrens goto out; 516*fa9e4066Sahrens } 517*fa9e4066Sahrens } 518*fa9e4066Sahrens 519*fa9e4066Sahrens *acepp = result; 520*fa9e4066Sahrens *rescount = resultsize; 521*fa9e4066Sahrens 522*fa9e4066Sahrens out: 523*fa9e4066Sahrens if (error != 0) { 524*fa9e4066Sahrens if ((result != NULL) && (resultsize > 0)) { 525*fa9e4066Sahrens free(result); 526*fa9e4066Sahrens } 527*fa9e4066Sahrens } 528*fa9e4066Sahrens 529*fa9e4066Sahrens return (error); 530*fa9e4066Sahrens } 531*fa9e4066Sahrens 532*fa9e4066Sahrens static int 533*fa9e4066Sahrens convert_aent_to_ace(aclent_t *aclentp, int aclcnt, int isdir, 534*fa9e4066Sahrens ace_t **retacep, int *retacecnt) 535*fa9e4066Sahrens { 536*fa9e4066Sahrens ace_t *acep; 537*fa9e4066Sahrens ace_t *dfacep; 538*fa9e4066Sahrens ace_t *newacep; 539*fa9e4066Sahrens int acecnt = 0; 540*fa9e4066Sahrens int dfacecnt = 0; 541*fa9e4066Sahrens int dfaclstart = 0; 542*fa9e4066Sahrens int dfaclcnt = 0; 543*fa9e4066Sahrens aclent_t *aclp; 544*fa9e4066Sahrens int i; 545*fa9e4066Sahrens int error; 546*fa9e4066Sahrens 547*fa9e4066Sahrens ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls); 548*fa9e4066Sahrens 549*fa9e4066Sahrens for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) { 550*fa9e4066Sahrens if (aclp->a_type & ACL_DEFAULT) 551*fa9e4066Sahrens break; 552*fa9e4066Sahrens } 553*fa9e4066Sahrens 554*fa9e4066Sahrens if (i < aclcnt) { 555*fa9e4066Sahrens dfaclstart = aclcnt - i; 556*fa9e4066Sahrens dfaclcnt = i; 557*fa9e4066Sahrens } 558*fa9e4066Sahrens 559*fa9e4066Sahrens if (dfaclcnt && isdir == 0) { 560*fa9e4066Sahrens return (-1); 561*fa9e4066Sahrens } 562*fa9e4066Sahrens 563*fa9e4066Sahrens error = ln_aent_to_ace(aclentp, i, &acep, &acecnt, isdir); 564*fa9e4066Sahrens if (error) 565*fa9e4066Sahrens return (-1); 566*fa9e4066Sahrens 567*fa9e4066Sahrens if (dfaclcnt) { 568*fa9e4066Sahrens error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt, 569*fa9e4066Sahrens &dfacep, &dfacecnt, isdir); 570*fa9e4066Sahrens if (error) { 571*fa9e4066Sahrens if (acep) { 572*fa9e4066Sahrens free(acep); 573*fa9e4066Sahrens } 574*fa9e4066Sahrens return (-1); 575*fa9e4066Sahrens } 576*fa9e4066Sahrens } 577*fa9e4066Sahrens 578*fa9e4066Sahrens newacep = malloc(sizeof (ace_t) * (acecnt + dfacecnt)); 579*fa9e4066Sahrens if (newacep == NULL) 580*fa9e4066Sahrens return (-1); 581*fa9e4066Sahrens 582*fa9e4066Sahrens (void) memcpy(newacep, acep, sizeof (ace_t) * acecnt); 583*fa9e4066Sahrens if (dfaclcnt) { 584*fa9e4066Sahrens (void) memcpy(newacep + acecnt, dfacep, 585*fa9e4066Sahrens sizeof (ace_t) * dfacecnt); 586*fa9e4066Sahrens } 587*fa9e4066Sahrens free(acep); 588*fa9e4066Sahrens if (dfaclcnt) 589*fa9e4066Sahrens free(dfacep); 590*fa9e4066Sahrens 591*fa9e4066Sahrens *retacecnt = acecnt + dfacecnt; 592*fa9e4066Sahrens *retacep = newacep; 593*fa9e4066Sahrens return (0); 594*fa9e4066Sahrens } 595*fa9e4066Sahrens 596*fa9e4066Sahrens 597*fa9e4066Sahrens static int 598*fa9e4066Sahrens cacl_get(acl_inp inp, int get_flag, int type, acl_t **aclp) 599*fa9e4066Sahrens { 600*fa9e4066Sahrens const char *fname; 601*fa9e4066Sahrens int fd; 602*fa9e4066Sahrens int ace_acl = 0; 603*fa9e4066Sahrens int error; 604*fa9e4066Sahrens int getcmd, cntcmd; 605*fa9e4066Sahrens acl_t *acl_info; 606*fa9e4066Sahrens int save_errno; 607*fa9e4066Sahrens int stat_error; 608*fa9e4066Sahrens struct stat64 statbuf; 609*fa9e4066Sahrens 610*fa9e4066Sahrens *aclp = NULL; 611*fa9e4066Sahrens if (type == ACL_PATH) { 612*fa9e4066Sahrens fname = inp.file; 613*fa9e4066Sahrens ace_acl = pathconf(fname, _PC_ACL_ENABLED); 614*fa9e4066Sahrens } else { 615*fa9e4066Sahrens fd = inp.fd; 616*fa9e4066Sahrens ace_acl = fpathconf(fd, _PC_ACL_ENABLED); 617*fa9e4066Sahrens } 618*fa9e4066Sahrens 619*fa9e4066Sahrens if (ace_acl == -1) 620*fa9e4066Sahrens return (-1); 621*fa9e4066Sahrens 622*fa9e4066Sahrens /* 623*fa9e4066Sahrens * if acl's aren't supported then 624*fa9e4066Sahrens * send it through the old GETACL interface 625*fa9e4066Sahrens */ 626*fa9e4066Sahrens if (ace_acl == 0) { 627*fa9e4066Sahrens ace_acl = _ACL_ACLENT_ENABLED; 628*fa9e4066Sahrens } 629*fa9e4066Sahrens 630*fa9e4066Sahrens if (ace_acl & _ACL_ACE_ENABLED) { 631*fa9e4066Sahrens cntcmd = ACE_GETACLCNT; 632*fa9e4066Sahrens getcmd = ACE_GETACL; 633*fa9e4066Sahrens acl_info = acl_alloc(ACE_T); 634*fa9e4066Sahrens } else { 635*fa9e4066Sahrens cntcmd = GETACLCNT; 636*fa9e4066Sahrens getcmd = GETACL; 637*fa9e4066Sahrens acl_info = acl_alloc(ACLENT_T); 638*fa9e4066Sahrens } 639*fa9e4066Sahrens 640*fa9e4066Sahrens if (acl_info == NULL) 641*fa9e4066Sahrens return (-1); 642*fa9e4066Sahrens 643*fa9e4066Sahrens if (type == ACL_PATH) { 644*fa9e4066Sahrens acl_info->acl_cnt = acl(fname, cntcmd, 0, NULL); 645*fa9e4066Sahrens } else { 646*fa9e4066Sahrens acl_info->acl_cnt = facl(fd, cntcmd, 0, NULL); 647*fa9e4066Sahrens } 648*fa9e4066Sahrens 649*fa9e4066Sahrens save_errno = errno; 650*fa9e4066Sahrens if (acl_info->acl_cnt < 0) { 651*fa9e4066Sahrens acl_free(acl_info); 652*fa9e4066Sahrens errno = save_errno; 653*fa9e4066Sahrens return (-1); 654*fa9e4066Sahrens } 655*fa9e4066Sahrens 656*fa9e4066Sahrens if (acl_info->acl_cnt == 0) { 657*fa9e4066Sahrens acl_free(acl_info); 658*fa9e4066Sahrens errno = save_errno; 659*fa9e4066Sahrens return (0); 660*fa9e4066Sahrens } 661*fa9e4066Sahrens 662*fa9e4066Sahrens acl_info->acl_aclp = 663*fa9e4066Sahrens malloc(acl_info->acl_cnt * acl_info->acl_entry_size); 664*fa9e4066Sahrens save_errno = errno; 665*fa9e4066Sahrens 666*fa9e4066Sahrens if (acl_info->acl_aclp == NULL) { 667*fa9e4066Sahrens acl_free(acl_info); 668*fa9e4066Sahrens errno = save_errno; 669*fa9e4066Sahrens return (-1); 670*fa9e4066Sahrens } 671*fa9e4066Sahrens 672*fa9e4066Sahrens if (type == ACL_PATH) { 673*fa9e4066Sahrens stat_error = stat64(fname, &statbuf); 674*fa9e4066Sahrens error = acl(fname, getcmd, acl_info->acl_cnt, 675*fa9e4066Sahrens acl_info->acl_aclp); 676*fa9e4066Sahrens } else { 677*fa9e4066Sahrens stat_error = fstat64(fd, &statbuf); 678*fa9e4066Sahrens error = facl(fd, getcmd, acl_info->acl_cnt, 679*fa9e4066Sahrens acl_info->acl_aclp); 680*fa9e4066Sahrens } 681*fa9e4066Sahrens 682*fa9e4066Sahrens save_errno = errno; 683*fa9e4066Sahrens if (error == -1) { 684*fa9e4066Sahrens acl_free(acl_info); 685*fa9e4066Sahrens errno = save_errno; 686*fa9e4066Sahrens return (-1); 687*fa9e4066Sahrens } 688*fa9e4066Sahrens 689*fa9e4066Sahrens 690*fa9e4066Sahrens if (stat_error == 0) { 691*fa9e4066Sahrens acl_info->acl_flags = 692*fa9e4066Sahrens (S_ISDIR(statbuf.st_mode) ? ACL_IS_DIR : 0); 693*fa9e4066Sahrens } else 694*fa9e4066Sahrens acl_info->acl_flags = 0; 695*fa9e4066Sahrens 696*fa9e4066Sahrens switch (acl_info->acl_type) { 697*fa9e4066Sahrens case ACLENT_T: 698*fa9e4066Sahrens if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) 699*fa9e4066Sahrens acl_info->acl_flags |= ACL_IS_TRIVIAL; 700*fa9e4066Sahrens break; 701*fa9e4066Sahrens case ACE_T: 702*fa9e4066Sahrens if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) 703*fa9e4066Sahrens acl_info->acl_flags |= ACL_IS_TRIVIAL; 704*fa9e4066Sahrens break; 705*fa9e4066Sahrens default: 706*fa9e4066Sahrens errno = EINVAL; 707*fa9e4066Sahrens acl_free(acl_info); 708*fa9e4066Sahrens return (-1); 709*fa9e4066Sahrens } 710*fa9e4066Sahrens 711*fa9e4066Sahrens if ((acl_info->acl_flags & ACL_IS_TRIVIAL) && 712*fa9e4066Sahrens (get_flag & ACL_NO_TRIVIAL)) { 713*fa9e4066Sahrens acl_free(acl_info); 714*fa9e4066Sahrens errno = 0; 715*fa9e4066Sahrens return (0); 716*fa9e4066Sahrens } 717*fa9e4066Sahrens 718*fa9e4066Sahrens *aclp = acl_info; 719*fa9e4066Sahrens return (0); 720*fa9e4066Sahrens } 721*fa9e4066Sahrens 722*fa9e4066Sahrens /* 723*fa9e4066Sahrens * return -1 on failure, otherwise the number of acl 724*fa9e4066Sahrens * entries is returned 725*fa9e4066Sahrens */ 726*fa9e4066Sahrens int 727*fa9e4066Sahrens acl_get(const char *path, int get_flag, acl_t **aclp) 728*fa9e4066Sahrens { 729*fa9e4066Sahrens acl_inp acl_inp; 730*fa9e4066Sahrens acl_inp.file = path; 731*fa9e4066Sahrens 732*fa9e4066Sahrens return (cacl_get(acl_inp, get_flag, ACL_PATH, aclp)); 733*fa9e4066Sahrens } 734*fa9e4066Sahrens 735*fa9e4066Sahrens int 736*fa9e4066Sahrens facl_get(int fd, int get_flag, acl_t **aclp) 737*fa9e4066Sahrens { 738*fa9e4066Sahrens 739*fa9e4066Sahrens acl_inp acl_inp; 740*fa9e4066Sahrens acl_inp.fd = fd; 741*fa9e4066Sahrens 742*fa9e4066Sahrens return (cacl_get(acl_inp, get_flag, ACL_FD, aclp)); 743*fa9e4066Sahrens } 744*fa9e4066Sahrens 745*fa9e4066Sahrens /* 746*fa9e4066Sahrens * Set an ACL, translates acl to ace_t when appropriate. 747*fa9e4066Sahrens */ 748*fa9e4066Sahrens static int 749*fa9e4066Sahrens cacl_set(acl_inp *acl_inp, acl_t *aclp, int type) 750*fa9e4066Sahrens { 751*fa9e4066Sahrens int error = 0; 752*fa9e4066Sahrens int acl_flavor_target; 753*fa9e4066Sahrens ace_t *acep = NULL; 754*fa9e4066Sahrens int acecnt; 755*fa9e4066Sahrens struct stat64 statbuf; 756*fa9e4066Sahrens int stat_error; 757*fa9e4066Sahrens int isdir; 758*fa9e4066Sahrens 759*fa9e4066Sahrens 760*fa9e4066Sahrens if (type == ACL_PATH) { 761*fa9e4066Sahrens stat_error = stat64(acl_inp->file, &statbuf); 762*fa9e4066Sahrens if (stat_error) 763*fa9e4066Sahrens return (-1); 764*fa9e4066Sahrens acl_flavor_target = pathconf(acl_inp->file, _PC_ACL_ENABLED); 765*fa9e4066Sahrens } else { 766*fa9e4066Sahrens stat_error = fstat64(acl_inp->fd, &statbuf); 767*fa9e4066Sahrens if (stat_error) 768*fa9e4066Sahrens return (-1); 769*fa9e4066Sahrens acl_flavor_target = fpathconf(acl_inp->fd, _PC_ACL_ENABLED); 770*fa9e4066Sahrens } 771*fa9e4066Sahrens 772*fa9e4066Sahrens isdir = S_ISDIR(statbuf.st_mode); 773*fa9e4066Sahrens 774*fa9e4066Sahrens if (acl_flavor_target == -1) 775*fa9e4066Sahrens return (-1); 776*fa9e4066Sahrens 777*fa9e4066Sahrens /* 778*fa9e4066Sahrens * Translate aclent_t ACL's to ACE ACL's. 779*fa9e4066Sahrens */ 780*fa9e4066Sahrens if (acl_flavor_target == _ACL_ACE_ENABLED && 781*fa9e4066Sahrens aclp->acl_type == ACLENT_T) { 782*fa9e4066Sahrens error = convert_aent_to_ace(aclp->acl_aclp, 783*fa9e4066Sahrens aclp->acl_cnt, isdir, &acep, &acecnt); 784*fa9e4066Sahrens if (error) { 785*fa9e4066Sahrens errno = ENOTSUP; 786*fa9e4066Sahrens return (-1); 787*fa9e4066Sahrens } 788*fa9e4066Sahrens /* 789*fa9e4066Sahrens * replace old acl with newly translated acl 790*fa9e4066Sahrens */ 791*fa9e4066Sahrens free(aclp->acl_aclp); 792*fa9e4066Sahrens aclp->acl_aclp = acep; 793*fa9e4066Sahrens aclp->acl_cnt = acecnt; 794*fa9e4066Sahrens aclp->acl_type = ACE_T; 795*fa9e4066Sahrens } 796*fa9e4066Sahrens 797*fa9e4066Sahrens if (type == ACL_PATH) { 798*fa9e4066Sahrens error = acl(acl_inp->file, 799*fa9e4066Sahrens (aclp->acl_type == ACE_T) ? ACE_SETACL : SETACL, 800*fa9e4066Sahrens aclp->acl_cnt, aclp->acl_aclp); 801*fa9e4066Sahrens } else { 802*fa9e4066Sahrens error = facl(acl_inp->fd, 803*fa9e4066Sahrens (aclp->acl_type == ACE_T) ? ACE_SETACL : SETACL, 804*fa9e4066Sahrens aclp->acl_cnt, aclp->acl_aclp); 805*fa9e4066Sahrens } 806*fa9e4066Sahrens 807*fa9e4066Sahrens return (error); 808*fa9e4066Sahrens } 809*fa9e4066Sahrens 810*fa9e4066Sahrens int 811*fa9e4066Sahrens acl_set(const char *path, acl_t *aclp) 812*fa9e4066Sahrens { 813*fa9e4066Sahrens acl_inp acl_inp; 814*fa9e4066Sahrens 815*fa9e4066Sahrens acl_inp.file = path; 816*fa9e4066Sahrens 817*fa9e4066Sahrens return (cacl_set(&acl_inp, aclp, ACL_PATH)); 818*fa9e4066Sahrens } 819*fa9e4066Sahrens 820*fa9e4066Sahrens int 821*fa9e4066Sahrens facl_set(int fd, acl_t *aclp) 822*fa9e4066Sahrens { 823*fa9e4066Sahrens acl_inp acl_inp; 824*fa9e4066Sahrens 825*fa9e4066Sahrens acl_inp.fd = fd; 826*fa9e4066Sahrens 827*fa9e4066Sahrens return (cacl_set(&acl_inp, aclp, ACL_FD)); 828*fa9e4066Sahrens } 829*fa9e4066Sahrens 830*fa9e4066Sahrens int 831*fa9e4066Sahrens acl_cnt(acl_t *aclp) 832*fa9e4066Sahrens { 833*fa9e4066Sahrens return (aclp->acl_cnt); 834*fa9e4066Sahrens } 835*fa9e4066Sahrens 836*fa9e4066Sahrens int 837*fa9e4066Sahrens acl_type(acl_t *aclp) 838*fa9e4066Sahrens { 839*fa9e4066Sahrens return (aclp->acl_type); 840*fa9e4066Sahrens } 841*fa9e4066Sahrens 842*fa9e4066Sahrens acl_t * 843*fa9e4066Sahrens acl_dup(acl_t *aclp) 844*fa9e4066Sahrens { 845*fa9e4066Sahrens acl_t *newaclp; 846*fa9e4066Sahrens 847*fa9e4066Sahrens newaclp = acl_alloc(aclp->acl_type); 848*fa9e4066Sahrens if (newaclp == NULL) 849*fa9e4066Sahrens return (NULL); 850*fa9e4066Sahrens 851*fa9e4066Sahrens newaclp->acl_aclp = malloc(aclp->acl_entry_size * aclp->acl_cnt); 852*fa9e4066Sahrens if (newaclp->acl_aclp == NULL) { 853*fa9e4066Sahrens acl_free(newaclp); 854*fa9e4066Sahrens return (NULL); 855*fa9e4066Sahrens } 856*fa9e4066Sahrens 857*fa9e4066Sahrens (void) memcpy(newaclp->acl_aclp, 858*fa9e4066Sahrens aclp->acl_aclp, aclp->acl_entry_size * aclp->acl_cnt); 859*fa9e4066Sahrens newaclp->acl_cnt = aclp->acl_cnt; 860*fa9e4066Sahrens 861*fa9e4066Sahrens return (newaclp); 862*fa9e4066Sahrens } 863*fa9e4066Sahrens 864*fa9e4066Sahrens int 865*fa9e4066Sahrens acl_flags(acl_t *aclp) 866*fa9e4066Sahrens { 867*fa9e4066Sahrens return (aclp->acl_flags); 868*fa9e4066Sahrens } 869*fa9e4066Sahrens 870*fa9e4066Sahrens void * 871*fa9e4066Sahrens acl_data(acl_t *aclp) 872*fa9e4066Sahrens { 873*fa9e4066Sahrens return (aclp->acl_aclp); 874*fa9e4066Sahrens } 875*fa9e4066Sahrens 876*fa9e4066Sahrens /* 877*fa9e4066Sahrens * Remove an ACL from a file and create a trivial ACL based 878*fa9e4066Sahrens * off of the mode argument. After acl has been set owner/group 879*fa9e4066Sahrens * are updated to match owner,group arguments 880*fa9e4066Sahrens */ 881*fa9e4066Sahrens int 882*fa9e4066Sahrens acl_strip(const char *file, uid_t owner, gid_t group, mode_t mode) 883*fa9e4066Sahrens { 884*fa9e4066Sahrens int error = 0; 885*fa9e4066Sahrens aclent_t min_acl[MIN_ACL_ENTRIES]; 886*fa9e4066Sahrens ace_t min_ace_acl[6]; /* owner, group, everyone + complement denies */ 887*fa9e4066Sahrens int acl_flavor; 888*fa9e4066Sahrens int aclcnt; 889*fa9e4066Sahrens 890*fa9e4066Sahrens acl_flavor = pathconf(file, _PC_ACL_ENABLED); 891*fa9e4066Sahrens 892*fa9e4066Sahrens if (acl_flavor == -1) 893*fa9e4066Sahrens return (-1); 894*fa9e4066Sahrens /* 895*fa9e4066Sahrens * force it through aclent flavor when file system doesn't 896*fa9e4066Sahrens * understand question 897*fa9e4066Sahrens */ 898*fa9e4066Sahrens if (acl_flavor == 0) 899*fa9e4066Sahrens acl_flavor = _ACL_ACLENT_ENABLED; 900*fa9e4066Sahrens 901*fa9e4066Sahrens if (acl_flavor & _ACL_ACLENT_ENABLED) { 902*fa9e4066Sahrens min_acl[0].a_type = USER_OBJ; 903*fa9e4066Sahrens min_acl[0].a_id = owner; 904*fa9e4066Sahrens min_acl[0].a_perm = ((mode & 0700) >> 6); 905*fa9e4066Sahrens min_acl[1].a_type = GROUP_OBJ; 906*fa9e4066Sahrens min_acl[1].a_id = group; 907*fa9e4066Sahrens min_acl[1].a_perm = ((mode & 0070) >> 3); 908*fa9e4066Sahrens min_acl[2].a_type = CLASS_OBJ; 909*fa9e4066Sahrens min_acl[2].a_id = (uid_t)-1; 910*fa9e4066Sahrens min_acl[2].a_perm = ((mode & 0070) >> 3); 911*fa9e4066Sahrens min_acl[3].a_type = OTHER_OBJ; 912*fa9e4066Sahrens min_acl[3].a_id = (uid_t)-1; 913*fa9e4066Sahrens min_acl[3].a_perm = (mode & 0007); 914*fa9e4066Sahrens aclcnt = 4; 915*fa9e4066Sahrens error = acl(file, SETACL, aclcnt, min_acl); 916*fa9e4066Sahrens } else if (acl_flavor & _ACL_ACE_ENABLED) { 917*fa9e4066Sahrens (void) memcpy(min_ace_acl, trivial_acl, sizeof (ace_t) * 6); 918*fa9e4066Sahrens 919*fa9e4066Sahrens /* 920*fa9e4066Sahrens * Make aces match request mode 921*fa9e4066Sahrens */ 922*fa9e4066Sahrens adjust_ace_pair(&min_ace_acl[0], (mode & 0700) >> 6); 923*fa9e4066Sahrens adjust_ace_pair(&min_ace_acl[2], (mode & 0070) >> 3); 924*fa9e4066Sahrens adjust_ace_pair(&min_ace_acl[4], mode & 0007); 925*fa9e4066Sahrens 926*fa9e4066Sahrens error = acl(file, ACE_SETACL, 6, min_ace_acl); 927*fa9e4066Sahrens } else { 928*fa9e4066Sahrens errno = EINVAL; 929*fa9e4066Sahrens error = 1; 930*fa9e4066Sahrens } 931*fa9e4066Sahrens 932*fa9e4066Sahrens if (error == 0) 933*fa9e4066Sahrens error = chown(file, owner, group); 934*fa9e4066Sahrens return (error); 935*fa9e4066Sahrens } 936*fa9e4066Sahrens 937*fa9e4066Sahrens static int 938*fa9e4066Sahrens ace_match(void *entry1, void *entry2) 939*fa9e4066Sahrens { 940*fa9e4066Sahrens ace_t *p1 = (ace_t *)entry1; 941*fa9e4066Sahrens ace_t *p2 = (ace_t *)entry2; 942*fa9e4066Sahrens ace_t ace1, ace2; 943*fa9e4066Sahrens 944*fa9e4066Sahrens ace1 = *p1; 945*fa9e4066Sahrens ace2 = *p2; 946*fa9e4066Sahrens 947*fa9e4066Sahrens /* 948*fa9e4066Sahrens * Need to fixup who field for abstrations for 949*fa9e4066Sahrens * accurate comparison, since field is undefined. 950*fa9e4066Sahrens */ 951*fa9e4066Sahrens if (ace1.a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE)) 952*fa9e4066Sahrens ace1.a_who = -1; 953*fa9e4066Sahrens if (ace2.a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE)) 954*fa9e4066Sahrens ace2.a_who = -1; 955*fa9e4066Sahrens return (memcmp(&ace1, &ace2, sizeof (ace_t))); 956*fa9e4066Sahrens } 957*fa9e4066Sahrens 958*fa9e4066Sahrens static int 959*fa9e4066Sahrens aclent_match(void *entry1, void *entry2) 960*fa9e4066Sahrens { 961*fa9e4066Sahrens aclent_t *aclent1 = (aclent_t *)entry1; 962*fa9e4066Sahrens aclent_t *aclent2 = (aclent_t *)entry2; 963*fa9e4066Sahrens 964*fa9e4066Sahrens return (memcmp(aclent1, aclent2, sizeof (aclent_t))); 965*fa9e4066Sahrens } 966*fa9e4066Sahrens 967*fa9e4066Sahrens /* 968*fa9e4066Sahrens * Find acl entries in acl that correspond to removeacl. Search 969*fa9e4066Sahrens * is started from slot. The flag argument indicates whether to 970*fa9e4066Sahrens * remove all matches or just the first match. 971*fa9e4066Sahrens */ 972*fa9e4066Sahrens int 973*fa9e4066Sahrens acl_removeentries(acl_t *acl, acl_t *removeacl, int start_slot, int flag) 974*fa9e4066Sahrens { 975*fa9e4066Sahrens int i, j; 976*fa9e4066Sahrens int match; 977*fa9e4066Sahrens int (*acl_match)(void *acl1, void *acl2); 978*fa9e4066Sahrens void *acl_entry, *remove_entry; 979*fa9e4066Sahrens void *start; 980*fa9e4066Sahrens int found = 0; 981*fa9e4066Sahrens 982*fa9e4066Sahrens if (flag != ACL_REMOVE_ALL && flag != ACL_REMOVE_FIRST) 983*fa9e4066Sahrens flag = ACL_REMOVE_FIRST; 984*fa9e4066Sahrens 985*fa9e4066Sahrens if (acl == NULL || removeacl == NULL) 986*fa9e4066Sahrens return (EACL_NO_ACL_ENTRY); 987*fa9e4066Sahrens 988*fa9e4066Sahrens if (acl->acl_type != removeacl->acl_type) 989*fa9e4066Sahrens return (EACL_DIFF_TYPE); 990*fa9e4066Sahrens 991*fa9e4066Sahrens if (acl->acl_type == ACLENT_T) 992*fa9e4066Sahrens acl_match = aclent_match; 993*fa9e4066Sahrens else 994*fa9e4066Sahrens acl_match = ace_match; 995*fa9e4066Sahrens 996*fa9e4066Sahrens for (i = 0, remove_entry = removeacl->acl_aclp; 997*fa9e4066Sahrens i != removeacl->acl_cnt; i++) { 998*fa9e4066Sahrens 999*fa9e4066Sahrens j = 0; 1000*fa9e4066Sahrens acl_entry = (char *)acl->acl_aclp + 1001*fa9e4066Sahrens (acl->acl_entry_size * start_slot); 1002*fa9e4066Sahrens for (;;) { 1003*fa9e4066Sahrens match = acl_match(acl_entry, remove_entry); 1004*fa9e4066Sahrens if (match == 0) { 1005*fa9e4066Sahrens found++; 1006*fa9e4066Sahrens start = (char *)acl_entry + 1007*fa9e4066Sahrens acl->acl_entry_size; 1008*fa9e4066Sahrens (void) memmove(acl_entry, start, 1009*fa9e4066Sahrens acl->acl_entry_size * 1010*fa9e4066Sahrens acl->acl_cnt-- - (j + 1)); 1011*fa9e4066Sahrens 1012*fa9e4066Sahrens if (flag == ACL_REMOVE_FIRST) 1013*fa9e4066Sahrens break; 1014*fa9e4066Sahrens /* 1015*fa9e4066Sahrens * List has changed, restart search from 1016*fa9e4066Sahrens * beginning. 1017*fa9e4066Sahrens */ 1018*fa9e4066Sahrens acl_entry = acl->acl_aclp; 1019*fa9e4066Sahrens j = 0; 1020*fa9e4066Sahrens continue; 1021*fa9e4066Sahrens } 1022*fa9e4066Sahrens acl_entry = ((char *)acl_entry + acl->acl_entry_size); 1023*fa9e4066Sahrens if (++j >= acl->acl_cnt) { 1024*fa9e4066Sahrens break; 1025*fa9e4066Sahrens } 1026*fa9e4066Sahrens } 1027*fa9e4066Sahrens } 1028*fa9e4066Sahrens 1029*fa9e4066Sahrens return ((found == 0) ? EACL_NO_ACL_ENTRY : 0); 1030*fa9e4066Sahrens } 1031*fa9e4066Sahrens 1032*fa9e4066Sahrens /* 1033*fa9e4066Sahrens * Replace entires entries in acl1 with the corresponding entries 1034*fa9e4066Sahrens * in newentries. The where argument specifies where to begin 1035*fa9e4066Sahrens * the replacement. If the where argument is 1 greater than the 1036*fa9e4066Sahrens * number of acl entries in acl1 then they are appended. If the 1037*fa9e4066Sahrens * where argument is 2+ greater than the number of acl entries then 1038*fa9e4066Sahrens * EACL_INVALID_SLOT is returned. 1039*fa9e4066Sahrens */ 1040*fa9e4066Sahrens int 1041*fa9e4066Sahrens acl_modifyentries(acl_t *acl1, acl_t *newentries, int where) 1042*fa9e4066Sahrens { 1043*fa9e4066Sahrens 1044*fa9e4066Sahrens int slot; 1045*fa9e4066Sahrens int slots_needed; 1046*fa9e4066Sahrens int slots_left; 1047*fa9e4066Sahrens int newsize; 1048*fa9e4066Sahrens 1049*fa9e4066Sahrens if (acl1 == NULL || newentries == NULL) 1050*fa9e4066Sahrens return (EACL_NO_ACL_ENTRY); 1051*fa9e4066Sahrens 1052*fa9e4066Sahrens if (where < 0 || where >= acl1->acl_cnt) 1053*fa9e4066Sahrens return (EACL_INVALID_SLOT); 1054*fa9e4066Sahrens 1055*fa9e4066Sahrens if (acl1->acl_type != newentries->acl_type) 1056*fa9e4066Sahrens return (EACL_DIFF_TYPE); 1057*fa9e4066Sahrens 1058*fa9e4066Sahrens slot = where; 1059*fa9e4066Sahrens 1060*fa9e4066Sahrens slots_left = acl1->acl_cnt - slot + 1; 1061*fa9e4066Sahrens if (slots_left < newentries->acl_cnt) { 1062*fa9e4066Sahrens slots_needed = newentries->acl_cnt - slots_left; 1063*fa9e4066Sahrens newsize = (acl1->acl_entry_size * acl1->acl_cnt) + 1064*fa9e4066Sahrens (acl1->acl_entry_size * slots_needed); 1065*fa9e4066Sahrens acl1->acl_aclp = realloc(acl1->acl_aclp, newsize); 1066*fa9e4066Sahrens if (acl1->acl_aclp == NULL) 1067*fa9e4066Sahrens return (-1); 1068*fa9e4066Sahrens } 1069*fa9e4066Sahrens (void) memcpy((char *)acl1->acl_aclp + (acl1->acl_entry_size * slot), 1070*fa9e4066Sahrens newentries->acl_aclp, 1071*fa9e4066Sahrens newentries->acl_entry_size * newentries->acl_cnt); 1072*fa9e4066Sahrens 1073*fa9e4066Sahrens /* 1074*fa9e4066Sahrens * Did ACL grow? 1075*fa9e4066Sahrens */ 1076*fa9e4066Sahrens 1077*fa9e4066Sahrens if ((slot + newentries->acl_cnt) > acl1->acl_cnt) { 1078*fa9e4066Sahrens acl1->acl_cnt = slot + newentries->acl_cnt; 1079*fa9e4066Sahrens } 1080*fa9e4066Sahrens 1081*fa9e4066Sahrens return (0); 1082*fa9e4066Sahrens } 1083*fa9e4066Sahrens 1084*fa9e4066Sahrens /* 1085*fa9e4066Sahrens * Add acl2 entries into acl1. The where argument specifies where 1086*fa9e4066Sahrens * to add the entries. 1087*fa9e4066Sahrens */ 1088*fa9e4066Sahrens int 1089*fa9e4066Sahrens acl_addentries(acl_t *acl1, acl_t *acl2, int where) 1090*fa9e4066Sahrens { 1091*fa9e4066Sahrens 1092*fa9e4066Sahrens int newsize; 1093*fa9e4066Sahrens int len; 1094*fa9e4066Sahrens void *start; 1095*fa9e4066Sahrens void *to; 1096*fa9e4066Sahrens 1097*fa9e4066Sahrens if (acl1 == NULL || acl2 == NULL) 1098*fa9e4066Sahrens return (EACL_NO_ACL_ENTRY); 1099*fa9e4066Sahrens 1100*fa9e4066Sahrens if (acl1->acl_type != acl2->acl_type) 1101*fa9e4066Sahrens return (EACL_DIFF_TYPE); 1102*fa9e4066Sahrens 1103*fa9e4066Sahrens /* 1104*fa9e4066Sahrens * allow where to specify 1 past last slot for an append operation 1105*fa9e4066Sahrens * but anything greater is an error. 1106*fa9e4066Sahrens */ 1107*fa9e4066Sahrens if (where < 0 || where > acl1->acl_cnt) 1108*fa9e4066Sahrens return (EACL_INVALID_SLOT); 1109*fa9e4066Sahrens 1110*fa9e4066Sahrens newsize = (acl2->acl_entry_size * acl2->acl_cnt) + 1111*fa9e4066Sahrens (acl1->acl_entry_size * acl1->acl_cnt); 1112*fa9e4066Sahrens acl1->acl_aclp = realloc(acl1->acl_aclp, newsize); 1113*fa9e4066Sahrens if (acl1->acl_aclp == NULL) 1114*fa9e4066Sahrens return (-1); 1115*fa9e4066Sahrens 1116*fa9e4066Sahrens /* 1117*fa9e4066Sahrens * first push down entries where new ones will be inserted 1118*fa9e4066Sahrens */ 1119*fa9e4066Sahrens 1120*fa9e4066Sahrens to = (void *)((char *)acl1->acl_aclp + 1121*fa9e4066Sahrens ((where + acl2->acl_cnt) * acl1->acl_entry_size)); 1122*fa9e4066Sahrens 1123*fa9e4066Sahrens start = (void *)((char *)acl1->acl_aclp + 1124*fa9e4066Sahrens where * acl1->acl_entry_size); 1125*fa9e4066Sahrens 1126*fa9e4066Sahrens if (where < acl1->acl_cnt) { 1127*fa9e4066Sahrens len = (acl1->acl_cnt - where) * acl1->acl_entry_size; 1128*fa9e4066Sahrens (void) memmove(to, start, len); 1129*fa9e4066Sahrens } 1130*fa9e4066Sahrens 1131*fa9e4066Sahrens /* 1132*fa9e4066Sahrens * now stick in new entries. 1133*fa9e4066Sahrens */ 1134*fa9e4066Sahrens 1135*fa9e4066Sahrens (void) memmove(start, acl2->acl_aclp, 1136*fa9e4066Sahrens acl2->acl_cnt * acl2->acl_entry_size); 1137*fa9e4066Sahrens 1138*fa9e4066Sahrens acl1->acl_cnt += acl2->acl_cnt; 1139*fa9e4066Sahrens return (0); 1140*fa9e4066Sahrens } 1141*fa9e4066Sahrens 1142*fa9e4066Sahrens static void 1143*fa9e4066Sahrens aclent_perms(int perm, char *txt_perms) 1144*fa9e4066Sahrens { 1145*fa9e4066Sahrens if (perm & S_IROTH) 1146*fa9e4066Sahrens txt_perms[0] = 'r'; 1147*fa9e4066Sahrens else 1148*fa9e4066Sahrens txt_perms[0] = '-'; 1149*fa9e4066Sahrens if (perm & S_IWOTH) 1150*fa9e4066Sahrens txt_perms[1] = 'w'; 1151*fa9e4066Sahrens else 1152*fa9e4066Sahrens txt_perms[1] = '-'; 1153*fa9e4066Sahrens if (perm & S_IXOTH) 1154*fa9e4066Sahrens txt_perms[2] = 'x'; 1155*fa9e4066Sahrens else 1156*fa9e4066Sahrens txt_perms[2] = '-'; 1157*fa9e4066Sahrens txt_perms[3] = '\0'; 1158*fa9e4066Sahrens } 1159*fa9e4066Sahrens 1160*fa9e4066Sahrens static char * 1161*fa9e4066Sahrens pruname(uid_t uid) 1162*fa9e4066Sahrens { 1163*fa9e4066Sahrens struct passwd *passwdp; 1164*fa9e4066Sahrens static char uidp[10]; /* big enough */ 1165*fa9e4066Sahrens 1166*fa9e4066Sahrens passwdp = getpwuid(uid); 1167*fa9e4066Sahrens if (passwdp == (struct passwd *)NULL) { 1168*fa9e4066Sahrens /* could not get passwd information: display uid instead */ 1169*fa9e4066Sahrens (void) sprintf(uidp, "%ld", (long)uid); 1170*fa9e4066Sahrens return (uidp); 1171*fa9e4066Sahrens } else 1172*fa9e4066Sahrens return (passwdp->pw_name); 1173*fa9e4066Sahrens } 1174*fa9e4066Sahrens 1175*fa9e4066Sahrens static char * 1176*fa9e4066Sahrens prgname(gid_t gid) 1177*fa9e4066Sahrens { 1178*fa9e4066Sahrens struct group *groupp; 1179*fa9e4066Sahrens static char gidp[10]; /* big enough */ 1180*fa9e4066Sahrens 1181*fa9e4066Sahrens groupp = getgrgid(gid); 1182*fa9e4066Sahrens if (groupp == (struct group *)NULL) { 1183*fa9e4066Sahrens /* could not get group information: display gid instead */ 1184*fa9e4066Sahrens (void) sprintf(gidp, "%ld", (long)gid); 1185*fa9e4066Sahrens return (gidp); 1186*fa9e4066Sahrens } else 1187*fa9e4066Sahrens return (groupp->gr_name); 1188*fa9e4066Sahrens } 1189*fa9e4066Sahrens static void 1190*fa9e4066Sahrens aclent_printacl(acl_t *aclp) 1191*fa9e4066Sahrens { 1192*fa9e4066Sahrens aclent_t *tp; 1193*fa9e4066Sahrens int aclcnt; 1194*fa9e4066Sahrens int mask; 1195*fa9e4066Sahrens int slot = 0; 1196*fa9e4066Sahrens char perm[4]; 1197*fa9e4066Sahrens 1198*fa9e4066Sahrens /* display ACL: assume it is sorted. */ 1199*fa9e4066Sahrens aclcnt = aclp->acl_cnt; 1200*fa9e4066Sahrens for (tp = aclp->acl_aclp; aclcnt--; tp++) { 1201*fa9e4066Sahrens if (tp->a_type == CLASS_OBJ) 1202*fa9e4066Sahrens mask = tp->a_perm; 1203*fa9e4066Sahrens } 1204*fa9e4066Sahrens aclcnt = aclp->acl_cnt; 1205*fa9e4066Sahrens for (tp = aclp->acl_aclp; aclcnt--; tp++) { 1206*fa9e4066Sahrens (void) printf(" %d:", slot++); 1207*fa9e4066Sahrens switch (tp->a_type) { 1208*fa9e4066Sahrens case USER: 1209*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1210*fa9e4066Sahrens (void) printf("user:%s:%s\t\t", 1211*fa9e4066Sahrens pruname(tp->a_id), perm); 1212*fa9e4066Sahrens aclent_perms((tp->a_perm & mask), perm); 1213*fa9e4066Sahrens (void) printf("#effective:%s\n", perm); 1214*fa9e4066Sahrens break; 1215*fa9e4066Sahrens case USER_OBJ: 1216*fa9e4066Sahrens /* no need to display uid */ 1217*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1218*fa9e4066Sahrens (void) printf("user::%s\n", perm); 1219*fa9e4066Sahrens break; 1220*fa9e4066Sahrens case GROUP: 1221*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1222*fa9e4066Sahrens (void) printf("group:%s:%s\t\t", 1223*fa9e4066Sahrens prgname(tp->a_id), perm); 1224*fa9e4066Sahrens aclent_perms(tp->a_perm & mask, perm); 1225*fa9e4066Sahrens (void) printf("#effective:%s\n", perm); 1226*fa9e4066Sahrens break; 1227*fa9e4066Sahrens case GROUP_OBJ: 1228*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1229*fa9e4066Sahrens (void) printf("group::%s\t\t", perm); 1230*fa9e4066Sahrens aclent_perms(tp->a_perm & mask, perm); 1231*fa9e4066Sahrens (void) printf("#effective:%s\n", perm); 1232*fa9e4066Sahrens break; 1233*fa9e4066Sahrens case CLASS_OBJ: 1234*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1235*fa9e4066Sahrens (void) printf("mask:%s\n", perm); 1236*fa9e4066Sahrens break; 1237*fa9e4066Sahrens case OTHER_OBJ: 1238*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1239*fa9e4066Sahrens (void) printf("other:%s\n", perm); 1240*fa9e4066Sahrens break; 1241*fa9e4066Sahrens case DEF_USER: 1242*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1243*fa9e4066Sahrens (void) printf("default:user:%s:%s\n", 1244*fa9e4066Sahrens pruname(tp->a_id), perm); 1245*fa9e4066Sahrens break; 1246*fa9e4066Sahrens case DEF_USER_OBJ: 1247*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1248*fa9e4066Sahrens (void) printf("default:user::%s\n", perm); 1249*fa9e4066Sahrens break; 1250*fa9e4066Sahrens case DEF_GROUP: 1251*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1252*fa9e4066Sahrens (void) printf("default:group:%s:%s\n", 1253*fa9e4066Sahrens prgname(tp->a_id), perm); 1254*fa9e4066Sahrens break; 1255*fa9e4066Sahrens case DEF_GROUP_OBJ: 1256*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1257*fa9e4066Sahrens (void) printf("default:group::%s\n", perm); 1258*fa9e4066Sahrens break; 1259*fa9e4066Sahrens case DEF_CLASS_OBJ: 1260*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1261*fa9e4066Sahrens (void) printf("default:mask:%s\n", perm); 1262*fa9e4066Sahrens break; 1263*fa9e4066Sahrens case DEF_OTHER_OBJ: 1264*fa9e4066Sahrens aclent_perms(tp->a_perm, perm); 1265*fa9e4066Sahrens (void) printf("default:other:%s\n", perm); 1266*fa9e4066Sahrens break; 1267*fa9e4066Sahrens default: 1268*fa9e4066Sahrens (void) fprintf(stderr, 1269*fa9e4066Sahrens gettext("unrecognized entry\n")); 1270*fa9e4066Sahrens break; 1271*fa9e4066Sahrens } 1272*fa9e4066Sahrens } 1273*fa9e4066Sahrens } 1274*fa9e4066Sahrens 1275*fa9e4066Sahrens static void 1276*fa9e4066Sahrens split_line(char *str, int cols) 1277*fa9e4066Sahrens { 1278*fa9e4066Sahrens char *ptr; 1279*fa9e4066Sahrens int len; 1280*fa9e4066Sahrens int i; 1281*fa9e4066Sahrens int last_split; 1282*fa9e4066Sahrens char pad[11]; 1283*fa9e4066Sahrens int pad_len; 1284*fa9e4066Sahrens 1285*fa9e4066Sahrens len = strlen(str); 1286*fa9e4066Sahrens ptr = str; 1287*fa9e4066Sahrens (void) strcpy(pad, ""); 1288*fa9e4066Sahrens pad_len = 0; 1289*fa9e4066Sahrens 1290*fa9e4066Sahrens ptr = str; 1291*fa9e4066Sahrens last_split = 0; 1292*fa9e4066Sahrens for (i = 0; i != len; i++) { 1293*fa9e4066Sahrens if ((i + pad_len + 4) >= cols) { 1294*fa9e4066Sahrens (void) printf("%s%.*s\n", pad, last_split, ptr); 1295*fa9e4066Sahrens ptr = &ptr[last_split]; 1296*fa9e4066Sahrens len = strlen(ptr); 1297*fa9e4066Sahrens i = 0; 1298*fa9e4066Sahrens pad_len = 4; 1299*fa9e4066Sahrens (void) strcpy(pad, " "); 1300*fa9e4066Sahrens } else { 1301*fa9e4066Sahrens if (ptr[i] == '/' || ptr[i] == ':') { 1302*fa9e4066Sahrens last_split = i; 1303*fa9e4066Sahrens } 1304*fa9e4066Sahrens } 1305*fa9e4066Sahrens } 1306*fa9e4066Sahrens if (i == len) { 1307*fa9e4066Sahrens (void) printf("%s%s\n", pad, ptr); 1308*fa9e4066Sahrens } 1309*fa9e4066Sahrens } 1310*fa9e4066Sahrens 1311*fa9e4066Sahrens static void 1312*fa9e4066Sahrens ace_printacl(acl_t *aclp, int cols) 1313*fa9e4066Sahrens { 1314*fa9e4066Sahrens int slot = 0; 1315*fa9e4066Sahrens char *token; 1316*fa9e4066Sahrens char *acltext; 1317*fa9e4066Sahrens 1318*fa9e4066Sahrens acltext = acl_totext(aclp); 1319*fa9e4066Sahrens 1320*fa9e4066Sahrens if (acltext == NULL) 1321*fa9e4066Sahrens return; 1322*fa9e4066Sahrens 1323*fa9e4066Sahrens token = strtok(acltext, ","); 1324*fa9e4066Sahrens if (token == NULL) { 1325*fa9e4066Sahrens free(acltext); 1326*fa9e4066Sahrens return; 1327*fa9e4066Sahrens } 1328*fa9e4066Sahrens 1329*fa9e4066Sahrens do { 1330*fa9e4066Sahrens (void) printf(" %d:", slot++); 1331*fa9e4066Sahrens split_line(token, cols - 5); 1332*fa9e4066Sahrens } while (token = strtok(NULL, ",")); 1333*fa9e4066Sahrens free(acltext); 1334*fa9e4066Sahrens } 1335*fa9e4066Sahrens 1336*fa9e4066Sahrens /* 1337*fa9e4066Sahrens * pretty print an ACL. 1338*fa9e4066Sahrens * For aclent_t ACL's the format is 1339*fa9e4066Sahrens * similar to the old format used by getfacl, 1340*fa9e4066Sahrens * with the addition of adding a "slot" number 1341*fa9e4066Sahrens * before each entry. 1342*fa9e4066Sahrens * 1343*fa9e4066Sahrens * for ace_t ACL's the cols variable will break up 1344*fa9e4066Sahrens * the long lines into multiple lines and will also 1345*fa9e4066Sahrens * print a "slot" number. 1346*fa9e4066Sahrens */ 1347*fa9e4066Sahrens void 1348*fa9e4066Sahrens acl_printacl(acl_t *aclp, int cols) 1349*fa9e4066Sahrens { 1350*fa9e4066Sahrens 1351*fa9e4066Sahrens switch (aclp->acl_type) { 1352*fa9e4066Sahrens case ACLENT_T: 1353*fa9e4066Sahrens aclent_printacl(aclp); 1354*fa9e4066Sahrens break; 1355*fa9e4066Sahrens case ACE_T: 1356*fa9e4066Sahrens ace_printacl(aclp, cols); 1357*fa9e4066Sahrens break; 1358*fa9e4066Sahrens } 1359*fa9e4066Sahrens } 1360*fa9e4066Sahrens 1361*fa9e4066Sahrens 1362*fa9e4066Sahrens /* 1363*fa9e4066Sahrens * return text for an ACL error. 1364*fa9e4066Sahrens */ 1365*fa9e4066Sahrens char * 1366*fa9e4066Sahrens acl_strerror(int errnum) 1367*fa9e4066Sahrens { 1368*fa9e4066Sahrens switch (errnum) { 1369*fa9e4066Sahrens case EACL_GRP_ERROR: 1370*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1371*fa9e4066Sahrens "There is more than one user group owner entry")); 1372*fa9e4066Sahrens case EACL_USER_ERROR: 1373*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1374*fa9e4066Sahrens "There is more than one user owner entry")); 1375*fa9e4066Sahrens case EACL_OTHER_ERROR: 1376*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1377*fa9e4066Sahrens "There is more than one other entry")); 1378*fa9e4066Sahrens case EACL_CLASS_ERROR: 1379*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1380*fa9e4066Sahrens "There is more than one mask entry")); 1381*fa9e4066Sahrens case EACL_DUPLICATE_ERROR: 1382*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1383*fa9e4066Sahrens "Duplicate user or group entries")); 1384*fa9e4066Sahrens case EACL_MISS_ERROR: 1385*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1386*fa9e4066Sahrens "Missing user/group owner, other, mask entry")); 1387*fa9e4066Sahrens case EACL_MEM_ERROR: 1388*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1389*fa9e4066Sahrens "Memory error")); 1390*fa9e4066Sahrens case EACL_ENTRY_ERROR: 1391*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1392*fa9e4066Sahrens "Unrecognized entry type")); 1393*fa9e4066Sahrens case EACL_INHERIT_ERROR: 1394*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1395*fa9e4066Sahrens "Invalid inheritance flags")); 1396*fa9e4066Sahrens case EACL_FLAGS_ERROR: 1397*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1398*fa9e4066Sahrens "Unrecognized entry flags")); 1399*fa9e4066Sahrens case EACL_PERM_MASK_ERROR: 1400*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1401*fa9e4066Sahrens "Invalid ACL permissions")); 1402*fa9e4066Sahrens case EACL_COUNT_ERROR: 1403*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1404*fa9e4066Sahrens "Invalid ACL count")); 1405*fa9e4066Sahrens case EACL_INVALID_SLOT: 1406*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1407*fa9e4066Sahrens "Invalid ACL entry number specified")); 1408*fa9e4066Sahrens case EACL_NO_ACL_ENTRY: 1409*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1410*fa9e4066Sahrens "ACL entry doesn't exist")); 1411*fa9e4066Sahrens case EACL_DIFF_TYPE: 1412*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1413*fa9e4066Sahrens "ACL type's are different")); 1414*fa9e4066Sahrens case EACL_INVALID_USER_GROUP: 1415*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, "Invalid user or group")); 1416*fa9e4066Sahrens case EACL_INVALID_STR: 1417*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, "ACL string is invalid")); 1418*fa9e4066Sahrens case EACL_FIELD_NOT_BLANK: 1419*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, "Field expected to be blank")); 1420*fa9e4066Sahrens case EACL_INVALID_ACCESS_TYPE: 1421*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, "Invalid access type")); 1422*fa9e4066Sahrens case EACL_UNKNOWN_DATA: 1423*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, "Unrecognized entry")); 1424*fa9e4066Sahrens case EACL_MISSING_FIELDS: 1425*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1426*fa9e4066Sahrens "ACL specification missing required fields")); 1427*fa9e4066Sahrens case EACL_INHERIT_NOTDIR: 1428*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, 1429*fa9e4066Sahrens "Inheritance flags are only allowed on directories")); 1430*fa9e4066Sahrens case -1: 1431*fa9e4066Sahrens return (strerror(errno)); 1432*fa9e4066Sahrens default: 1433*fa9e4066Sahrens errno = EINVAL; 1434*fa9e4066Sahrens return (dgettext(TEXT_DOMAIN, "Unknown error")); 1435*fa9e4066Sahrens } 1436*fa9e4066Sahrens } 1437