10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1507Sgjelinek * Common Development and Distribution License (the "License"). 6*1507Sgjelinek * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 221420Smarks * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate /*LINTLIBRARY*/ 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <grp.h> 300Sstevel@tonic-gate #include <pwd.h> 310Sstevel@tonic-gate #include <string.h> 320Sstevel@tonic-gate #include <limits.h> 330Sstevel@tonic-gate #include <stdlib.h> 34789Sahrens #include <errno.h> 350Sstevel@tonic-gate #include <sys/param.h> 360Sstevel@tonic-gate #include <sys/types.h> 371420Smarks #include <sys/stat.h> 380Sstevel@tonic-gate #include <sys/acl.h> 39789Sahrens #include <aclutils.h> 401420Smarks 411420Smarks #define ID_STR_MAX 20 /* digits in LONG_MAX */ 42789Sahrens 431420Smarks #define APPENDED_ID_MAX ID_STR_MAX + 1 /* id + colon */ 441420Smarks /* 451420Smarks * yyinteractive controls whether yyparse should print out 461420Smarks * error messages to stderr, and whether or not id's should be 471420Smarks * allowed from acl_fromtext(). 481420Smarks */ 491420Smarks int yyinteractive; 501420Smarks acl_t *yyacl; 511420Smarks char *yybuf; 52789Sahrens 53789Sahrens extern acl_t *acl_alloc(enum acl_type); 540Sstevel@tonic-gate 55922Shm123892 560Sstevel@tonic-gate struct dynaclstr { 570Sstevel@tonic-gate size_t bufsize; /* current size of aclexport */ 580Sstevel@tonic-gate char *aclexport; 590Sstevel@tonic-gate }; 600Sstevel@tonic-gate 610Sstevel@tonic-gate static char *strappend(char *, char *); 620Sstevel@tonic-gate static char *convert_perm(char *, o_mode_t); 630Sstevel@tonic-gate static int increase_length(struct dynaclstr *, size_t); 640Sstevel@tonic-gate 651420Smarks static void 661420Smarks aclent_perms(int perm, char *txt_perms) 671420Smarks { 681420Smarks if (perm & S_IROTH) 691420Smarks txt_perms[0] = 'r'; 701420Smarks else 711420Smarks txt_perms[0] = '-'; 721420Smarks if (perm & S_IWOTH) 731420Smarks txt_perms[1] = 'w'; 741420Smarks else 751420Smarks txt_perms[1] = '-'; 761420Smarks if (perm & S_IXOTH) 771420Smarks txt_perms[2] = 'x'; 781420Smarks else 791420Smarks txt_perms[2] = '-'; 801420Smarks txt_perms[3] = '\0'; 811420Smarks } 821420Smarks 831420Smarks static char * 841420Smarks pruname(uid_t uid, char *uidp) 851420Smarks { 861420Smarks struct passwd *passwdp; 871420Smarks 881420Smarks passwdp = getpwuid(uid); 891420Smarks if (passwdp == (struct passwd *)NULL) { 901420Smarks /* could not get passwd information: display uid instead */ 911420Smarks (void) sprintf(uidp, "%ld", (long)uid); 921420Smarks return (uidp); 931420Smarks } else 941420Smarks return (passwdp->pw_name); 951420Smarks } 961420Smarks 971420Smarks static char * 981420Smarks prgname(gid_t gid, char *gidp) 991420Smarks { 1001420Smarks struct group *groupp; 1011420Smarks 1021420Smarks groupp = getgrgid(gid); 1031420Smarks if (groupp == (struct group *)NULL) { 1041420Smarks /* could not get group information: display gid instead */ 1051420Smarks (void) sprintf(gidp, "%ld", (long)gid); 1061420Smarks return (gidp); 1071420Smarks } else 1081420Smarks return (groupp->gr_name); 1091420Smarks } 1101420Smarks static void 1111420Smarks aclent_printacl(acl_t *aclp) 112789Sahrens { 1131420Smarks aclent_t *tp; 1141420Smarks int aclcnt; 1151420Smarks int mask; 1161420Smarks int slot = 0; 1171420Smarks char perm[4]; 1181420Smarks char uidp[10]; 1191420Smarks char gidp[10]; 1201420Smarks 1211420Smarks /* display ACL: assume it is sorted. */ 1221420Smarks aclcnt = aclp->acl_cnt; 1231420Smarks for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) { 1241420Smarks if (tp->a_type == CLASS_OBJ) 1251420Smarks mask = tp->a_perm; 1261420Smarks } 1271420Smarks aclcnt = aclp->acl_cnt; 1281420Smarks for (tp = aclp->acl_aclp; aclcnt--; tp++) { 1291420Smarks (void) printf(" %d:", slot++); 1301420Smarks switch (tp->a_type) { 1311420Smarks case USER: 1321420Smarks aclent_perms(tp->a_perm, perm); 1331420Smarks (void) printf("user:%s:%s\t\t", 1341420Smarks pruname(tp->a_id, uidp), perm); 1351420Smarks aclent_perms((tp->a_perm & mask), perm); 1361420Smarks (void) printf("#effective:%s\n", perm); 1371420Smarks break; 1381420Smarks case USER_OBJ: 1391420Smarks /* no need to display uid */ 1401420Smarks aclent_perms(tp->a_perm, perm); 1411420Smarks (void) printf("user::%s\n", perm); 1421420Smarks break; 1431420Smarks case GROUP: 1441420Smarks aclent_perms(tp->a_perm, perm); 1451420Smarks (void) printf("group:%s:%s\t\t", 1461420Smarks prgname(tp->a_id, gidp), perm); 1471420Smarks aclent_perms(tp->a_perm & mask, perm); 1481420Smarks (void) printf("#effective:%s\n", perm); 1491420Smarks break; 1501420Smarks case GROUP_OBJ: 1511420Smarks aclent_perms(tp->a_perm, perm); 1521420Smarks (void) printf("group::%s\t\t", perm); 1531420Smarks aclent_perms(tp->a_perm & mask, perm); 1541420Smarks (void) printf("#effective:%s\n", perm); 1551420Smarks break; 1561420Smarks case CLASS_OBJ: 1571420Smarks aclent_perms(tp->a_perm, perm); 1581420Smarks (void) printf("mask:%s\n", perm); 1591420Smarks break; 1601420Smarks case OTHER_OBJ: 1611420Smarks aclent_perms(tp->a_perm, perm); 1621420Smarks (void) printf("other:%s\n", perm); 1631420Smarks break; 1641420Smarks case DEF_USER: 1651420Smarks aclent_perms(tp->a_perm, perm); 1661420Smarks (void) printf("default:user:%s:%s\n", 1671420Smarks pruname(tp->a_id, uidp), perm); 1681420Smarks break; 1691420Smarks case DEF_USER_OBJ: 1701420Smarks aclent_perms(tp->a_perm, perm); 1711420Smarks (void) printf("default:user::%s\n", perm); 1721420Smarks break; 1731420Smarks case DEF_GROUP: 1741420Smarks aclent_perms(tp->a_perm, perm); 1751420Smarks (void) printf("default:group:%s:%s\n", 1761420Smarks prgname(tp->a_id, gidp), perm); 1771420Smarks break; 1781420Smarks case DEF_GROUP_OBJ: 1791420Smarks aclent_perms(tp->a_perm, perm); 1801420Smarks (void) printf("default:group::%s\n", perm); 1811420Smarks break; 1821420Smarks case DEF_CLASS_OBJ: 1831420Smarks aclent_perms(tp->a_perm, perm); 1841420Smarks (void) printf("default:mask:%s\n", perm); 1851420Smarks break; 1861420Smarks case DEF_OTHER_OBJ: 1871420Smarks aclent_perms(tp->a_perm, perm); 1881420Smarks (void) printf("default:other:%s\n", perm); 1891420Smarks break; 1901420Smarks default: 1911420Smarks (void) fprintf(stderr, 1921420Smarks gettext("unrecognized entry\n")); 1931420Smarks break; 1941420Smarks } 1951420Smarks } 1961420Smarks } 1971420Smarks 1981420Smarks static void 1991420Smarks split_line(char *str, int cols) 2001420Smarks { 2011420Smarks char *ptr; 2021420Smarks int len; 2031420Smarks int i; 2041420Smarks int last_split; 2051420Smarks char *pad = ""; 2061420Smarks int pad_len; 2071420Smarks 2081420Smarks len = strlen(str); 2091420Smarks ptr = str; 2101420Smarks pad_len = 0; 2111420Smarks 2121420Smarks ptr = str; 2131420Smarks last_split = 0; 2141420Smarks for (i = 0; i != len; i++) { 2151420Smarks if ((i + pad_len + 4) >= cols) { 2161420Smarks (void) printf("%s%.*s\n", pad, last_split, ptr); 2171420Smarks ptr = &ptr[last_split]; 2181420Smarks len = strlen(ptr); 2191420Smarks i = 0; 2201420Smarks pad_len = 4; 2211420Smarks pad = " "; 2221420Smarks } else { 2231420Smarks if (ptr[i] == '/' || ptr[i] == ':') { 2241420Smarks last_split = i; 2251420Smarks } 2261420Smarks } 2271420Smarks } 2281420Smarks if (i == len) { 2291420Smarks (void) printf("%s%s\n", pad, ptr); 2301420Smarks } 2311420Smarks } 2321420Smarks 2331420Smarks #define OWNERAT_TXT "owner@" 2341420Smarks #define GROUPAT_TXT "group@" 2351420Smarks #define EVERYONEAT_TXT "everyone@" 2361420Smarks #define GROUP_TXT "group:" 2371420Smarks #define USER_TXT "user:" 2381420Smarks 2391420Smarks char * 2401420Smarks ace_type_txt(char *buf, char **endp, ace_t *acep) 2411420Smarks { 2421420Smarks 2431420Smarks char idp[10]; 2441420Smarks 2451420Smarks if (buf == NULL) 2461420Smarks return (NULL); 2471420Smarks 2481420Smarks switch (acep->a_flags & ACE_TYPE_FLAGS) { 2491420Smarks case ACE_OWNER: 2501420Smarks strcpy(buf, OWNERAT_TXT); 2511420Smarks *endp = buf + sizeof (OWNERAT_TXT) - 1; 2521420Smarks break; 2531420Smarks 2541420Smarks case ACE_GROUP|ACE_IDENTIFIER_GROUP: 2551420Smarks strcpy(buf, GROUPAT_TXT); 2561420Smarks *endp = buf + sizeof (GROUPAT_TXT) - 1; 2571420Smarks break; 2581420Smarks 2591420Smarks case ACE_IDENTIFIER_GROUP: 2601420Smarks strcpy(buf, GROUP_TXT); 2611420Smarks strcat(buf, prgname(acep->a_who, idp)); 2621420Smarks *endp = buf + strlen(buf); 2631420Smarks break; 2641420Smarks 2651420Smarks case ACE_EVERYONE: 2661420Smarks strcpy(buf, EVERYONEAT_TXT); 2671420Smarks *endp = buf + sizeof (EVERYONEAT_TXT) - 1; 2681420Smarks break; 2691420Smarks 2701420Smarks case 0: 2711420Smarks strcpy(buf, USER_TXT); 2721420Smarks strcat(buf, pruname(acep->a_who, idp)); 2731420Smarks *endp = buf + strlen(buf); 2741420Smarks break; 2751420Smarks } 2761420Smarks 2771420Smarks return (buf); 2781420Smarks } 2791420Smarks 2801420Smarks #define READ_DATA_TXT "read_data/" 2811420Smarks #define WRITE_DATA_TXT "write_data/" 2821420Smarks #define EXECUTE_TXT "execute/" 2831420Smarks #define READ_XATTR_TXT "read_xattr/" 2841420Smarks #define WRITE_XATTR_TXT "write_xattr/" 2851420Smarks #define READ_ATTRIBUTES_TXT "read_attributes/" 2861420Smarks #define WRITE_ATTRIBUTES_TXT "write_attributes/" 2871420Smarks #define DELETE_TXT "delete/" 2881420Smarks #define DELETE_CHILD_TXT "delete_child/" 2891420Smarks #define WRITE_OWNER_TXT "write_owner/" 2901420Smarks #define READ_ACL_TXT "read_acl/" 2911420Smarks #define WRITE_ACL_TXT "write_acl/" 2921420Smarks #define APPEND_DATA_TXT "append_data/" 2931420Smarks #define READ_DIR_TXT "list_directory/read_data/" 2941420Smarks #define ADD_DIR_TXT "add_subdirectory/append_data/" 2951420Smarks #define ADD_FILE_TXT "add_file/write_data/" 2961420Smarks #define SYNCHRONIZE_TXT "synchronize" /* not slash on this one */ 2971420Smarks 2981420Smarks char * 2991420Smarks ace_perm_txt(char *buf, char **endp, uint32_t mask, 3001420Smarks uint32_t iflags, int isdir, int flags) 3011420Smarks { 3021420Smarks char *lend = buf; /* local end */ 3031420Smarks 3041420Smarks if (buf == NULL) 3051420Smarks return (NULL); 3061420Smarks 3071420Smarks if (flags & ACL_COMPACT_FMT) { 308789Sahrens 3091420Smarks if (mask & ACE_READ_DATA) 3101420Smarks buf[0] = 'r'; 3111420Smarks else 3121420Smarks buf[0] = '-'; 3131420Smarks if (mask & ACE_WRITE_DATA) 3141420Smarks buf[1] = 'w'; 3151420Smarks else 3161420Smarks buf[1] = '-'; 3171420Smarks if (mask & ACE_EXECUTE) 3181420Smarks buf[2] = 'x'; 3191420Smarks else 3201420Smarks buf[2] = '-'; 3211420Smarks if (mask & ACE_APPEND_DATA) 3221420Smarks buf[3] = 'p'; 3231420Smarks else 3241420Smarks buf[3] = '-'; 3251420Smarks if (mask & ACE_DELETE) 3261420Smarks buf[4] = 'd'; 3271420Smarks else 3281420Smarks buf[4] = '-'; 3291420Smarks if (mask & ACE_DELETE_CHILD) 3301420Smarks buf[5] = 'D'; 3311420Smarks else 3321420Smarks buf[5] = '-'; 3331420Smarks if (mask & ACE_READ_ATTRIBUTES) 3341420Smarks buf[6] = 'a'; 3351420Smarks else 3361420Smarks buf[6] = '-'; 3371420Smarks if (mask & ACE_WRITE_ATTRIBUTES) 3381420Smarks buf[7] = 'A'; 3391420Smarks else 3401420Smarks buf[7] = '-'; 3411420Smarks if (mask & ACE_READ_NAMED_ATTRS) 3421420Smarks buf[8] = 'R'; 3431420Smarks else 3441420Smarks buf[8] = '-'; 3451420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) 3461420Smarks buf[9] = 'W'; 3471420Smarks else 3481420Smarks buf[9] = '-'; 3491420Smarks if (mask & ACE_READ_ACL) 3501420Smarks buf[10] = 'c'; 3511420Smarks else 3521420Smarks buf[10] = '-'; 3531420Smarks if (mask & ACE_WRITE_ACL) 3541420Smarks buf[11] = 'C'; 3551420Smarks else 3561420Smarks buf[11] = '-'; 3571420Smarks if (mask & ACE_WRITE_OWNER) 3581420Smarks buf[12] = 'o'; 3591420Smarks else 3601420Smarks buf[12] = '-'; 3611420Smarks if (mask & ACE_SYNCHRONIZE) 3621420Smarks buf[13] = 's'; 3631420Smarks else 3641420Smarks buf[13] = '-'; 3651420Smarks buf[14] = '\0'; 3661420Smarks *endp = buf + 14; 3671420Smarks return (buf); 3681420Smarks } else { 3691420Smarks /* 3701420Smarks * If ACE is a directory, but inheritance indicates its 3711420Smarks * for a file then print permissions for file rather than 3721420Smarks * dir. 3731420Smarks */ 3741420Smarks if (isdir) { 3751420Smarks if (mask & ACE_LIST_DIRECTORY) { 3761420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 3771420Smarks strcpy(lend, READ_DATA_TXT); 3781420Smarks lend += sizeof (READ_DATA_TXT) - 1; 3791420Smarks } else { 3801420Smarks strcpy(lend, READ_DIR_TXT); 3811420Smarks lend += sizeof (READ_DIR_TXT) - 1; 3821420Smarks } 3831420Smarks } 3841420Smarks if (mask & ACE_ADD_FILE) { 3851420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 3861420Smarks strcpy(lend, WRITE_DATA_TXT); 3871420Smarks lend += sizeof (WRITE_DATA_TXT) - 1; 3881420Smarks } else { 3891420Smarks strcpy(lend, ADD_FILE_TXT); 3901420Smarks lend += 3911420Smarks sizeof (ADD_FILE_TXT) -1; 3921420Smarks } 3931420Smarks } 3941420Smarks if (mask & ACE_ADD_SUBDIRECTORY) { 3951420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 3961420Smarks strcpy(lend, APPEND_DATA_TXT); 3971420Smarks lend += sizeof (APPEND_DATA_TXT) - 1; 3981420Smarks } else { 3991420Smarks strcpy(lend, ADD_DIR_TXT); 4001420Smarks lend += sizeof (ADD_DIR_TXT) - 1; 4011420Smarks } 4021420Smarks } 4031420Smarks } else { 4041420Smarks if (mask & ACE_READ_DATA) { 4051420Smarks strcpy(lend, READ_DATA_TXT); 4061420Smarks lend += sizeof (READ_DATA_TXT) - 1; 4071420Smarks } 4081420Smarks if (mask & ACE_WRITE_DATA) { 4091420Smarks strcpy(lend, WRITE_DATA_TXT); 4101420Smarks lend += sizeof (WRITE_DATA_TXT) - 1; 4111420Smarks } 4121420Smarks if (mask & ACE_APPEND_DATA) { 4131420Smarks strcpy(lend, APPEND_DATA_TXT); 4141420Smarks lend += sizeof (APPEND_DATA_TXT) - 1; 4151420Smarks } 4161420Smarks } 4171420Smarks if (mask & ACE_READ_NAMED_ATTRS) { 4181420Smarks strcpy(lend, READ_XATTR_TXT); 4191420Smarks lend += sizeof (READ_XATTR_TXT) - 1; 4201420Smarks } 4211420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) { 4221420Smarks strcpy(lend, WRITE_XATTR_TXT); 4231420Smarks lend += sizeof (WRITE_XATTR_TXT) - 1; 4241420Smarks } 4251420Smarks if (mask & ACE_EXECUTE) { 4261420Smarks strcpy(lend, EXECUTE_TXT); 4271420Smarks lend += sizeof (EXECUTE_TXT) - 1; 4281420Smarks } 4291420Smarks if (mask & ACE_DELETE_CHILD) { 4301420Smarks strcpy(lend, DELETE_CHILD_TXT); 4311420Smarks lend += sizeof (DELETE_CHILD_TXT) - 1; 4321420Smarks } 4331420Smarks if (mask & ACE_READ_ATTRIBUTES) { 4341420Smarks strcpy(lend, READ_ATTRIBUTES_TXT); 4351420Smarks lend += sizeof (READ_ATTRIBUTES_TXT) - 1; 4361420Smarks } 4371420Smarks if (mask & ACE_WRITE_ATTRIBUTES) { 4381420Smarks strcpy(lend, WRITE_ATTRIBUTES_TXT); 4391420Smarks lend += sizeof (WRITE_ATTRIBUTES_TXT) - 1; 4401420Smarks } 4411420Smarks if (mask & ACE_DELETE) { 4421420Smarks strcpy(lend, DELETE_TXT); 4431420Smarks lend += sizeof (DELETE_TXT) - 1; 4441420Smarks } 4451420Smarks if (mask & ACE_READ_ACL) { 4461420Smarks strcpy(lend, READ_ACL_TXT); 4471420Smarks lend += sizeof (READ_ACL_TXT) - 1; 4481420Smarks } 4491420Smarks if (mask & ACE_WRITE_ACL) { 4501420Smarks strcpy(lend, WRITE_ACL_TXT); 4511420Smarks lend += sizeof (WRITE_ACL_TXT) - 1; 4521420Smarks } 4531420Smarks if (mask & ACE_WRITE_OWNER) { 4541420Smarks strcpy(lend, WRITE_OWNER_TXT); 4551420Smarks lend += sizeof (WRITE_OWNER_TXT) - 1; 4561420Smarks } 4571420Smarks if (mask & ACE_SYNCHRONIZE) { 4581420Smarks strcpy(lend, SYNCHRONIZE_TXT); 4591420Smarks lend += sizeof (SYNCHRONIZE_TXT) - 1; 4601420Smarks } 461789Sahrens 4621420Smarks if (*(lend - 1) == '/') 4631420Smarks *--lend = '\0'; 4641420Smarks } 4651420Smarks 4661420Smarks *endp = lend; 4671420Smarks return (buf); 4681420Smarks } 4691420Smarks 4701420Smarks #define ALLOW_TXT "allow" 4711420Smarks #define DENY_TXT "deny" 4721420Smarks #define ALARM_TXT "alarm" 4731420Smarks #define AUDIT_TXT "audit" 4741420Smarks #define UNKNOWN_TXT "unknown" 4751420Smarks char * 4761420Smarks ace_access_txt(char *buf, char **endp, int type) 4771420Smarks { 4781420Smarks 4791420Smarks if (buf == NULL) 4801420Smarks return (NULL); 4811420Smarks 4821420Smarks if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 4831420Smarks strcpy(buf, ALLOW_TXT); 4841420Smarks *endp += sizeof (ALLOW_TXT) - 1; 4851420Smarks } else if (type == ACE_ACCESS_DENIED_ACE_TYPE) { 4861420Smarks strcpy(buf, DENY_TXT); 4871420Smarks *endp += sizeof (DENY_TXT) - 1; 4881420Smarks } else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) { 4891420Smarks strcpy(buf, AUDIT_TXT); 4901420Smarks *endp += sizeof (AUDIT_TXT) - 1; 4911420Smarks } else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) { 4921420Smarks strcpy(buf, ALARM_TXT); 4931420Smarks *endp += sizeof (ALARM_TXT) - 1; 4941420Smarks } else { 4951420Smarks strcpy(buf, UNKNOWN_TXT); 4961420Smarks *endp += sizeof (UNKNOWN_TXT) - 1; 4971420Smarks } 4981420Smarks 4991420Smarks return (buf); 5001420Smarks } 5011420Smarks 5021420Smarks static char * 5031420Smarks ace_inherit_txt(char *buf, char **endp, uint32_t iflags, int flags) 5041420Smarks { 5051420Smarks 5061420Smarks char *lend = buf; 5071420Smarks 5081420Smarks if (buf == NULL) { 5091420Smarks return (NULL); 5101420Smarks } 511789Sahrens 5121420Smarks if (flags & ACL_COMPACT_FMT) { 5131420Smarks if (iflags & ACE_FILE_INHERIT_ACE) 5141420Smarks buf[0] = 'f'; 5151420Smarks else 5161420Smarks buf[0] = '-'; 5171420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) 5181420Smarks buf[1] = 'd'; 5191420Smarks else 5201420Smarks buf[1] = '-'; 5211420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) 5221420Smarks buf[2] = 'i'; 5231420Smarks else 5241420Smarks buf[2] = '-'; 5251420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) 5261420Smarks buf[3] = 'n'; 5271420Smarks else 5281420Smarks buf[3] = '-'; 5291420Smarks if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 5301420Smarks buf[4] = 'S'; 5311420Smarks else 5321420Smarks buf[4] = '-'; 5331420Smarks if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) 5341420Smarks buf[5] = 'F'; 5351420Smarks else 5361420Smarks buf[5] = '-'; 5371420Smarks buf[6] = '\0'; 5381420Smarks *endp = buf + 6; 5391420Smarks } else { 5401420Smarks if (iflags & ACE_FILE_INHERIT_ACE) { 5411420Smarks strcpy(lend, "file_inherit/"); 5421420Smarks lend += sizeof ("file_inherit/") - 1; 5431420Smarks } 5441420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) { 5451420Smarks strcpy(lend, "dir_inherit/"); 5461420Smarks lend += sizeof ("dir_inherit/") - 1; 5471420Smarks } 5481420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) { 5491420Smarks strcpy(lend, "no_propagate/"); 5501420Smarks lend += sizeof ("no_propagate/") - 1; 5511420Smarks } 5521420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) { 5531420Smarks strcpy(lend, "inherit_only/"); 5541420Smarks lend += sizeof ("inherit_only/") - 1; 5551420Smarks } 556789Sahrens 5571420Smarks if (*(lend - 1) == '/') 5581420Smarks *--lend = '\0'; 5591420Smarks *endp = lend; 5601420Smarks } 5611420Smarks 5621420Smarks return (buf); 563789Sahrens } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate /* 5660Sstevel@tonic-gate * Convert internal acl representation to external representation. 5670Sstevel@tonic-gate * 5680Sstevel@tonic-gate * The length of a non-owning user name or non-owning group name ie entries 5690Sstevel@tonic-gate * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We 5700Sstevel@tonic-gate * thus check the length of these entries, and if greater than LOGNAME_MAX, 5710Sstevel@tonic-gate * we realloc() via increase_length(). 5720Sstevel@tonic-gate * 5730Sstevel@tonic-gate * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always 5740Sstevel@tonic-gate * adhered to. 5750Sstevel@tonic-gate */ 5761420Smarks 5771420Smarks /* 5781420Smarks * acltotext() converts each ACL entry to look like this: 5791420Smarks * 5801420Smarks * entry_type:uid^gid^name:perms[:id] 5811420Smarks * 5821420Smarks * The maximum length of entry_type is 14 ("defaultgroup::" and 5831420Smarks * "defaultother::") hence ENTRYTYPELEN is set to 14. 5841420Smarks * 5851420Smarks * The max length of a uid^gid^name entry (in theory) is 8, hence we use, 5861420Smarks * however the ID could be a number so we therefore use ID_STR_MAX 5871420Smarks * 5881420Smarks * The length of a perms entry is 4 to allow for the comma appended to each 5891420Smarks * to each acl entry. Hence PERMS is set to 4. 5901420Smarks */ 5911420Smarks 5921420Smarks #define ENTRYTYPELEN 14 5931420Smarks #define PERMS 4 5941420Smarks #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX) 5951420Smarks #define UPDATE_WHERE where = dstr->aclexport + strlen(dstr->aclexport) 5961420Smarks 5970Sstevel@tonic-gate char * 5981420Smarks aclent_acltotext(aclent_t *aclp, int aclcnt, int flags) 5990Sstevel@tonic-gate { 6000Sstevel@tonic-gate char *aclexport; 6010Sstevel@tonic-gate char *where; 602*1507Sgjelinek struct group *groupp = NULL; 603*1507Sgjelinek struct passwd *passwdp = NULL; 6040Sstevel@tonic-gate struct dynaclstr *dstr; 6050Sstevel@tonic-gate int i, rtn; 6060Sstevel@tonic-gate size_t excess = 0; 6071420Smarks char id[20], *idstr; 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate if (aclp == NULL) 6100Sstevel@tonic-gate return (NULL); 6110Sstevel@tonic-gate if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL) 6120Sstevel@tonic-gate return (NULL); 6130Sstevel@tonic-gate dstr->bufsize = aclcnt * ACL_ENTRY_SIZE; 6140Sstevel@tonic-gate if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) { 6150Sstevel@tonic-gate free(dstr); 6160Sstevel@tonic-gate return (NULL); 6170Sstevel@tonic-gate } 6180Sstevel@tonic-gate *dstr->aclexport = '\0'; 6190Sstevel@tonic-gate where = dstr->aclexport; 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate for (i = 0; i < aclcnt; i++, aclp++) { 6220Sstevel@tonic-gate switch (aclp->a_type) { 6230Sstevel@tonic-gate case DEF_USER_OBJ: 6240Sstevel@tonic-gate case USER_OBJ: 6250Sstevel@tonic-gate if (aclp->a_type == USER_OBJ) 6260Sstevel@tonic-gate where = strappend(where, "user::"); 6270Sstevel@tonic-gate else 6280Sstevel@tonic-gate where = strappend(where, "defaultuser::"); 6290Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6300Sstevel@tonic-gate break; 6310Sstevel@tonic-gate case DEF_USER: 6320Sstevel@tonic-gate case USER: 6330Sstevel@tonic-gate if (aclp->a_type == USER) 6340Sstevel@tonic-gate where = strappend(where, "user:"); 6350Sstevel@tonic-gate else 6360Sstevel@tonic-gate where = strappend(where, "defaultuser:"); 637*1507Sgjelinek if ((flags & ACL_NORESOLVE) == 0) 638*1507Sgjelinek passwdp = getpwuid(aclp->a_id); 6390Sstevel@tonic-gate if (passwdp == (struct passwd *)NULL) { 6400Sstevel@tonic-gate /* put in uid instead */ 6410Sstevel@tonic-gate (void) sprintf(where, "%d", aclp->a_id); 642922Shm123892 UPDATE_WHERE; 6430Sstevel@tonic-gate } else { 6440Sstevel@tonic-gate excess = strlen(passwdp->pw_name) - LOGNAME_MAX; 6450Sstevel@tonic-gate if (excess > 0) { 6460Sstevel@tonic-gate rtn = increase_length(dstr, excess); 6470Sstevel@tonic-gate if (rtn == 1) { 648922Shm123892 UPDATE_WHERE; 6490Sstevel@tonic-gate } else { 6500Sstevel@tonic-gate free(dstr->aclexport); 6510Sstevel@tonic-gate free(dstr); 6520Sstevel@tonic-gate return (NULL); 6530Sstevel@tonic-gate } 6540Sstevel@tonic-gate } 6550Sstevel@tonic-gate where = strappend(where, passwdp->pw_name); 6560Sstevel@tonic-gate } 6570Sstevel@tonic-gate where = strappend(where, ":"); 6580Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6590Sstevel@tonic-gate break; 6600Sstevel@tonic-gate case DEF_GROUP_OBJ: 6610Sstevel@tonic-gate case GROUP_OBJ: 6620Sstevel@tonic-gate if (aclp->a_type == GROUP_OBJ) 6630Sstevel@tonic-gate where = strappend(where, "group::"); 6640Sstevel@tonic-gate else 6650Sstevel@tonic-gate where = strappend(where, "defaultgroup::"); 6660Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6670Sstevel@tonic-gate break; 6680Sstevel@tonic-gate case DEF_GROUP: 6690Sstevel@tonic-gate case GROUP: 6700Sstevel@tonic-gate if (aclp->a_type == GROUP) 6710Sstevel@tonic-gate where = strappend(where, "group:"); 6720Sstevel@tonic-gate else 6730Sstevel@tonic-gate where = strappend(where, "defaultgroup:"); 674*1507Sgjelinek if ((flags & ACL_NORESOLVE) == 0) 675*1507Sgjelinek groupp = getgrgid(aclp->a_id); 6760Sstevel@tonic-gate if (groupp == (struct group *)NULL) { 6770Sstevel@tonic-gate /* put in gid instead */ 6780Sstevel@tonic-gate (void) sprintf(where, "%d", aclp->a_id); 679922Shm123892 UPDATE_WHERE; 6800Sstevel@tonic-gate } else { 6810Sstevel@tonic-gate excess = strlen(groupp->gr_name) - LOGNAME_MAX; 6820Sstevel@tonic-gate if (excess > 0) { 6830Sstevel@tonic-gate rtn = increase_length(dstr, excess); 6840Sstevel@tonic-gate if (rtn == 1) { 685922Shm123892 UPDATE_WHERE; 6860Sstevel@tonic-gate } else { 6870Sstevel@tonic-gate free(dstr->aclexport); 6880Sstevel@tonic-gate free(dstr); 6890Sstevel@tonic-gate return (NULL); 6900Sstevel@tonic-gate } 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate where = strappend(where, groupp->gr_name); 6930Sstevel@tonic-gate } 6940Sstevel@tonic-gate where = strappend(where, ":"); 6950Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6960Sstevel@tonic-gate break; 6970Sstevel@tonic-gate case DEF_CLASS_OBJ: 6980Sstevel@tonic-gate case CLASS_OBJ: 6990Sstevel@tonic-gate if (aclp->a_type == CLASS_OBJ) 7000Sstevel@tonic-gate where = strappend(where, "mask:"); 7010Sstevel@tonic-gate else 7020Sstevel@tonic-gate where = strappend(where, "defaultmask:"); 7030Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7040Sstevel@tonic-gate break; 7050Sstevel@tonic-gate case DEF_OTHER_OBJ: 7060Sstevel@tonic-gate case OTHER_OBJ: 7070Sstevel@tonic-gate if (aclp->a_type == OTHER_OBJ) 7080Sstevel@tonic-gate where = strappend(where, "other:"); 7090Sstevel@tonic-gate else 7100Sstevel@tonic-gate where = strappend(where, "defaultother:"); 7110Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7120Sstevel@tonic-gate break; 7130Sstevel@tonic-gate default: 7140Sstevel@tonic-gate free(dstr->aclexport); 7150Sstevel@tonic-gate free(dstr); 7160Sstevel@tonic-gate return (NULL); 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate } 7191420Smarks 7201420Smarks if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) || 7211420Smarks (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) || 7221420Smarks (aclp->a_type == DEF_GROUP))) { 7231420Smarks where = strappend(where, ":"); 7241420Smarks id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */ 7251420Smarks idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]); 7261420Smarks where = strappend(where, idstr); 7271420Smarks } 7280Sstevel@tonic-gate if (i < aclcnt - 1) 7290Sstevel@tonic-gate where = strappend(where, ","); 7300Sstevel@tonic-gate } 7310Sstevel@tonic-gate aclexport = dstr->aclexport; 7320Sstevel@tonic-gate free(dstr); 7330Sstevel@tonic-gate return (aclexport); 7341420Smarks 7351420Smarks 7361420Smarks 7371420Smarks 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate 7401420Smarks char * 7411420Smarks acltotext(aclent_t *aclp, int aclcnt) 7420Sstevel@tonic-gate { 7431420Smarks return (aclent_acltotext(aclp, aclcnt, 0)); 7441420Smarks } 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate 747789Sahrens aclent_t * 748789Sahrens aclfromtext(char *aclstr, int *aclcnt) 749789Sahrens { 750789Sahrens acl_t *aclp; 751789Sahrens aclent_t *aclentp; 752789Sahrens int error; 753789Sahrens 7541420Smarks error = acl_fromtext(aclstr, &aclp); 755789Sahrens if (error) 756789Sahrens return (NULL); 757789Sahrens 758789Sahrens aclentp = aclp->acl_aclp; 759789Sahrens aclp->acl_aclp = NULL; 7601420Smarks *aclcnt = aclp->acl_cnt; 761789Sahrens 7621420Smarks acl_free(aclp); 763789Sahrens return (aclentp); 764789Sahrens } 765789Sahrens 766789Sahrens 7670Sstevel@tonic-gate static char * 7680Sstevel@tonic-gate strappend(char *where, char *newstr) 7690Sstevel@tonic-gate { 7700Sstevel@tonic-gate (void) strcat(where, newstr); 7710Sstevel@tonic-gate return (where + strlen(newstr)); 7720Sstevel@tonic-gate } 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate static char * 7750Sstevel@tonic-gate convert_perm(char *where, o_mode_t perm) 7760Sstevel@tonic-gate { 7771420Smarks if (perm & S_IROTH) 7780Sstevel@tonic-gate where = strappend(where, "r"); 7790Sstevel@tonic-gate else 7800Sstevel@tonic-gate where = strappend(where, "-"); 7811420Smarks if (perm & S_IWOTH) 7820Sstevel@tonic-gate where = strappend(where, "w"); 7830Sstevel@tonic-gate else 7840Sstevel@tonic-gate where = strappend(where, "-"); 7851420Smarks if (perm & S_IXOTH) 7860Sstevel@tonic-gate where = strappend(where, "x"); 7870Sstevel@tonic-gate else 7880Sstevel@tonic-gate where = strappend(where, "-"); 7890Sstevel@tonic-gate /* perm is the last field */ 7900Sstevel@tonic-gate return (where); 7910Sstevel@tonic-gate } 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate /* 7940Sstevel@tonic-gate * Callers should check the return code as this routine may change the string 7950Sstevel@tonic-gate * pointer in dynaclstr. 7960Sstevel@tonic-gate */ 7970Sstevel@tonic-gate static int 7980Sstevel@tonic-gate increase_length(struct dynaclstr *dacl, size_t increase) 7990Sstevel@tonic-gate { 8000Sstevel@tonic-gate char *tptr; 8010Sstevel@tonic-gate size_t newsize; 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate newsize = dacl->bufsize + increase; 8040Sstevel@tonic-gate tptr = realloc(dacl->aclexport, newsize); 8050Sstevel@tonic-gate if (tptr != NULL) { 8060Sstevel@tonic-gate dacl->aclexport = tptr; 8070Sstevel@tonic-gate dacl->bufsize = newsize; 8080Sstevel@tonic-gate return (1); 8090Sstevel@tonic-gate } else 8100Sstevel@tonic-gate return (0); 8110Sstevel@tonic-gate } 812789Sahrens 813789Sahrens /* 8141420Smarks * ace_acltotext() convert each ace formatted acl to look like this: 815789Sahrens * 8161420Smarks * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,] 817789Sahrens * 818789Sahrens * The maximum length of entry_type is 5 ("group") 819789Sahrens * 8201420Smarks * The max length of a uid^gid^name entry (in theory) is 8, 8211420Smarks * however id could be a number so we therefore use ID_STR_MAX 822789Sahrens * 823789Sahrens * The length of a perms entry is 144 i.e read_data/write_data... 824789Sahrens * to each acl entry. 825789Sahrens * 826789Sahrens * iflags: file_inherit/dir_inherit/inherit_only/no_propagate 827789Sahrens * 828789Sahrens */ 829789Sahrens 830789Sahrens #define ACE_ENTRYTYPLEN 6 831789Sahrens #define IFLAGS_SIZE 51 8321420Smarks #define ACCESS_TYPE_SIZE 7 /* if unknown */ 833789Sahrens #define COLON_CNT 3 834789Sahrens #define PERMS_LEN 216 8351420Smarks #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN +\ 8361420Smarks ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX) 837789Sahrens 838789Sahrens static char * 8391420Smarks ace_acltotext(acl_t *aceaclp, int flags) 840789Sahrens { 841789Sahrens ace_t *aclp = aceaclp->acl_aclp; 842789Sahrens int aclcnt = aceaclp->acl_cnt; 843789Sahrens char *aclexport; 8441420Smarks char *endp; 8451420Smarks int i; 8461420Smarks char id[ID_STR_MAX], *idstr; 847789Sahrens int isdir = (aceaclp->acl_flags & ACL_IS_DIR); 848789Sahrens 849789Sahrens if (aclp == NULL) 850789Sahrens return (NULL); 8511420Smarks if ((aclexport = malloc(aclcnt * ACE_ENTRY_SIZE)) == NULL) 852789Sahrens return (NULL); 853789Sahrens 8541420Smarks aclexport[0] = '\0'; 8551420Smarks endp = aclexport; 856789Sahrens for (i = 0; i < aclcnt; i++, aclp++) { 8571420Smarks 8581420Smarks (void) ace_type_txt(endp, &endp, aclp); 8591420Smarks *endp++ = ':'; 8601420Smarks *endp = '\0'; 8611420Smarks (void) ace_perm_txt(endp, &endp, aclp->a_access_mask, 8621420Smarks aclp->a_flags, isdir, flags); 8631420Smarks *endp++ = ':'; 8641420Smarks *endp = '\0'; 8651420Smarks (void) ace_inherit_txt(endp, &endp, aclp->a_flags, flags); 8661420Smarks if (flags & ACL_COMPACT_FMT || aclp->a_flags & 8671420Smarks (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE | 8681420Smarks (ACE_INHERIT_ONLY_ACE | ACE_NO_PROPAGATE_INHERIT_ACE))) { 8691420Smarks *endp++ = ':'; 8701420Smarks *endp = '\0'; 8711420Smarks } 8721420Smarks (void) ace_access_txt(endp, &endp, aclp->a_type); 873789Sahrens 8741420Smarks if ((flags & ACL_APPEND_ID) && 8751420Smarks (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) || 8761420Smarks ((aclp->a_flags & ACE_TYPE_FLAGS) == 8771420Smarks ACE_IDENTIFIER_GROUP))) { 8781420Smarks *endp++ = ':'; 8791420Smarks *endp = '\0'; 8801420Smarks id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */ 8811420Smarks idstr = lltostr(aclp->a_who, &id[ID_STR_MAX - 1]); 8821420Smarks strcpy(endp, idstr); 8831420Smarks endp += strlen(idstr); 884789Sahrens } 8851420Smarks if (i < aclcnt - 1) { 8861420Smarks *endp++ = ','; 8871420Smarks *(endp + 1) = '\0'; 888789Sahrens } 889789Sahrens } 890789Sahrens return (aclexport); 891789Sahrens } 892789Sahrens 8931420Smarks char * 8941420Smarks acl_totext(acl_t *aclp, int flags) 895789Sahrens { 896789Sahrens 8971420Smarks char *txtp; 898789Sahrens 899789Sahrens if (aclp == NULL) 900789Sahrens return (NULL); 901789Sahrens 902789Sahrens switch (aclp->acl_type) { 903789Sahrens case ACE_T: 9041420Smarks txtp = ace_acltotext(aclp, flags); 9051420Smarks break; 906789Sahrens case ACLENT_T: 9071420Smarks txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags); 9081420Smarks break; 909789Sahrens } 9101420Smarks 9111420Smarks return (txtp); 912789Sahrens } 913789Sahrens 914789Sahrens int 915789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp) 916789Sahrens { 9171420Smarks int error; 9181420Smarks char *buf; 9191420Smarks 9201420Smarks buf = malloc(strlen(acltextp) + 2); 9211420Smarks if (buf == NULL) 9221420Smarks return (EACL_MEM_ERROR); 9231420Smarks strcpy(buf, acltextp); 9241420Smarks strcat(buf, "\n"); 9251420Smarks yybuf = buf; 9261420Smarks yyreset(); 9271420Smarks error = yyparse(); 9281420Smarks free(buf); 9291420Smarks 9301420Smarks if (yyacl) { 9311420Smarks if (error == 0) 9321420Smarks *ret_aclp = yyacl; 9331420Smarks else { 9341420Smarks acl_free(yyacl); 9351420Smarks } 9361420Smarks yyacl = NULL; 9371420Smarks } 9381420Smarks return (error); 9391420Smarks } 9401420Smarks 9411420Smarks int 9421420Smarks acl_parse(const char *acltextp, acl_t **aclp) 9431420Smarks { 944789Sahrens int error; 945789Sahrens 9461420Smarks yyinteractive = 1; 9471420Smarks error = acl_fromtext(acltextp, aclp); 9481420Smarks yyinteractive = 0; 9491420Smarks return (error); 9501420Smarks } 9511420Smarks 9521420Smarks static void 9531420Smarks ace_compact_printacl(acl_t *aclp) 9541420Smarks { 9551420Smarks int cnt; 9561420Smarks ace_t *acep; 9571420Smarks char *endp; 9581420Smarks char buf[ACE_ENTRY_SIZE]; 959789Sahrens 9601420Smarks for (cnt = 0, acep = aclp->acl_aclp; 9611420Smarks cnt != aclp->acl_cnt; cnt++, acep++) { 9621420Smarks buf[0] = '\0'; 9631420Smarks (void) printf(" %14s:", ace_type_txt(buf, &endp, acep)); 9641420Smarks (void) printf("%s:", ace_perm_txt(endp, &endp, 9651420Smarks acep->a_access_mask, acep->a_flags, 9661420Smarks aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT)); 9671420Smarks (void) printf("%s:", 9681420Smarks ace_inherit_txt(endp, &endp, acep->a_flags, 9691420Smarks ACL_COMPACT_FMT)); 9701420Smarks (void) printf("%s\n", ace_access_txt(endp, &endp, 9711420Smarks acep->a_type)); 9721420Smarks } 9731420Smarks } 974789Sahrens 9751420Smarks static void 9761420Smarks ace_printacl(acl_t *aclp, int cols, int compact) 9771420Smarks { 9781420Smarks int slot = 0; 9791420Smarks char *token; 9801420Smarks char *acltext; 9811420Smarks 9821420Smarks if (compact) { 9831420Smarks ace_compact_printacl(aclp); 9841420Smarks return; 985789Sahrens } 986789Sahrens 9871420Smarks acltext = acl_totext(aclp, 0); 9881420Smarks 9891420Smarks if (acltext == NULL) 9901420Smarks return; 9911420Smarks 9921420Smarks token = strtok(acltext, ","); 9931420Smarks if (token == NULL) { 9941420Smarks free(acltext); 9951420Smarks return; 996789Sahrens } 997789Sahrens 9981420Smarks do { 9991420Smarks (void) printf(" %d:", slot++); 10001420Smarks split_line(token, cols - 5); 10011420Smarks } while (token = strtok(NULL, ",")); 10021420Smarks free(acltext); 10031420Smarks } 10041420Smarks 10051420Smarks /* 10061420Smarks * pretty print an ACL. 10071420Smarks * For aclent_t ACL's the format is 10081420Smarks * similar to the old format used by getfacl, 10091420Smarks * with the addition of adding a "slot" number 10101420Smarks * before each entry. 10111420Smarks * 10121420Smarks * for ace_t ACL's the cols variable will break up 10131420Smarks * the long lines into multiple lines and will also 10141420Smarks * print a "slot" number. 10151420Smarks */ 10161420Smarks void 10171420Smarks acl_printacl(acl_t *aclp, int cols, int compact) 10181420Smarks { 10191420Smarks 10201420Smarks switch (aclp->acl_type) { 10211420Smarks case ACLENT_T: 10221420Smarks aclent_printacl(aclp); 10231420Smarks break; 10241420Smarks case ACE_T: 10251420Smarks ace_printacl(aclp, cols, compact); 10261420Smarks break; 10271420Smarks } 10281420Smarks } 10291420Smarks 10301420Smarks typedef struct value_table { 10311420Smarks char p_letter; /* perm letter such as 'r' */ 10321420Smarks uint32_t p_value; /* value for perm when pletter found */ 10331420Smarks } value_table_t; 10341420Smarks 10351420Smarks #define ACE_PERM_COUNT 14 10361420Smarks 10371420Smarks /* 10381420Smarks * The permission tables are layed out in positional order 10391420Smarks * a '-' character will indicate a permission at a given 10401420Smarks * position is not specified. The '-' is not part of the 10411420Smarks * table, but will be checked for in the permission computation 10421420Smarks * routine. 10431420Smarks */ 10441420Smarks value_table_t ace_perm_table[ACE_PERM_COUNT] = { 10451420Smarks { 'r', ACE_READ_DATA}, 10461420Smarks { 'w', ACE_WRITE_DATA}, 10471420Smarks { 'x', ACE_EXECUTE}, 10481420Smarks { 'p', ACE_APPEND_DATA}, 10491420Smarks { 'd', ACE_DELETE}, 10501420Smarks { 'D', ACE_DELETE_CHILD}, 10511420Smarks { 'a', ACE_READ_ATTRIBUTES}, 10521420Smarks { 'A', ACE_WRITE_ATTRIBUTES}, 10531420Smarks { 'R', ACE_READ_NAMED_ATTRS}, 10541420Smarks { 'W', ACE_WRITE_NAMED_ATTRS}, 10551420Smarks { 'c', ACE_READ_ACL}, 10561420Smarks { 'C', ACE_WRITE_ACL}, 10571420Smarks { 'o', ACE_WRITE_OWNER}, 10581420Smarks { 's', ACE_SYNCHRONIZE} 10591420Smarks }; 10601420Smarks 10611420Smarks #define ACLENT_PERM_COUNT 3 10621420Smarks 10631420Smarks value_table_t aclent_perm_table[ACLENT_PERM_COUNT] = { 10641420Smarks { 'r', S_IROTH}, 10651420Smarks { 'w', S_IWOTH}, 10661420Smarks { 'x', S_IXOTH} 10671420Smarks }; 10681420Smarks 10691420Smarks #define IFLAG_COUNT 6 10701420Smarks value_table_t inherit_table[IFLAG_COUNT] = { 10711420Smarks {'f', ACE_FILE_INHERIT_ACE}, 10721420Smarks {'d', ACE_DIRECTORY_INHERIT_ACE}, 10731420Smarks {'i', ACE_INHERIT_ONLY_ACE}, 10741420Smarks {'n', ACE_NO_PROPAGATE_INHERIT_ACE}, 10751420Smarks {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 10761420Smarks {'F', ACE_FAILED_ACCESS_ACE_FLAG} 10771420Smarks }; 10781420Smarks 10791420Smarks /* 10801420Smarks * compute value from a permission table or inheritance table 10811420Smarks * based on string passed in. If positional is set then 10821420Smarks * string must match order in permtab, otherwise any order 10831420Smarks * is allowed. 10841420Smarks */ 10851420Smarks int 10861420Smarks compute_values(value_table_t *permtab, int count, 10871420Smarks char *permstr, int positional, uint32_t *mask) 10881420Smarks { 10891420Smarks uint32_t perm_val = 0; 10901420Smarks char *pstr; 10911420Smarks int i, found; 10921420Smarks 10931420Smarks if (count < 0) 10941420Smarks return (1); 10951420Smarks 10961420Smarks if (positional) { 10971420Smarks for (i = 0, pstr = permstr; i != count && pstr && 10981420Smarks *pstr; i++, pstr++) { 10991420Smarks if (*pstr == permtab[i].p_letter) { 11001420Smarks perm_val |= permtab[i].p_value; 11011420Smarks } else if (*pstr != '-') { 11021420Smarks return (1); 11031420Smarks } 1104789Sahrens } 11051420Smarks } else { /* random order single letters with no '-' */ 11061420Smarks for (pstr = permstr; pstr && *pstr; pstr++) { 11071420Smarks for (found = 0, i = 0; i != count; i++) { 11081420Smarks if (*pstr == permtab[i].p_letter) { 11091420Smarks perm_val |= permtab[i].p_value; 11101420Smarks found = 1; 11111420Smarks break; 11121420Smarks } 11131420Smarks } 11141420Smarks if (found == 0) 11151420Smarks return (1); 11161420Smarks } 1117789Sahrens } 1118789Sahrens 11191420Smarks *mask = perm_val; 11201420Smarks return (0); 11211420Smarks } 1122789Sahrens 11231420Smarks /* 11241420Smarks * compute value for inheritance flags. 11251420Smarks */ 11261420Smarks int 11271420Smarks compute_ace_inherit(char *str, uint32_t *imask) 11281420Smarks { 11291420Smarks int error; 11301420Smarks int positional = 0; 1131789Sahrens 11321420Smarks if (strlen(str) == IFLAG_COUNT) 11331420Smarks positional = 1; 11341420Smarks 11351420Smarks error = compute_values(inherit_table, IFLAG_COUNT, 11361420Smarks str, positional, imask); 11371420Smarks 11381420Smarks if (error) 11391420Smarks return (EACL_INHERIT_ERROR); 11401420Smarks 1141789Sahrens return (error); 1142789Sahrens } 11431420Smarks 11441420Smarks 11451420Smarks /* 11461420Smarks * compute value for ACE permissions. 11471420Smarks */ 11481420Smarks int 11491420Smarks compute_ace_perms(char *str, uint32_t *mask) 11501420Smarks { 11511420Smarks int positional = 0; 11521420Smarks int error; 11531420Smarks 11541420Smarks if (strlen(str) == ACE_PERM_COUNT) 11551420Smarks positional = 1; 11561420Smarks 11571420Smarks error = compute_values(ace_perm_table, ACE_PERM_COUNT, 11581420Smarks str, positional, mask); 11591420Smarks 11601420Smarks if (error && positional) { 11611420Smarks /* 11621420Smarks * If positional was set, then make sure permissions 11631420Smarks * aren't actually valid in non positional case where 11641420Smarks * all permissions are specified, just in random order. 11651420Smarks */ 11661420Smarks error = compute_values(ace_perm_table, 11671420Smarks ACE_PERM_COUNT, str, 0, mask); 11681420Smarks } 11691420Smarks if (error) 11701420Smarks error = EACL_PERM_MASK_ERROR; 11711420Smarks 11721420Smarks return (error); 11731420Smarks } 11741420Smarks 11751420Smarks 11761420Smarks 11771420Smarks /* 11781420Smarks * compute values for aclent permissions. 11791420Smarks */ 11801420Smarks int 11811420Smarks compute_aclent_perms(char *str, o_mode_t *mask) 11821420Smarks { 11831420Smarks int error; 11841420Smarks uint32_t pmask; 11851420Smarks 11861420Smarks if (strlen(str) != ACLENT_PERM_COUNT) 11871420Smarks return (EACL_PERM_MASK_ERROR); 11881420Smarks 11891420Smarks *mask = 0; 11901420Smarks error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT, 11911420Smarks str, 1, &pmask); 11921420Smarks if (error == 0) { 11931420Smarks *mask = (o_mode_t)pmask; 11941420Smarks } else 11951420Smarks error = EACL_PERM_MASK_ERROR; 11961420Smarks return (error); 11971420Smarks } 11981420Smarks 11991420Smarks /* 12001420Smarks * determine ACE permissions. 12011420Smarks */ 12021420Smarks int 12031420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask) 12041420Smarks { 12051420Smarks int error; 12061420Smarks 12071420Smarks if (aclperm->perm_style == PERM_TYPE_EMPTY) { 12081420Smarks *mask = 0; 12091420Smarks return (0); 12101420Smarks } 12111420Smarks 12121420Smarks if (aclperm->perm_style == PERM_TYPE_ACE) { 12131420Smarks *mask = aclperm->perm_val; 12141420Smarks return (0); 12151420Smarks } 12161420Smarks 12171420Smarks error = compute_ace_perms(aclperm->perm_str, mask); 12181420Smarks if (error) { 12191420Smarks acl_error(gettext("Invalid permission(s) '%s' specified\n"), 12201420Smarks aclperm->perm_str); 12211420Smarks return (EACL_PERM_MASK_ERROR); 12221420Smarks } 12231420Smarks 12241420Smarks return (0); 12251420Smarks } 1226