17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5ee519a1fSgjelinek * Common Development and Distribution License (the "License"). 6ee519a1fSgjelinek * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 225a5eeccaSmarks * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <grp.h> 307c478bd9Sstevel@tonic-gate #include <pwd.h> 317c478bd9Sstevel@tonic-gate #include <string.h> 327c478bd9Sstevel@tonic-gate #include <limits.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 34fa9e4066Sahrens #include <errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/param.h> 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 375a5eeccaSmarks #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/acl.h> 39fa9e4066Sahrens #include <aclutils.h> 40fa9e4066Sahrens 415a5eeccaSmarks #define ID_STR_MAX 20 /* digits in LONG_MAX */ 425a5eeccaSmarks 435a5eeccaSmarks #define APPENDED_ID_MAX ID_STR_MAX + 1 /* id + colon */ 445a5eeccaSmarks /* 455a5eeccaSmarks * yyinteractive controls whether yyparse should print out 465a5eeccaSmarks * error messages to stderr, and whether or not id's should be 475a5eeccaSmarks * allowed from acl_fromtext(). 485a5eeccaSmarks */ 495a5eeccaSmarks int yyinteractive; 505a5eeccaSmarks acl_t *yyacl; 515a5eeccaSmarks char *yybuf; 52fa9e4066Sahrens 53fa9e4066Sahrens extern acl_t *acl_alloc(enum acl_type); 547c478bd9Sstevel@tonic-gate 5511e32170Shm123892 567c478bd9Sstevel@tonic-gate struct dynaclstr { 577c478bd9Sstevel@tonic-gate size_t bufsize; /* current size of aclexport */ 587c478bd9Sstevel@tonic-gate char *aclexport; 597c478bd9Sstevel@tonic-gate }; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate static char *strappend(char *, char *); 627c478bd9Sstevel@tonic-gate static char *convert_perm(char *, o_mode_t); 637c478bd9Sstevel@tonic-gate static int increase_length(struct dynaclstr *, size_t); 647c478bd9Sstevel@tonic-gate 655a5eeccaSmarks static void 665a5eeccaSmarks aclent_perms(int perm, char *txt_perms) 67fa9e4066Sahrens { 685a5eeccaSmarks if (perm & S_IROTH) 695a5eeccaSmarks txt_perms[0] = 'r'; 705a5eeccaSmarks else 715a5eeccaSmarks txt_perms[0] = '-'; 725a5eeccaSmarks if (perm & S_IWOTH) 735a5eeccaSmarks txt_perms[1] = 'w'; 745a5eeccaSmarks else 755a5eeccaSmarks txt_perms[1] = '-'; 765a5eeccaSmarks if (perm & S_IXOTH) 775a5eeccaSmarks txt_perms[2] = 'x'; 785a5eeccaSmarks else 795a5eeccaSmarks txt_perms[2] = '-'; 805a5eeccaSmarks txt_perms[3] = '\0'; 815a5eeccaSmarks } 82fa9e4066Sahrens 835a5eeccaSmarks static char * 84*45a17f45Sgjelinek pruname(uid_t uid, char *uidp, int noresolve) 855a5eeccaSmarks { 86*45a17f45Sgjelinek struct passwd *passwdp = NULL; 87fa9e4066Sahrens 88*45a17f45Sgjelinek if (noresolve == 0) 895a5eeccaSmarks passwdp = getpwuid(uid); 905a5eeccaSmarks if (passwdp == (struct passwd *)NULL) { 915a5eeccaSmarks /* could not get passwd information: display uid instead */ 925a5eeccaSmarks (void) sprintf(uidp, "%ld", (long)uid); 935a5eeccaSmarks return (uidp); 945a5eeccaSmarks } else 955a5eeccaSmarks return (passwdp->pw_name); 965a5eeccaSmarks } 97fa9e4066Sahrens 985a5eeccaSmarks static char * 99*45a17f45Sgjelinek prgname(gid_t gid, char *gidp, int noresolve) 1005a5eeccaSmarks { 101*45a17f45Sgjelinek struct group *groupp = NULL; 102fa9e4066Sahrens 103*45a17f45Sgjelinek if (noresolve == 0) 1045a5eeccaSmarks groupp = getgrgid(gid); 1055a5eeccaSmarks if (groupp == (struct group *)NULL) { 1065a5eeccaSmarks /* could not get group information: display gid instead */ 1075a5eeccaSmarks (void) sprintf(gidp, "%ld", (long)gid); 1085a5eeccaSmarks return (gidp); 1095a5eeccaSmarks } else 1105a5eeccaSmarks return (groupp->gr_name); 1115a5eeccaSmarks } 1125a5eeccaSmarks static void 1135a5eeccaSmarks aclent_printacl(acl_t *aclp) 1145a5eeccaSmarks { 1155a5eeccaSmarks aclent_t *tp; 1165a5eeccaSmarks int aclcnt; 1175a5eeccaSmarks int mask; 1185a5eeccaSmarks int slot = 0; 1195a5eeccaSmarks char perm[4]; 1205a5eeccaSmarks char uidp[10]; 1215a5eeccaSmarks char gidp[10]; 1225a5eeccaSmarks 1235a5eeccaSmarks /* display ACL: assume it is sorted. */ 1245a5eeccaSmarks aclcnt = aclp->acl_cnt; 1255a5eeccaSmarks for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) { 1265a5eeccaSmarks if (tp->a_type == CLASS_OBJ) 1275a5eeccaSmarks mask = tp->a_perm; 1285a5eeccaSmarks } 1295a5eeccaSmarks aclcnt = aclp->acl_cnt; 1305a5eeccaSmarks for (tp = aclp->acl_aclp; aclcnt--; tp++) { 1315a5eeccaSmarks (void) printf(" %d:", slot++); 1325a5eeccaSmarks switch (tp->a_type) { 1335a5eeccaSmarks case USER: 1345a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1355a5eeccaSmarks (void) printf("user:%s:%s\t\t", 136*45a17f45Sgjelinek pruname(tp->a_id, uidp, 0), perm); 1375a5eeccaSmarks aclent_perms((tp->a_perm & mask), perm); 1385a5eeccaSmarks (void) printf("#effective:%s\n", perm); 1395a5eeccaSmarks break; 1405a5eeccaSmarks case USER_OBJ: 1415a5eeccaSmarks /* no need to display uid */ 1425a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1435a5eeccaSmarks (void) printf("user::%s\n", perm); 1445a5eeccaSmarks break; 1455a5eeccaSmarks case GROUP: 1465a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1475a5eeccaSmarks (void) printf("group:%s:%s\t\t", 148*45a17f45Sgjelinek prgname(tp->a_id, gidp, 0), perm); 1495a5eeccaSmarks aclent_perms(tp->a_perm & mask, perm); 1505a5eeccaSmarks (void) printf("#effective:%s\n", perm); 1515a5eeccaSmarks break; 1525a5eeccaSmarks case GROUP_OBJ: 1535a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1545a5eeccaSmarks (void) printf("group::%s\t\t", perm); 1555a5eeccaSmarks aclent_perms(tp->a_perm & mask, perm); 1565a5eeccaSmarks (void) printf("#effective:%s\n", perm); 1575a5eeccaSmarks break; 1585a5eeccaSmarks case CLASS_OBJ: 1595a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1605a5eeccaSmarks (void) printf("mask:%s\n", perm); 1615a5eeccaSmarks break; 1625a5eeccaSmarks case OTHER_OBJ: 1635a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1645a5eeccaSmarks (void) printf("other:%s\n", perm); 1655a5eeccaSmarks break; 1665a5eeccaSmarks case DEF_USER: 1675a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1685a5eeccaSmarks (void) printf("default:user:%s:%s\n", 169*45a17f45Sgjelinek pruname(tp->a_id, uidp, 0), perm); 1705a5eeccaSmarks break; 1715a5eeccaSmarks case DEF_USER_OBJ: 1725a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1735a5eeccaSmarks (void) printf("default:user::%s\n", perm); 1745a5eeccaSmarks break; 1755a5eeccaSmarks case DEF_GROUP: 1765a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1775a5eeccaSmarks (void) printf("default:group:%s:%s\n", 178*45a17f45Sgjelinek prgname(tp->a_id, gidp, 0), perm); 1795a5eeccaSmarks break; 1805a5eeccaSmarks case DEF_GROUP_OBJ: 1815a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1825a5eeccaSmarks (void) printf("default:group::%s\n", perm); 1835a5eeccaSmarks break; 1845a5eeccaSmarks case DEF_CLASS_OBJ: 1855a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1865a5eeccaSmarks (void) printf("default:mask:%s\n", perm); 1875a5eeccaSmarks break; 1885a5eeccaSmarks case DEF_OTHER_OBJ: 1895a5eeccaSmarks aclent_perms(tp->a_perm, perm); 1905a5eeccaSmarks (void) printf("default:other:%s\n", perm); 1915a5eeccaSmarks break; 1925a5eeccaSmarks default: 1935a5eeccaSmarks (void) fprintf(stderr, 1945a5eeccaSmarks gettext("unrecognized entry\n")); 1955a5eeccaSmarks break; 1965a5eeccaSmarks } 1975a5eeccaSmarks } 1985a5eeccaSmarks } 1995a5eeccaSmarks 2005a5eeccaSmarks static void 2015a5eeccaSmarks split_line(char *str, int cols) 2025a5eeccaSmarks { 2035a5eeccaSmarks char *ptr; 2045a5eeccaSmarks int len; 2055a5eeccaSmarks int i; 2065a5eeccaSmarks int last_split; 2075a5eeccaSmarks char *pad = ""; 2085a5eeccaSmarks int pad_len; 2095a5eeccaSmarks 2105a5eeccaSmarks len = strlen(str); 2115a5eeccaSmarks ptr = str; 2125a5eeccaSmarks pad_len = 0; 2135a5eeccaSmarks 2145a5eeccaSmarks ptr = str; 2155a5eeccaSmarks last_split = 0; 2165a5eeccaSmarks for (i = 0; i != len; i++) { 2175a5eeccaSmarks if ((i + pad_len + 4) >= cols) { 2185a5eeccaSmarks (void) printf("%s%.*s\n", pad, last_split, ptr); 2195a5eeccaSmarks ptr = &ptr[last_split]; 2205a5eeccaSmarks len = strlen(ptr); 2215a5eeccaSmarks i = 0; 2225a5eeccaSmarks pad_len = 4; 2235a5eeccaSmarks pad = " "; 2245a5eeccaSmarks } else { 2255a5eeccaSmarks if (ptr[i] == '/' || ptr[i] == ':') { 2265a5eeccaSmarks last_split = i; 2275a5eeccaSmarks } 2285a5eeccaSmarks } 2295a5eeccaSmarks } 2305a5eeccaSmarks if (i == len) { 2315a5eeccaSmarks (void) printf("%s%s\n", pad, ptr); 2325a5eeccaSmarks } 2335a5eeccaSmarks } 2345a5eeccaSmarks 2355a5eeccaSmarks #define OWNERAT_TXT "owner@" 2365a5eeccaSmarks #define GROUPAT_TXT "group@" 2375a5eeccaSmarks #define EVERYONEAT_TXT "everyone@" 2385a5eeccaSmarks #define GROUP_TXT "group:" 2395a5eeccaSmarks #define USER_TXT "user:" 2405a5eeccaSmarks 2415a5eeccaSmarks char * 242*45a17f45Sgjelinek ace_type_txt(char *buf, char **endp, ace_t *acep, int flags) 2435a5eeccaSmarks { 2445a5eeccaSmarks 2455a5eeccaSmarks char idp[10]; 2465a5eeccaSmarks 2475a5eeccaSmarks if (buf == NULL) 2485a5eeccaSmarks return (NULL); 2495a5eeccaSmarks 2505a5eeccaSmarks switch (acep->a_flags & ACE_TYPE_FLAGS) { 2515a5eeccaSmarks case ACE_OWNER: 2525a5eeccaSmarks strcpy(buf, OWNERAT_TXT); 2535a5eeccaSmarks *endp = buf + sizeof (OWNERAT_TXT) - 1; 2545a5eeccaSmarks break; 2555a5eeccaSmarks 2565a5eeccaSmarks case ACE_GROUP|ACE_IDENTIFIER_GROUP: 2575a5eeccaSmarks strcpy(buf, GROUPAT_TXT); 2585a5eeccaSmarks *endp = buf + sizeof (GROUPAT_TXT) - 1; 2595a5eeccaSmarks break; 2605a5eeccaSmarks 2615a5eeccaSmarks case ACE_IDENTIFIER_GROUP: 2625a5eeccaSmarks strcpy(buf, GROUP_TXT); 263*45a17f45Sgjelinek strcat(buf, prgname(acep->a_who, idp, flags & ACL_NORESOLVE)); 2645a5eeccaSmarks *endp = buf + strlen(buf); 2655a5eeccaSmarks break; 2665a5eeccaSmarks 2675a5eeccaSmarks case ACE_EVERYONE: 2685a5eeccaSmarks strcpy(buf, EVERYONEAT_TXT); 2695a5eeccaSmarks *endp = buf + sizeof (EVERYONEAT_TXT) - 1; 2705a5eeccaSmarks break; 2715a5eeccaSmarks 2725a5eeccaSmarks case 0: 2735a5eeccaSmarks strcpy(buf, USER_TXT); 274*45a17f45Sgjelinek strcat(buf, pruname(acep->a_who, idp, flags & ACL_NORESOLVE)); 2755a5eeccaSmarks *endp = buf + strlen(buf); 2765a5eeccaSmarks break; 2775a5eeccaSmarks } 2785a5eeccaSmarks 2795a5eeccaSmarks return (buf); 2805a5eeccaSmarks } 2815a5eeccaSmarks 2825a5eeccaSmarks #define READ_DATA_TXT "read_data/" 2835a5eeccaSmarks #define WRITE_DATA_TXT "write_data/" 2845a5eeccaSmarks #define EXECUTE_TXT "execute/" 2855a5eeccaSmarks #define READ_XATTR_TXT "read_xattr/" 2865a5eeccaSmarks #define WRITE_XATTR_TXT "write_xattr/" 2875a5eeccaSmarks #define READ_ATTRIBUTES_TXT "read_attributes/" 2885a5eeccaSmarks #define WRITE_ATTRIBUTES_TXT "write_attributes/" 2895a5eeccaSmarks #define DELETE_TXT "delete/" 2905a5eeccaSmarks #define DELETE_CHILD_TXT "delete_child/" 2915a5eeccaSmarks #define WRITE_OWNER_TXT "write_owner/" 2925a5eeccaSmarks #define READ_ACL_TXT "read_acl/" 2935a5eeccaSmarks #define WRITE_ACL_TXT "write_acl/" 2945a5eeccaSmarks #define APPEND_DATA_TXT "append_data/" 2955a5eeccaSmarks #define READ_DIR_TXT "list_directory/read_data/" 2965a5eeccaSmarks #define ADD_DIR_TXT "add_subdirectory/append_data/" 2975a5eeccaSmarks #define ADD_FILE_TXT "add_file/write_data/" 2985a5eeccaSmarks #define SYNCHRONIZE_TXT "synchronize" /* not slash on this one */ 2995a5eeccaSmarks 3005a5eeccaSmarks char * 3015a5eeccaSmarks ace_perm_txt(char *buf, char **endp, uint32_t mask, 3025a5eeccaSmarks uint32_t iflags, int isdir, int flags) 3035a5eeccaSmarks { 3045a5eeccaSmarks char *lend = buf; /* local end */ 3055a5eeccaSmarks 3065a5eeccaSmarks if (buf == NULL) 3075a5eeccaSmarks return (NULL); 3085a5eeccaSmarks 3095a5eeccaSmarks if (flags & ACL_COMPACT_FMT) { 3105a5eeccaSmarks 3115a5eeccaSmarks if (mask & ACE_READ_DATA) 3125a5eeccaSmarks buf[0] = 'r'; 3135a5eeccaSmarks else 3145a5eeccaSmarks buf[0] = '-'; 3155a5eeccaSmarks if (mask & ACE_WRITE_DATA) 3165a5eeccaSmarks buf[1] = 'w'; 3175a5eeccaSmarks else 3185a5eeccaSmarks buf[1] = '-'; 3195a5eeccaSmarks if (mask & ACE_EXECUTE) 3205a5eeccaSmarks buf[2] = 'x'; 3215a5eeccaSmarks else 3225a5eeccaSmarks buf[2] = '-'; 3235a5eeccaSmarks if (mask & ACE_APPEND_DATA) 3245a5eeccaSmarks buf[3] = 'p'; 3255a5eeccaSmarks else 3265a5eeccaSmarks buf[3] = '-'; 3275a5eeccaSmarks if (mask & ACE_DELETE) 3285a5eeccaSmarks buf[4] = 'd'; 3295a5eeccaSmarks else 3305a5eeccaSmarks buf[4] = '-'; 3315a5eeccaSmarks if (mask & ACE_DELETE_CHILD) 3325a5eeccaSmarks buf[5] = 'D'; 3335a5eeccaSmarks else 3345a5eeccaSmarks buf[5] = '-'; 3355a5eeccaSmarks if (mask & ACE_READ_ATTRIBUTES) 3365a5eeccaSmarks buf[6] = 'a'; 3375a5eeccaSmarks else 3385a5eeccaSmarks buf[6] = '-'; 3395a5eeccaSmarks if (mask & ACE_WRITE_ATTRIBUTES) 3405a5eeccaSmarks buf[7] = 'A'; 3415a5eeccaSmarks else 3425a5eeccaSmarks buf[7] = '-'; 3435a5eeccaSmarks if (mask & ACE_READ_NAMED_ATTRS) 3445a5eeccaSmarks buf[8] = 'R'; 3455a5eeccaSmarks else 3465a5eeccaSmarks buf[8] = '-'; 3475a5eeccaSmarks if (mask & ACE_WRITE_NAMED_ATTRS) 3485a5eeccaSmarks buf[9] = 'W'; 3495a5eeccaSmarks else 3505a5eeccaSmarks buf[9] = '-'; 3515a5eeccaSmarks if (mask & ACE_READ_ACL) 3525a5eeccaSmarks buf[10] = 'c'; 3535a5eeccaSmarks else 3545a5eeccaSmarks buf[10] = '-'; 3555a5eeccaSmarks if (mask & ACE_WRITE_ACL) 3565a5eeccaSmarks buf[11] = 'C'; 3575a5eeccaSmarks else 3585a5eeccaSmarks buf[11] = '-'; 3595a5eeccaSmarks if (mask & ACE_WRITE_OWNER) 3605a5eeccaSmarks buf[12] = 'o'; 3615a5eeccaSmarks else 3625a5eeccaSmarks buf[12] = '-'; 3635a5eeccaSmarks if (mask & ACE_SYNCHRONIZE) 3645a5eeccaSmarks buf[13] = 's'; 3655a5eeccaSmarks else 3665a5eeccaSmarks buf[13] = '-'; 3675a5eeccaSmarks buf[14] = '\0'; 3685a5eeccaSmarks *endp = buf + 14; 3695a5eeccaSmarks return (buf); 3705a5eeccaSmarks } else { 3715a5eeccaSmarks /* 3725a5eeccaSmarks * If ACE is a directory, but inheritance indicates its 3735a5eeccaSmarks * for a file then print permissions for file rather than 3745a5eeccaSmarks * dir. 3755a5eeccaSmarks */ 3765a5eeccaSmarks if (isdir) { 3775a5eeccaSmarks if (mask & ACE_LIST_DIRECTORY) { 3785a5eeccaSmarks if (iflags == ACE_FILE_INHERIT_ACE) { 3795a5eeccaSmarks strcpy(lend, READ_DATA_TXT); 3805a5eeccaSmarks lend += sizeof (READ_DATA_TXT) - 1; 3815a5eeccaSmarks } else { 3825a5eeccaSmarks strcpy(lend, READ_DIR_TXT); 3835a5eeccaSmarks lend += sizeof (READ_DIR_TXT) - 1; 3845a5eeccaSmarks } 3855a5eeccaSmarks } 3865a5eeccaSmarks if (mask & ACE_ADD_FILE) { 3875a5eeccaSmarks if (iflags == ACE_FILE_INHERIT_ACE) { 3885a5eeccaSmarks strcpy(lend, WRITE_DATA_TXT); 3895a5eeccaSmarks lend += sizeof (WRITE_DATA_TXT) - 1; 3905a5eeccaSmarks } else { 3915a5eeccaSmarks strcpy(lend, ADD_FILE_TXT); 3925a5eeccaSmarks lend += 3935a5eeccaSmarks sizeof (ADD_FILE_TXT) -1; 3945a5eeccaSmarks } 3955a5eeccaSmarks } 3965a5eeccaSmarks if (mask & ACE_ADD_SUBDIRECTORY) { 3975a5eeccaSmarks if (iflags == ACE_FILE_INHERIT_ACE) { 3985a5eeccaSmarks strcpy(lend, APPEND_DATA_TXT); 3995a5eeccaSmarks lend += sizeof (APPEND_DATA_TXT) - 1; 4005a5eeccaSmarks } else { 4015a5eeccaSmarks strcpy(lend, ADD_DIR_TXT); 4025a5eeccaSmarks lend += sizeof (ADD_DIR_TXT) - 1; 4035a5eeccaSmarks } 4045a5eeccaSmarks } 4055a5eeccaSmarks } else { 4065a5eeccaSmarks if (mask & ACE_READ_DATA) { 4075a5eeccaSmarks strcpy(lend, READ_DATA_TXT); 4085a5eeccaSmarks lend += sizeof (READ_DATA_TXT) - 1; 4095a5eeccaSmarks } 4105a5eeccaSmarks if (mask & ACE_WRITE_DATA) { 4115a5eeccaSmarks strcpy(lend, WRITE_DATA_TXT); 4125a5eeccaSmarks lend += sizeof (WRITE_DATA_TXT) - 1; 4135a5eeccaSmarks } 4145a5eeccaSmarks if (mask & ACE_APPEND_DATA) { 4155a5eeccaSmarks strcpy(lend, APPEND_DATA_TXT); 4165a5eeccaSmarks lend += sizeof (APPEND_DATA_TXT) - 1; 4175a5eeccaSmarks } 4185a5eeccaSmarks } 4195a5eeccaSmarks if (mask & ACE_READ_NAMED_ATTRS) { 4205a5eeccaSmarks strcpy(lend, READ_XATTR_TXT); 4215a5eeccaSmarks lend += sizeof (READ_XATTR_TXT) - 1; 4225a5eeccaSmarks } 4235a5eeccaSmarks if (mask & ACE_WRITE_NAMED_ATTRS) { 4245a5eeccaSmarks strcpy(lend, WRITE_XATTR_TXT); 4255a5eeccaSmarks lend += sizeof (WRITE_XATTR_TXT) - 1; 4265a5eeccaSmarks } 4275a5eeccaSmarks if (mask & ACE_EXECUTE) { 4285a5eeccaSmarks strcpy(lend, EXECUTE_TXT); 4295a5eeccaSmarks lend += sizeof (EXECUTE_TXT) - 1; 4305a5eeccaSmarks } 4315a5eeccaSmarks if (mask & ACE_DELETE_CHILD) { 4325a5eeccaSmarks strcpy(lend, DELETE_CHILD_TXT); 4335a5eeccaSmarks lend += sizeof (DELETE_CHILD_TXT) - 1; 4345a5eeccaSmarks } 4355a5eeccaSmarks if (mask & ACE_READ_ATTRIBUTES) { 4365a5eeccaSmarks strcpy(lend, READ_ATTRIBUTES_TXT); 4375a5eeccaSmarks lend += sizeof (READ_ATTRIBUTES_TXT) - 1; 4385a5eeccaSmarks } 4395a5eeccaSmarks if (mask & ACE_WRITE_ATTRIBUTES) { 4405a5eeccaSmarks strcpy(lend, WRITE_ATTRIBUTES_TXT); 4415a5eeccaSmarks lend += sizeof (WRITE_ATTRIBUTES_TXT) - 1; 4425a5eeccaSmarks } 4435a5eeccaSmarks if (mask & ACE_DELETE) { 4445a5eeccaSmarks strcpy(lend, DELETE_TXT); 4455a5eeccaSmarks lend += sizeof (DELETE_TXT) - 1; 4465a5eeccaSmarks } 4475a5eeccaSmarks if (mask & ACE_READ_ACL) { 4485a5eeccaSmarks strcpy(lend, READ_ACL_TXT); 4495a5eeccaSmarks lend += sizeof (READ_ACL_TXT) - 1; 4505a5eeccaSmarks } 4515a5eeccaSmarks if (mask & ACE_WRITE_ACL) { 4525a5eeccaSmarks strcpy(lend, WRITE_ACL_TXT); 4535a5eeccaSmarks lend += sizeof (WRITE_ACL_TXT) - 1; 4545a5eeccaSmarks } 4555a5eeccaSmarks if (mask & ACE_WRITE_OWNER) { 4565a5eeccaSmarks strcpy(lend, WRITE_OWNER_TXT); 4575a5eeccaSmarks lend += sizeof (WRITE_OWNER_TXT) - 1; 4585a5eeccaSmarks } 4595a5eeccaSmarks if (mask & ACE_SYNCHRONIZE) { 4605a5eeccaSmarks strcpy(lend, SYNCHRONIZE_TXT); 4615a5eeccaSmarks lend += sizeof (SYNCHRONIZE_TXT) - 1; 4625a5eeccaSmarks } 4635a5eeccaSmarks 4645a5eeccaSmarks if (*(lend - 1) == '/') 4655a5eeccaSmarks *--lend = '\0'; 4665a5eeccaSmarks } 4675a5eeccaSmarks 4685a5eeccaSmarks *endp = lend; 4695a5eeccaSmarks return (buf); 4705a5eeccaSmarks } 4715a5eeccaSmarks 4725a5eeccaSmarks #define ALLOW_TXT "allow" 4735a5eeccaSmarks #define DENY_TXT "deny" 4745a5eeccaSmarks #define ALARM_TXT "alarm" 4755a5eeccaSmarks #define AUDIT_TXT "audit" 4765a5eeccaSmarks #define UNKNOWN_TXT "unknown" 4775a5eeccaSmarks char * 4785a5eeccaSmarks ace_access_txt(char *buf, char **endp, int type) 4795a5eeccaSmarks { 4805a5eeccaSmarks 4815a5eeccaSmarks if (buf == NULL) 4825a5eeccaSmarks return (NULL); 4835a5eeccaSmarks 4845a5eeccaSmarks if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 4855a5eeccaSmarks strcpy(buf, ALLOW_TXT); 4865a5eeccaSmarks *endp += sizeof (ALLOW_TXT) - 1; 4875a5eeccaSmarks } else if (type == ACE_ACCESS_DENIED_ACE_TYPE) { 4885a5eeccaSmarks strcpy(buf, DENY_TXT); 4895a5eeccaSmarks *endp += sizeof (DENY_TXT) - 1; 4905a5eeccaSmarks } else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) { 4915a5eeccaSmarks strcpy(buf, AUDIT_TXT); 4925a5eeccaSmarks *endp += sizeof (AUDIT_TXT) - 1; 4935a5eeccaSmarks } else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) { 4945a5eeccaSmarks strcpy(buf, ALARM_TXT); 4955a5eeccaSmarks *endp += sizeof (ALARM_TXT) - 1; 4965a5eeccaSmarks } else { 4975a5eeccaSmarks strcpy(buf, UNKNOWN_TXT); 4985a5eeccaSmarks *endp += sizeof (UNKNOWN_TXT) - 1; 4995a5eeccaSmarks } 5005a5eeccaSmarks 5015a5eeccaSmarks return (buf); 5025a5eeccaSmarks } 5035a5eeccaSmarks 5045a5eeccaSmarks static char * 5055a5eeccaSmarks ace_inherit_txt(char *buf, char **endp, uint32_t iflags, int flags) 5065a5eeccaSmarks { 5075a5eeccaSmarks 5085a5eeccaSmarks char *lend = buf; 5095a5eeccaSmarks 5105a5eeccaSmarks if (buf == NULL) { 5115a5eeccaSmarks return (NULL); 5125a5eeccaSmarks } 5135a5eeccaSmarks 5145a5eeccaSmarks if (flags & ACL_COMPACT_FMT) { 5155a5eeccaSmarks if (iflags & ACE_FILE_INHERIT_ACE) 5165a5eeccaSmarks buf[0] = 'f'; 5175a5eeccaSmarks else 5185a5eeccaSmarks buf[0] = '-'; 5195a5eeccaSmarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) 5205a5eeccaSmarks buf[1] = 'd'; 5215a5eeccaSmarks else 5225a5eeccaSmarks buf[1] = '-'; 5235a5eeccaSmarks if (iflags & ACE_INHERIT_ONLY_ACE) 5245a5eeccaSmarks buf[2] = 'i'; 5255a5eeccaSmarks else 5265a5eeccaSmarks buf[2] = '-'; 5275a5eeccaSmarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) 5285a5eeccaSmarks buf[3] = 'n'; 5295a5eeccaSmarks else 5305a5eeccaSmarks buf[3] = '-'; 5315a5eeccaSmarks if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 5325a5eeccaSmarks buf[4] = 'S'; 5335a5eeccaSmarks else 5345a5eeccaSmarks buf[4] = '-'; 5355a5eeccaSmarks if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) 5365a5eeccaSmarks buf[5] = 'F'; 5375a5eeccaSmarks else 5385a5eeccaSmarks buf[5] = '-'; 5395a5eeccaSmarks buf[6] = '\0'; 5405a5eeccaSmarks *endp = buf + 6; 5415a5eeccaSmarks } else { 5425a5eeccaSmarks if (iflags & ACE_FILE_INHERIT_ACE) { 5435a5eeccaSmarks strcpy(lend, "file_inherit/"); 5445a5eeccaSmarks lend += sizeof ("file_inherit/") - 1; 5455a5eeccaSmarks } 5465a5eeccaSmarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) { 5475a5eeccaSmarks strcpy(lend, "dir_inherit/"); 5485a5eeccaSmarks lend += sizeof ("dir_inherit/") - 1; 5495a5eeccaSmarks } 5505a5eeccaSmarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) { 5515a5eeccaSmarks strcpy(lend, "no_propagate/"); 5525a5eeccaSmarks lend += sizeof ("no_propagate/") - 1; 5535a5eeccaSmarks } 5545a5eeccaSmarks if (iflags & ACE_INHERIT_ONLY_ACE) { 5555a5eeccaSmarks strcpy(lend, "inherit_only/"); 5565a5eeccaSmarks lend += sizeof ("inherit_only/") - 1; 5575a5eeccaSmarks } 5585a5eeccaSmarks 5595a5eeccaSmarks if (*(lend - 1) == '/') 5605a5eeccaSmarks *--lend = '\0'; 5615a5eeccaSmarks *endp = lend; 5625a5eeccaSmarks } 5635a5eeccaSmarks 5645a5eeccaSmarks return (buf); 565fa9e4066Sahrens } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * Convert internal acl representation to external representation. 5697c478bd9Sstevel@tonic-gate * 5707c478bd9Sstevel@tonic-gate * The length of a non-owning user name or non-owning group name ie entries 5717c478bd9Sstevel@tonic-gate * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We 5727c478bd9Sstevel@tonic-gate * thus check the length of these entries, and if greater than LOGNAME_MAX, 5737c478bd9Sstevel@tonic-gate * we realloc() via increase_length(). 5747c478bd9Sstevel@tonic-gate * 5757c478bd9Sstevel@tonic-gate * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always 5767c478bd9Sstevel@tonic-gate * adhered to. 5777c478bd9Sstevel@tonic-gate */ 5785a5eeccaSmarks 5795a5eeccaSmarks /* 5805a5eeccaSmarks * acltotext() converts each ACL entry to look like this: 5815a5eeccaSmarks * 5825a5eeccaSmarks * entry_type:uid^gid^name:perms[:id] 5835a5eeccaSmarks * 5845a5eeccaSmarks * The maximum length of entry_type is 14 ("defaultgroup::" and 5855a5eeccaSmarks * "defaultother::") hence ENTRYTYPELEN is set to 14. 5865a5eeccaSmarks * 5875a5eeccaSmarks * The max length of a uid^gid^name entry (in theory) is 8, hence we use, 5885a5eeccaSmarks * however the ID could be a number so we therefore use ID_STR_MAX 5895a5eeccaSmarks * 5905a5eeccaSmarks * The length of a perms entry is 4 to allow for the comma appended to each 5915a5eeccaSmarks * to each acl entry. Hence PERMS is set to 4. 5925a5eeccaSmarks */ 5935a5eeccaSmarks 5945a5eeccaSmarks #define ENTRYTYPELEN 14 5955a5eeccaSmarks #define PERMS 4 5965a5eeccaSmarks #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX) 5975a5eeccaSmarks #define UPDATE_WHERE where = dstr->aclexport + strlen(dstr->aclexport) 5985a5eeccaSmarks 5997c478bd9Sstevel@tonic-gate char * 6005a5eeccaSmarks aclent_acltotext(aclent_t *aclp, int aclcnt, int flags) 6017c478bd9Sstevel@tonic-gate { 6027c478bd9Sstevel@tonic-gate char *aclexport; 6037c478bd9Sstevel@tonic-gate char *where; 604ee519a1fSgjelinek struct group *groupp = NULL; 605ee519a1fSgjelinek struct passwd *passwdp = NULL; 6067c478bd9Sstevel@tonic-gate struct dynaclstr *dstr; 6077c478bd9Sstevel@tonic-gate int i, rtn; 6087c478bd9Sstevel@tonic-gate size_t excess = 0; 6095a5eeccaSmarks char id[20], *idstr; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate if (aclp == NULL) 6127c478bd9Sstevel@tonic-gate return (NULL); 6137c478bd9Sstevel@tonic-gate if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL) 6147c478bd9Sstevel@tonic-gate return (NULL); 6157c478bd9Sstevel@tonic-gate dstr->bufsize = aclcnt * ACL_ENTRY_SIZE; 6167c478bd9Sstevel@tonic-gate if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) { 6177c478bd9Sstevel@tonic-gate free(dstr); 6187c478bd9Sstevel@tonic-gate return (NULL); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate *dstr->aclexport = '\0'; 6217c478bd9Sstevel@tonic-gate where = dstr->aclexport; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate for (i = 0; i < aclcnt; i++, aclp++) { 6247c478bd9Sstevel@tonic-gate switch (aclp->a_type) { 6257c478bd9Sstevel@tonic-gate case DEF_USER_OBJ: 6267c478bd9Sstevel@tonic-gate case USER_OBJ: 6277c478bd9Sstevel@tonic-gate if (aclp->a_type == USER_OBJ) 6287c478bd9Sstevel@tonic-gate where = strappend(where, "user::"); 6297c478bd9Sstevel@tonic-gate else 6307c478bd9Sstevel@tonic-gate where = strappend(where, "defaultuser::"); 6317c478bd9Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6327c478bd9Sstevel@tonic-gate break; 6337c478bd9Sstevel@tonic-gate case DEF_USER: 6347c478bd9Sstevel@tonic-gate case USER: 6357c478bd9Sstevel@tonic-gate if (aclp->a_type == USER) 6367c478bd9Sstevel@tonic-gate where = strappend(where, "user:"); 6377c478bd9Sstevel@tonic-gate else 6387c478bd9Sstevel@tonic-gate where = strappend(where, "defaultuser:"); 639ee519a1fSgjelinek if ((flags & ACL_NORESOLVE) == 0) 6407c478bd9Sstevel@tonic-gate passwdp = getpwuid(aclp->a_id); 6417c478bd9Sstevel@tonic-gate if (passwdp == (struct passwd *)NULL) { 6427c478bd9Sstevel@tonic-gate /* put in uid instead */ 6437c478bd9Sstevel@tonic-gate (void) sprintf(where, "%d", aclp->a_id); 64411e32170Shm123892 UPDATE_WHERE; 6457c478bd9Sstevel@tonic-gate } else { 6467c478bd9Sstevel@tonic-gate excess = strlen(passwdp->pw_name) - LOGNAME_MAX; 6477c478bd9Sstevel@tonic-gate if (excess > 0) { 6487c478bd9Sstevel@tonic-gate rtn = increase_length(dstr, excess); 6497c478bd9Sstevel@tonic-gate if (rtn == 1) { 65011e32170Shm123892 UPDATE_WHERE; 6517c478bd9Sstevel@tonic-gate } else { 6527c478bd9Sstevel@tonic-gate free(dstr->aclexport); 6537c478bd9Sstevel@tonic-gate free(dstr); 6547c478bd9Sstevel@tonic-gate return (NULL); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate where = strappend(where, passwdp->pw_name); 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate where = strappend(where, ":"); 6607c478bd9Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6617c478bd9Sstevel@tonic-gate break; 6627c478bd9Sstevel@tonic-gate case DEF_GROUP_OBJ: 6637c478bd9Sstevel@tonic-gate case GROUP_OBJ: 6647c478bd9Sstevel@tonic-gate if (aclp->a_type == GROUP_OBJ) 6657c478bd9Sstevel@tonic-gate where = strappend(where, "group::"); 6667c478bd9Sstevel@tonic-gate else 6677c478bd9Sstevel@tonic-gate where = strappend(where, "defaultgroup::"); 6687c478bd9Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6697c478bd9Sstevel@tonic-gate break; 6707c478bd9Sstevel@tonic-gate case DEF_GROUP: 6717c478bd9Sstevel@tonic-gate case GROUP: 6727c478bd9Sstevel@tonic-gate if (aclp->a_type == GROUP) 6737c478bd9Sstevel@tonic-gate where = strappend(where, "group:"); 6747c478bd9Sstevel@tonic-gate else 6757c478bd9Sstevel@tonic-gate where = strappend(where, "defaultgroup:"); 676ee519a1fSgjelinek if ((flags & ACL_NORESOLVE) == 0) 6777c478bd9Sstevel@tonic-gate groupp = getgrgid(aclp->a_id); 6787c478bd9Sstevel@tonic-gate if (groupp == (struct group *)NULL) { 6797c478bd9Sstevel@tonic-gate /* put in gid instead */ 6807c478bd9Sstevel@tonic-gate (void) sprintf(where, "%d", aclp->a_id); 68111e32170Shm123892 UPDATE_WHERE; 6827c478bd9Sstevel@tonic-gate } else { 6837c478bd9Sstevel@tonic-gate excess = strlen(groupp->gr_name) - LOGNAME_MAX; 6847c478bd9Sstevel@tonic-gate if (excess > 0) { 6857c478bd9Sstevel@tonic-gate rtn = increase_length(dstr, excess); 6867c478bd9Sstevel@tonic-gate if (rtn == 1) { 68711e32170Shm123892 UPDATE_WHERE; 6887c478bd9Sstevel@tonic-gate } else { 6897c478bd9Sstevel@tonic-gate free(dstr->aclexport); 6907c478bd9Sstevel@tonic-gate free(dstr); 6917c478bd9Sstevel@tonic-gate return (NULL); 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate where = strappend(where, groupp->gr_name); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate where = strappend(where, ":"); 6977c478bd9Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6987c478bd9Sstevel@tonic-gate break; 6997c478bd9Sstevel@tonic-gate case DEF_CLASS_OBJ: 7007c478bd9Sstevel@tonic-gate case CLASS_OBJ: 7017c478bd9Sstevel@tonic-gate if (aclp->a_type == CLASS_OBJ) 7027c478bd9Sstevel@tonic-gate where = strappend(where, "mask:"); 7037c478bd9Sstevel@tonic-gate else 7047c478bd9Sstevel@tonic-gate where = strappend(where, "defaultmask:"); 7057c478bd9Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7067c478bd9Sstevel@tonic-gate break; 7077c478bd9Sstevel@tonic-gate case DEF_OTHER_OBJ: 7087c478bd9Sstevel@tonic-gate case OTHER_OBJ: 7097c478bd9Sstevel@tonic-gate if (aclp->a_type == OTHER_OBJ) 7107c478bd9Sstevel@tonic-gate where = strappend(where, "other:"); 7117c478bd9Sstevel@tonic-gate else 7127c478bd9Sstevel@tonic-gate where = strappend(where, "defaultother:"); 7137c478bd9Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7147c478bd9Sstevel@tonic-gate break; 7157c478bd9Sstevel@tonic-gate default: 7167c478bd9Sstevel@tonic-gate free(dstr->aclexport); 7177c478bd9Sstevel@tonic-gate free(dstr); 7187c478bd9Sstevel@tonic-gate return (NULL); 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate } 7215a5eeccaSmarks 7225a5eeccaSmarks if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) || 7235a5eeccaSmarks (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) || 7245a5eeccaSmarks (aclp->a_type == DEF_GROUP))) { 7255a5eeccaSmarks where = strappend(where, ":"); 7265a5eeccaSmarks id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */ 7275a5eeccaSmarks idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]); 7285a5eeccaSmarks where = strappend(where, idstr); 7295a5eeccaSmarks } 7307c478bd9Sstevel@tonic-gate if (i < aclcnt - 1) 7317c478bd9Sstevel@tonic-gate where = strappend(where, ","); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate aclexport = dstr->aclexport; 7347c478bd9Sstevel@tonic-gate free(dstr); 7357c478bd9Sstevel@tonic-gate return (aclexport); 7365a5eeccaSmarks 7375a5eeccaSmarks 7385a5eeccaSmarks 7395a5eeccaSmarks 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate 7425a5eeccaSmarks char * 7435a5eeccaSmarks acltotext(aclent_t *aclp, int aclcnt) 7447c478bd9Sstevel@tonic-gate { 7455a5eeccaSmarks return (aclent_acltotext(aclp, aclcnt, 0)); 746fa9e4066Sahrens } 747fa9e4066Sahrens 7487c478bd9Sstevel@tonic-gate 749fa9e4066Sahrens aclent_t * 750fa9e4066Sahrens aclfromtext(char *aclstr, int *aclcnt) 751fa9e4066Sahrens { 752fa9e4066Sahrens acl_t *aclp; 753fa9e4066Sahrens aclent_t *aclentp; 754fa9e4066Sahrens int error; 755fa9e4066Sahrens 7565a5eeccaSmarks error = acl_fromtext(aclstr, &aclp); 757fa9e4066Sahrens if (error) 758fa9e4066Sahrens return (NULL); 759fa9e4066Sahrens 760fa9e4066Sahrens aclentp = aclp->acl_aclp; 761fa9e4066Sahrens aclp->acl_aclp = NULL; 762fa9e4066Sahrens *aclcnt = aclp->acl_cnt; 7635a5eeccaSmarks 7645a5eeccaSmarks acl_free(aclp); 765fa9e4066Sahrens return (aclentp); 766fa9e4066Sahrens } 767fa9e4066Sahrens 768fa9e4066Sahrens 7697c478bd9Sstevel@tonic-gate static char * 7707c478bd9Sstevel@tonic-gate strappend(char *where, char *newstr) 7717c478bd9Sstevel@tonic-gate { 7727c478bd9Sstevel@tonic-gate (void) strcat(where, newstr); 7737c478bd9Sstevel@tonic-gate return (where + strlen(newstr)); 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate static char * 7777c478bd9Sstevel@tonic-gate convert_perm(char *where, o_mode_t perm) 7787c478bd9Sstevel@tonic-gate { 7795a5eeccaSmarks if (perm & S_IROTH) 7807c478bd9Sstevel@tonic-gate where = strappend(where, "r"); 7817c478bd9Sstevel@tonic-gate else 7827c478bd9Sstevel@tonic-gate where = strappend(where, "-"); 7835a5eeccaSmarks if (perm & S_IWOTH) 7847c478bd9Sstevel@tonic-gate where = strappend(where, "w"); 7857c478bd9Sstevel@tonic-gate else 7867c478bd9Sstevel@tonic-gate where = strappend(where, "-"); 7875a5eeccaSmarks if (perm & S_IXOTH) 7887c478bd9Sstevel@tonic-gate where = strappend(where, "x"); 7897c478bd9Sstevel@tonic-gate else 7907c478bd9Sstevel@tonic-gate where = strappend(where, "-"); 7917c478bd9Sstevel@tonic-gate /* perm is the last field */ 7927c478bd9Sstevel@tonic-gate return (where); 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* 7967c478bd9Sstevel@tonic-gate * Callers should check the return code as this routine may change the string 7977c478bd9Sstevel@tonic-gate * pointer in dynaclstr. 7987c478bd9Sstevel@tonic-gate */ 7997c478bd9Sstevel@tonic-gate static int 8007c478bd9Sstevel@tonic-gate increase_length(struct dynaclstr *dacl, size_t increase) 8017c478bd9Sstevel@tonic-gate { 8027c478bd9Sstevel@tonic-gate char *tptr; 8037c478bd9Sstevel@tonic-gate size_t newsize; 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate newsize = dacl->bufsize + increase; 8067c478bd9Sstevel@tonic-gate tptr = realloc(dacl->aclexport, newsize); 8077c478bd9Sstevel@tonic-gate if (tptr != NULL) { 8087c478bd9Sstevel@tonic-gate dacl->aclexport = tptr; 8097c478bd9Sstevel@tonic-gate dacl->bufsize = newsize; 8107c478bd9Sstevel@tonic-gate return (1); 8117c478bd9Sstevel@tonic-gate } else 8127c478bd9Sstevel@tonic-gate return (0); 8137c478bd9Sstevel@tonic-gate } 814fa9e4066Sahrens 815fa9e4066Sahrens /* 8165a5eeccaSmarks * ace_acltotext() convert each ace formatted acl to look like this: 817fa9e4066Sahrens * 8185a5eeccaSmarks * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,] 819fa9e4066Sahrens * 820fa9e4066Sahrens * The maximum length of entry_type is 5 ("group") 821fa9e4066Sahrens * 8225a5eeccaSmarks * The max length of a uid^gid^name entry (in theory) is 8, 8235a5eeccaSmarks * however id could be a number so we therefore use ID_STR_MAX 824fa9e4066Sahrens * 825fa9e4066Sahrens * The length of a perms entry is 144 i.e read_data/write_data... 826fa9e4066Sahrens * to each acl entry. 827fa9e4066Sahrens * 828fa9e4066Sahrens * iflags: file_inherit/dir_inherit/inherit_only/no_propagate 829fa9e4066Sahrens * 830fa9e4066Sahrens */ 831fa9e4066Sahrens 832fa9e4066Sahrens #define ACE_ENTRYTYPLEN 6 833fa9e4066Sahrens #define IFLAGS_SIZE 51 8345a5eeccaSmarks #define ACCESS_TYPE_SIZE 7 /* if unknown */ 835fa9e4066Sahrens #define COLON_CNT 3 836fa9e4066Sahrens #define PERMS_LEN 216 8375a5eeccaSmarks #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN +\ 8385a5eeccaSmarks ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX) 839fa9e4066Sahrens 840fa9e4066Sahrens static char * 8415a5eeccaSmarks ace_acltotext(acl_t *aceaclp, int flags) 842fa9e4066Sahrens { 843fa9e4066Sahrens ace_t *aclp = aceaclp->acl_aclp; 844fa9e4066Sahrens int aclcnt = aceaclp->acl_cnt; 845fa9e4066Sahrens char *aclexport; 8465a5eeccaSmarks char *endp; 8475a5eeccaSmarks int i; 8485a5eeccaSmarks char id[ID_STR_MAX], *idstr; 849fa9e4066Sahrens int isdir = (aceaclp->acl_flags & ACL_IS_DIR); 850fa9e4066Sahrens 851fa9e4066Sahrens if (aclp == NULL) 852fa9e4066Sahrens return (NULL); 8535a5eeccaSmarks if ((aclexport = malloc(aclcnt * ACE_ENTRY_SIZE)) == NULL) 854fa9e4066Sahrens return (NULL); 855fa9e4066Sahrens 8565a5eeccaSmarks aclexport[0] = '\0'; 8575a5eeccaSmarks endp = aclexport; 858fa9e4066Sahrens for (i = 0; i < aclcnt; i++, aclp++) { 859fa9e4066Sahrens 860*45a17f45Sgjelinek (void) ace_type_txt(endp, &endp, aclp, flags); 8615a5eeccaSmarks *endp++ = ':'; 8625a5eeccaSmarks *endp = '\0'; 8635a5eeccaSmarks (void) ace_perm_txt(endp, &endp, aclp->a_access_mask, 8645a5eeccaSmarks aclp->a_flags, isdir, flags); 8655a5eeccaSmarks *endp++ = ':'; 8665a5eeccaSmarks *endp = '\0'; 8675a5eeccaSmarks (void) ace_inherit_txt(endp, &endp, aclp->a_flags, flags); 8685a5eeccaSmarks if (flags & ACL_COMPACT_FMT || aclp->a_flags & 8695a5eeccaSmarks (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE | 8705a5eeccaSmarks (ACE_INHERIT_ONLY_ACE | ACE_NO_PROPAGATE_INHERIT_ACE))) { 8715a5eeccaSmarks *endp++ = ':'; 8725a5eeccaSmarks *endp = '\0'; 873fa9e4066Sahrens } 8745a5eeccaSmarks (void) ace_access_txt(endp, &endp, aclp->a_type); 875fa9e4066Sahrens 8765a5eeccaSmarks if ((flags & ACL_APPEND_ID) && 8775a5eeccaSmarks (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) || 8785a5eeccaSmarks ((aclp->a_flags & ACE_TYPE_FLAGS) == 8795a5eeccaSmarks ACE_IDENTIFIER_GROUP))) { 8805a5eeccaSmarks *endp++ = ':'; 8815a5eeccaSmarks *endp = '\0'; 8825a5eeccaSmarks id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */ 8835a5eeccaSmarks idstr = lltostr(aclp->a_who, &id[ID_STR_MAX - 1]); 8845a5eeccaSmarks strcpy(endp, idstr); 8855a5eeccaSmarks endp += strlen(idstr); 8865a5eeccaSmarks } 8875a5eeccaSmarks if (i < aclcnt - 1) { 8885a5eeccaSmarks *endp++ = ','; 8895a5eeccaSmarks *(endp + 1) = '\0'; 890fa9e4066Sahrens } 891fa9e4066Sahrens } 892fa9e4066Sahrens return (aclexport); 893fa9e4066Sahrens } 894fa9e4066Sahrens 8955a5eeccaSmarks char * 8965a5eeccaSmarks acl_totext(acl_t *aclp, int flags) 897fa9e4066Sahrens { 898fa9e4066Sahrens 8995a5eeccaSmarks char *txtp; 900fa9e4066Sahrens 901fa9e4066Sahrens if (aclp == NULL) 902fa9e4066Sahrens return (NULL); 903fa9e4066Sahrens 904fa9e4066Sahrens switch (aclp->acl_type) { 905fa9e4066Sahrens case ACE_T: 9065a5eeccaSmarks txtp = ace_acltotext(aclp, flags); 9075a5eeccaSmarks break; 908fa9e4066Sahrens case ACLENT_T: 9095a5eeccaSmarks txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags); 9105a5eeccaSmarks break; 911fa9e4066Sahrens } 9125a5eeccaSmarks 9135a5eeccaSmarks return (txtp); 914fa9e4066Sahrens } 915fa9e4066Sahrens 916fa9e4066Sahrens int 917fa9e4066Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp) 918fa9e4066Sahrens { 9195a5eeccaSmarks int error; 9205a5eeccaSmarks char *buf; 9215a5eeccaSmarks 9225a5eeccaSmarks buf = malloc(strlen(acltextp) + 2); 9235a5eeccaSmarks if (buf == NULL) 9245a5eeccaSmarks return (EACL_MEM_ERROR); 9255a5eeccaSmarks strcpy(buf, acltextp); 9265a5eeccaSmarks strcat(buf, "\n"); 9275a5eeccaSmarks yybuf = buf; 9285a5eeccaSmarks yyreset(); 9295a5eeccaSmarks error = yyparse(); 9305a5eeccaSmarks free(buf); 9315a5eeccaSmarks 9325a5eeccaSmarks if (yyacl) { 9335a5eeccaSmarks if (error == 0) 9345a5eeccaSmarks *ret_aclp = yyacl; 9355a5eeccaSmarks else { 9365a5eeccaSmarks acl_free(yyacl); 9375a5eeccaSmarks } 9385a5eeccaSmarks yyacl = NULL; 9395a5eeccaSmarks } 9405a5eeccaSmarks return (error); 9415a5eeccaSmarks } 9425a5eeccaSmarks 9435a5eeccaSmarks int 9445a5eeccaSmarks acl_parse(const char *acltextp, acl_t **aclp) 9455a5eeccaSmarks { 946fa9e4066Sahrens int error; 947fa9e4066Sahrens 9485a5eeccaSmarks yyinteractive = 1; 9495a5eeccaSmarks error = acl_fromtext(acltextp, aclp); 9505a5eeccaSmarks yyinteractive = 0; 951fa9e4066Sahrens return (error); 952fa9e4066Sahrens } 9535a5eeccaSmarks 9545a5eeccaSmarks static void 9555a5eeccaSmarks ace_compact_printacl(acl_t *aclp) 9565a5eeccaSmarks { 9575a5eeccaSmarks int cnt; 9585a5eeccaSmarks ace_t *acep; 9595a5eeccaSmarks char *endp; 9605a5eeccaSmarks char buf[ACE_ENTRY_SIZE]; 9615a5eeccaSmarks 9625a5eeccaSmarks for (cnt = 0, acep = aclp->acl_aclp; 9635a5eeccaSmarks cnt != aclp->acl_cnt; cnt++, acep++) { 9645a5eeccaSmarks buf[0] = '\0'; 965*45a17f45Sgjelinek (void) printf(" %14s:", ace_type_txt(buf, &endp, acep, 0)); 9665a5eeccaSmarks (void) printf("%s:", ace_perm_txt(endp, &endp, 9675a5eeccaSmarks acep->a_access_mask, acep->a_flags, 9685a5eeccaSmarks aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT)); 9695a5eeccaSmarks (void) printf("%s:", 9705a5eeccaSmarks ace_inherit_txt(endp, &endp, acep->a_flags, 9715a5eeccaSmarks ACL_COMPACT_FMT)); 9725a5eeccaSmarks (void) printf("%s\n", ace_access_txt(endp, &endp, 9735a5eeccaSmarks acep->a_type)); 9745a5eeccaSmarks } 9755a5eeccaSmarks } 9765a5eeccaSmarks 9775a5eeccaSmarks static void 9785a5eeccaSmarks ace_printacl(acl_t *aclp, int cols, int compact) 9795a5eeccaSmarks { 9805a5eeccaSmarks int slot = 0; 9815a5eeccaSmarks char *token; 9825a5eeccaSmarks char *acltext; 9835a5eeccaSmarks 9845a5eeccaSmarks if (compact) { 9855a5eeccaSmarks ace_compact_printacl(aclp); 9865a5eeccaSmarks return; 9875a5eeccaSmarks } 9885a5eeccaSmarks 9895a5eeccaSmarks acltext = acl_totext(aclp, 0); 9905a5eeccaSmarks 9915a5eeccaSmarks if (acltext == NULL) 9925a5eeccaSmarks return; 9935a5eeccaSmarks 9945a5eeccaSmarks token = strtok(acltext, ","); 9955a5eeccaSmarks if (token == NULL) { 9965a5eeccaSmarks free(acltext); 9975a5eeccaSmarks return; 9985a5eeccaSmarks } 9995a5eeccaSmarks 10005a5eeccaSmarks do { 10015a5eeccaSmarks (void) printf(" %d:", slot++); 10025a5eeccaSmarks split_line(token, cols - 5); 10035a5eeccaSmarks } while (token = strtok(NULL, ",")); 10045a5eeccaSmarks free(acltext); 10055a5eeccaSmarks } 10065a5eeccaSmarks 10075a5eeccaSmarks /* 10085a5eeccaSmarks * pretty print an ACL. 10095a5eeccaSmarks * For aclent_t ACL's the format is 10105a5eeccaSmarks * similar to the old format used by getfacl, 10115a5eeccaSmarks * with the addition of adding a "slot" number 10125a5eeccaSmarks * before each entry. 10135a5eeccaSmarks * 10145a5eeccaSmarks * for ace_t ACL's the cols variable will break up 10155a5eeccaSmarks * the long lines into multiple lines and will also 10165a5eeccaSmarks * print a "slot" number. 10175a5eeccaSmarks */ 10185a5eeccaSmarks void 10195a5eeccaSmarks acl_printacl(acl_t *aclp, int cols, int compact) 10205a5eeccaSmarks { 10215a5eeccaSmarks 10225a5eeccaSmarks switch (aclp->acl_type) { 10235a5eeccaSmarks case ACLENT_T: 10245a5eeccaSmarks aclent_printacl(aclp); 10255a5eeccaSmarks break; 10265a5eeccaSmarks case ACE_T: 10275a5eeccaSmarks ace_printacl(aclp, cols, compact); 10285a5eeccaSmarks break; 10295a5eeccaSmarks } 10305a5eeccaSmarks } 10315a5eeccaSmarks 10325a5eeccaSmarks typedef struct value_table { 10335a5eeccaSmarks char p_letter; /* perm letter such as 'r' */ 10345a5eeccaSmarks uint32_t p_value; /* value for perm when pletter found */ 10355a5eeccaSmarks } value_table_t; 10365a5eeccaSmarks 10375a5eeccaSmarks #define ACE_PERM_COUNT 14 10385a5eeccaSmarks 10395a5eeccaSmarks /* 10405a5eeccaSmarks * The permission tables are layed out in positional order 10415a5eeccaSmarks * a '-' character will indicate a permission at a given 10425a5eeccaSmarks * position is not specified. The '-' is not part of the 10435a5eeccaSmarks * table, but will be checked for in the permission computation 10445a5eeccaSmarks * routine. 10455a5eeccaSmarks */ 10465a5eeccaSmarks value_table_t ace_perm_table[ACE_PERM_COUNT] = { 10475a5eeccaSmarks { 'r', ACE_READ_DATA}, 10485a5eeccaSmarks { 'w', ACE_WRITE_DATA}, 10495a5eeccaSmarks { 'x', ACE_EXECUTE}, 10505a5eeccaSmarks { 'p', ACE_APPEND_DATA}, 10515a5eeccaSmarks { 'd', ACE_DELETE}, 10525a5eeccaSmarks { 'D', ACE_DELETE_CHILD}, 10535a5eeccaSmarks { 'a', ACE_READ_ATTRIBUTES}, 10545a5eeccaSmarks { 'A', ACE_WRITE_ATTRIBUTES}, 10555a5eeccaSmarks { 'R', ACE_READ_NAMED_ATTRS}, 10565a5eeccaSmarks { 'W', ACE_WRITE_NAMED_ATTRS}, 10575a5eeccaSmarks { 'c', ACE_READ_ACL}, 10585a5eeccaSmarks { 'C', ACE_WRITE_ACL}, 10595a5eeccaSmarks { 'o', ACE_WRITE_OWNER}, 10605a5eeccaSmarks { 's', ACE_SYNCHRONIZE} 10615a5eeccaSmarks }; 10625a5eeccaSmarks 10635a5eeccaSmarks #define ACLENT_PERM_COUNT 3 10645a5eeccaSmarks 10655a5eeccaSmarks value_table_t aclent_perm_table[ACLENT_PERM_COUNT] = { 10665a5eeccaSmarks { 'r', S_IROTH}, 10675a5eeccaSmarks { 'w', S_IWOTH}, 10685a5eeccaSmarks { 'x', S_IXOTH} 10695a5eeccaSmarks }; 10705a5eeccaSmarks 10715a5eeccaSmarks #define IFLAG_COUNT 6 10725a5eeccaSmarks value_table_t inherit_table[IFLAG_COUNT] = { 10735a5eeccaSmarks {'f', ACE_FILE_INHERIT_ACE}, 10745a5eeccaSmarks {'d', ACE_DIRECTORY_INHERIT_ACE}, 10755a5eeccaSmarks {'i', ACE_INHERIT_ONLY_ACE}, 10765a5eeccaSmarks {'n', ACE_NO_PROPAGATE_INHERIT_ACE}, 10775a5eeccaSmarks {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 10785a5eeccaSmarks {'F', ACE_FAILED_ACCESS_ACE_FLAG} 10795a5eeccaSmarks }; 10805a5eeccaSmarks 10815a5eeccaSmarks /* 10825a5eeccaSmarks * compute value from a permission table or inheritance table 10835a5eeccaSmarks * based on string passed in. If positional is set then 10845a5eeccaSmarks * string must match order in permtab, otherwise any order 10855a5eeccaSmarks * is allowed. 10865a5eeccaSmarks */ 10875a5eeccaSmarks int 10885a5eeccaSmarks compute_values(value_table_t *permtab, int count, 10895a5eeccaSmarks char *permstr, int positional, uint32_t *mask) 10905a5eeccaSmarks { 10915a5eeccaSmarks uint32_t perm_val = 0; 10925a5eeccaSmarks char *pstr; 10935a5eeccaSmarks int i, found; 10945a5eeccaSmarks 10955a5eeccaSmarks if (count < 0) 10965a5eeccaSmarks return (1); 10975a5eeccaSmarks 10985a5eeccaSmarks if (positional) { 10995a5eeccaSmarks for (i = 0, pstr = permstr; i != count && pstr && 11005a5eeccaSmarks *pstr; i++, pstr++) { 11015a5eeccaSmarks if (*pstr == permtab[i].p_letter) { 11025a5eeccaSmarks perm_val |= permtab[i].p_value; 11035a5eeccaSmarks } else if (*pstr != '-') { 11045a5eeccaSmarks return (1); 11055a5eeccaSmarks } 11065a5eeccaSmarks } 11075a5eeccaSmarks } else { /* random order single letters with no '-' */ 11085a5eeccaSmarks for (pstr = permstr; pstr && *pstr; pstr++) { 11095a5eeccaSmarks for (found = 0, i = 0; i != count; i++) { 11105a5eeccaSmarks if (*pstr == permtab[i].p_letter) { 11115a5eeccaSmarks perm_val |= permtab[i].p_value; 11125a5eeccaSmarks found = 1; 11135a5eeccaSmarks break; 11145a5eeccaSmarks } 11155a5eeccaSmarks } 11165a5eeccaSmarks if (found == 0) 11175a5eeccaSmarks return (1); 11185a5eeccaSmarks } 11195a5eeccaSmarks } 11205a5eeccaSmarks 11215a5eeccaSmarks *mask = perm_val; 11225a5eeccaSmarks return (0); 11235a5eeccaSmarks } 11245a5eeccaSmarks 11255a5eeccaSmarks /* 11265a5eeccaSmarks * compute value for inheritance flags. 11275a5eeccaSmarks */ 11285a5eeccaSmarks int 11295a5eeccaSmarks compute_ace_inherit(char *str, uint32_t *imask) 11305a5eeccaSmarks { 11315a5eeccaSmarks int error; 11325a5eeccaSmarks int positional = 0; 11335a5eeccaSmarks 11345a5eeccaSmarks if (strlen(str) == IFLAG_COUNT) 11355a5eeccaSmarks positional = 1; 11365a5eeccaSmarks 11375a5eeccaSmarks error = compute_values(inherit_table, IFLAG_COUNT, 11385a5eeccaSmarks str, positional, imask); 11395a5eeccaSmarks 11405a5eeccaSmarks if (error) 11415a5eeccaSmarks return (EACL_INHERIT_ERROR); 11425a5eeccaSmarks 11435a5eeccaSmarks return (error); 11445a5eeccaSmarks } 11455a5eeccaSmarks 11465a5eeccaSmarks 11475a5eeccaSmarks /* 11485a5eeccaSmarks * compute value for ACE permissions. 11495a5eeccaSmarks */ 11505a5eeccaSmarks int 11515a5eeccaSmarks compute_ace_perms(char *str, uint32_t *mask) 11525a5eeccaSmarks { 11535a5eeccaSmarks int positional = 0; 11545a5eeccaSmarks int error; 11555a5eeccaSmarks 11565a5eeccaSmarks if (strlen(str) == ACE_PERM_COUNT) 11575a5eeccaSmarks positional = 1; 11585a5eeccaSmarks 11595a5eeccaSmarks error = compute_values(ace_perm_table, ACE_PERM_COUNT, 11605a5eeccaSmarks str, positional, mask); 11615a5eeccaSmarks 11625a5eeccaSmarks if (error && positional) { 11635a5eeccaSmarks /* 11645a5eeccaSmarks * If positional was set, then make sure permissions 11655a5eeccaSmarks * aren't actually valid in non positional case where 11665a5eeccaSmarks * all permissions are specified, just in random order. 11675a5eeccaSmarks */ 11685a5eeccaSmarks error = compute_values(ace_perm_table, 11695a5eeccaSmarks ACE_PERM_COUNT, str, 0, mask); 11705a5eeccaSmarks } 11715a5eeccaSmarks if (error) 11725a5eeccaSmarks error = EACL_PERM_MASK_ERROR; 11735a5eeccaSmarks 11745a5eeccaSmarks return (error); 11755a5eeccaSmarks } 11765a5eeccaSmarks 11775a5eeccaSmarks 11785a5eeccaSmarks 11795a5eeccaSmarks /* 11805a5eeccaSmarks * compute values for aclent permissions. 11815a5eeccaSmarks */ 11825a5eeccaSmarks int 11835a5eeccaSmarks compute_aclent_perms(char *str, o_mode_t *mask) 11845a5eeccaSmarks { 11855a5eeccaSmarks int error; 11865a5eeccaSmarks uint32_t pmask; 11875a5eeccaSmarks 11885a5eeccaSmarks if (strlen(str) != ACLENT_PERM_COUNT) 11895a5eeccaSmarks return (EACL_PERM_MASK_ERROR); 11905a5eeccaSmarks 11915a5eeccaSmarks *mask = 0; 11925a5eeccaSmarks error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT, 11935a5eeccaSmarks str, 1, &pmask); 11945a5eeccaSmarks if (error == 0) { 11955a5eeccaSmarks *mask = (o_mode_t)pmask; 11965a5eeccaSmarks } else 11975a5eeccaSmarks error = EACL_PERM_MASK_ERROR; 11985a5eeccaSmarks return (error); 11995a5eeccaSmarks } 12005a5eeccaSmarks 12015a5eeccaSmarks /* 12025a5eeccaSmarks * determine ACE permissions. 12035a5eeccaSmarks */ 12045a5eeccaSmarks int 12055a5eeccaSmarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask) 12065a5eeccaSmarks { 12075a5eeccaSmarks int error; 12085a5eeccaSmarks 12095a5eeccaSmarks if (aclperm->perm_style == PERM_TYPE_EMPTY) { 12105a5eeccaSmarks *mask = 0; 12115a5eeccaSmarks return (0); 12125a5eeccaSmarks } 12135a5eeccaSmarks 12145a5eeccaSmarks if (aclperm->perm_style == PERM_TYPE_ACE) { 12155a5eeccaSmarks *mask = aclperm->perm_val; 12165a5eeccaSmarks return (0); 12175a5eeccaSmarks } 12185a5eeccaSmarks 12195a5eeccaSmarks error = compute_ace_perms(aclperm->perm_str, mask); 12205a5eeccaSmarks if (error) { 12215a5eeccaSmarks acl_error(gettext("Invalid permission(s) '%s' specified\n"), 12225a5eeccaSmarks aclperm->perm_str); 12235a5eeccaSmarks return (EACL_PERM_MASK_ERROR); 12245a5eeccaSmarks } 12255a5eeccaSmarks 12265a5eeccaSmarks return (0); 12275a5eeccaSmarks } 1228