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 51507Sgjelinek * Common Development and Distribution License (the "License"). 61507Sgjelinek * 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 /* 224321Scasper * Copyright 2007 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 * 841535Smarks pruname(uid_t uid, char *uidp, size_t buflen, int noresolve) 851420Smarks { 861515Sgjelinek struct passwd *passwdp = NULL; 871420Smarks 881515Sgjelinek if (noresolve == 0) 891515Sgjelinek passwdp = getpwuid(uid); 901420Smarks if (passwdp == (struct passwd *)NULL) { 911420Smarks /* could not get passwd information: display uid instead */ 924321Scasper (void) snprintf(uidp, buflen, "%u", uid); 931535Smarks } else { 941535Smarks (void) strlcpy(uidp, passwdp->pw_name, buflen); 951535Smarks } 961535Smarks return (uidp); 971420Smarks } 981420Smarks 991420Smarks static char * 1001535Smarks prgname(gid_t gid, char *gidp, size_t buflen, int noresolve) 1011420Smarks { 1021515Sgjelinek struct group *groupp = NULL; 1031420Smarks 1041515Sgjelinek if (noresolve == 0) 1051515Sgjelinek groupp = getgrgid(gid); 1061420Smarks if (groupp == (struct group *)NULL) { 1071420Smarks /* could not get group information: display gid instead */ 1084321Scasper (void) snprintf(gidp, buflen, "%u", gid); 1091535Smarks } else { 1101535Smarks (void) strlcpy(gidp, groupp->gr_name, buflen); 1111535Smarks } 1121535Smarks return (gidp); 1131420Smarks } 1141420Smarks static void 1151420Smarks aclent_printacl(acl_t *aclp) 116789Sahrens { 1171420Smarks aclent_t *tp; 1181420Smarks int aclcnt; 1191420Smarks int mask; 1201420Smarks int slot = 0; 1211420Smarks char perm[4]; 1221535Smarks char uidp[ID_STR_MAX]; 1231535Smarks char gidp[ID_STR_MAX]; 1241420Smarks 1251420Smarks /* display ACL: assume it is sorted. */ 1261420Smarks aclcnt = aclp->acl_cnt; 1271420Smarks for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) { 1281420Smarks if (tp->a_type == CLASS_OBJ) 1291420Smarks mask = tp->a_perm; 1301420Smarks } 1311420Smarks aclcnt = aclp->acl_cnt; 1321420Smarks for (tp = aclp->acl_aclp; aclcnt--; tp++) { 1331420Smarks (void) printf(" %d:", slot++); 1341420Smarks switch (tp->a_type) { 1351420Smarks case USER: 1361420Smarks aclent_perms(tp->a_perm, perm); 1371420Smarks (void) printf("user:%s:%s\t\t", 1381535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 1391420Smarks aclent_perms((tp->a_perm & mask), perm); 1401420Smarks (void) printf("#effective:%s\n", perm); 1411420Smarks break; 1421420Smarks case USER_OBJ: 1431420Smarks /* no need to display uid */ 1441420Smarks aclent_perms(tp->a_perm, perm); 1451420Smarks (void) printf("user::%s\n", perm); 1461420Smarks break; 1471420Smarks case GROUP: 1481420Smarks aclent_perms(tp->a_perm, perm); 1491420Smarks (void) printf("group:%s:%s\t\t", 1501535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 1511420Smarks aclent_perms(tp->a_perm & mask, perm); 1521420Smarks (void) printf("#effective:%s\n", perm); 1531420Smarks break; 1541420Smarks case GROUP_OBJ: 1551420Smarks aclent_perms(tp->a_perm, perm); 1561420Smarks (void) printf("group::%s\t\t", perm); 1571420Smarks aclent_perms(tp->a_perm & mask, perm); 1581420Smarks (void) printf("#effective:%s\n", perm); 1591420Smarks break; 1601420Smarks case CLASS_OBJ: 1611420Smarks aclent_perms(tp->a_perm, perm); 1621420Smarks (void) printf("mask:%s\n", perm); 1631420Smarks break; 1641420Smarks case OTHER_OBJ: 1651420Smarks aclent_perms(tp->a_perm, perm); 1661420Smarks (void) printf("other:%s\n", perm); 1671420Smarks break; 1681420Smarks case DEF_USER: 1691420Smarks aclent_perms(tp->a_perm, perm); 1701420Smarks (void) printf("default:user:%s:%s\n", 1711535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 1721420Smarks break; 1731420Smarks case DEF_USER_OBJ: 1741420Smarks aclent_perms(tp->a_perm, perm); 1751420Smarks (void) printf("default:user::%s\n", perm); 1761420Smarks break; 1771420Smarks case DEF_GROUP: 1781420Smarks aclent_perms(tp->a_perm, perm); 1791420Smarks (void) printf("default:group:%s:%s\n", 1801535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 1811420Smarks break; 1821420Smarks case DEF_GROUP_OBJ: 1831420Smarks aclent_perms(tp->a_perm, perm); 1841420Smarks (void) printf("default:group::%s\n", perm); 1851420Smarks break; 1861420Smarks case DEF_CLASS_OBJ: 1871420Smarks aclent_perms(tp->a_perm, perm); 1881420Smarks (void) printf("default:mask:%s\n", perm); 1891420Smarks break; 1901420Smarks case DEF_OTHER_OBJ: 1911420Smarks aclent_perms(tp->a_perm, perm); 1921420Smarks (void) printf("default:other:%s\n", perm); 1931420Smarks break; 1941420Smarks default: 1951420Smarks (void) fprintf(stderr, 1961567Smarks dgettext(TEXT_DOMAIN, "unrecognized entry\n")); 1971420Smarks break; 1981420Smarks } 1991420Smarks } 2001420Smarks } 2011420Smarks 2021420Smarks static void 2031420Smarks split_line(char *str, int cols) 2041420Smarks { 2051420Smarks char *ptr; 2061420Smarks int len; 2071420Smarks int i; 2081420Smarks int last_split; 2091420Smarks char *pad = ""; 2101420Smarks int pad_len; 2111420Smarks 2121420Smarks len = strlen(str); 2131420Smarks ptr = str; 2141420Smarks pad_len = 0; 2151420Smarks 2161420Smarks ptr = str; 2171420Smarks last_split = 0; 2181420Smarks for (i = 0; i != len; i++) { 2191420Smarks if ((i + pad_len + 4) >= cols) { 2201420Smarks (void) printf("%s%.*s\n", pad, last_split, ptr); 2211420Smarks ptr = &ptr[last_split]; 2221420Smarks len = strlen(ptr); 2231420Smarks i = 0; 2241420Smarks pad_len = 4; 2251420Smarks pad = " "; 2261420Smarks } else { 2271420Smarks if (ptr[i] == '/' || ptr[i] == ':') { 2281420Smarks last_split = i; 2291420Smarks } 2301420Smarks } 2311420Smarks } 2321420Smarks if (i == len) { 2331420Smarks (void) printf("%s%s\n", pad, ptr); 2341420Smarks } 2351420Smarks } 2361420Smarks 2371420Smarks #define OWNERAT_TXT "owner@" 2381420Smarks #define GROUPAT_TXT "group@" 2391420Smarks #define EVERYONEAT_TXT "everyone@" 2401420Smarks #define GROUP_TXT "group:" 2411420Smarks #define USER_TXT "user:" 2421420Smarks 2431420Smarks char * 2441515Sgjelinek ace_type_txt(char *buf, char **endp, ace_t *acep, int flags) 2451420Smarks { 2461420Smarks 2471535Smarks char idp[ID_STR_MAX]; 2481420Smarks 2491420Smarks if (buf == NULL) 2501420Smarks return (NULL); 2511420Smarks 2521420Smarks switch (acep->a_flags & ACE_TYPE_FLAGS) { 2531420Smarks case ACE_OWNER: 2541420Smarks strcpy(buf, OWNERAT_TXT); 2551420Smarks *endp = buf + sizeof (OWNERAT_TXT) - 1; 2561420Smarks break; 2571420Smarks 2581420Smarks case ACE_GROUP|ACE_IDENTIFIER_GROUP: 2591420Smarks strcpy(buf, GROUPAT_TXT); 2601420Smarks *endp = buf + sizeof (GROUPAT_TXT) - 1; 2611420Smarks break; 2621420Smarks 2631420Smarks case ACE_IDENTIFIER_GROUP: 2641420Smarks strcpy(buf, GROUP_TXT); 2651535Smarks strcat(buf, prgname(acep->a_who, idp, 2661535Smarks sizeof (idp), flags & ACL_NORESOLVE)); 2671420Smarks *endp = buf + strlen(buf); 2681420Smarks break; 2691420Smarks 2701420Smarks case ACE_EVERYONE: 2711420Smarks strcpy(buf, EVERYONEAT_TXT); 2721420Smarks *endp = buf + sizeof (EVERYONEAT_TXT) - 1; 2731420Smarks break; 2741420Smarks 2751420Smarks case 0: 2761420Smarks strcpy(buf, USER_TXT); 2771535Smarks strcat(buf, pruname(acep->a_who, idp, 2781535Smarks sizeof (idp), flags & ACL_NORESOLVE)); 2791420Smarks *endp = buf + strlen(buf); 2801420Smarks break; 2811420Smarks } 2821420Smarks 2831420Smarks return (buf); 2841420Smarks } 2851420Smarks 2861420Smarks #define READ_DATA_TXT "read_data/" 2871420Smarks #define WRITE_DATA_TXT "write_data/" 2881420Smarks #define EXECUTE_TXT "execute/" 2891420Smarks #define READ_XATTR_TXT "read_xattr/" 2901420Smarks #define WRITE_XATTR_TXT "write_xattr/" 2911420Smarks #define READ_ATTRIBUTES_TXT "read_attributes/" 2921420Smarks #define WRITE_ATTRIBUTES_TXT "write_attributes/" 2931420Smarks #define DELETE_TXT "delete/" 2941420Smarks #define DELETE_CHILD_TXT "delete_child/" 2951420Smarks #define WRITE_OWNER_TXT "write_owner/" 2961420Smarks #define READ_ACL_TXT "read_acl/" 2971420Smarks #define WRITE_ACL_TXT "write_acl/" 2981420Smarks #define APPEND_DATA_TXT "append_data/" 2991420Smarks #define READ_DIR_TXT "list_directory/read_data/" 3001420Smarks #define ADD_DIR_TXT "add_subdirectory/append_data/" 3011420Smarks #define ADD_FILE_TXT "add_file/write_data/" 3021420Smarks #define SYNCHRONIZE_TXT "synchronize" /* not slash on this one */ 3031420Smarks 3041420Smarks char * 3051420Smarks ace_perm_txt(char *buf, char **endp, uint32_t mask, 3061420Smarks uint32_t iflags, int isdir, int flags) 3071420Smarks { 3081420Smarks char *lend = buf; /* local end */ 3091420Smarks 3101420Smarks if (buf == NULL) 3111420Smarks return (NULL); 3121420Smarks 3131420Smarks if (flags & ACL_COMPACT_FMT) { 314789Sahrens 3151420Smarks if (mask & ACE_READ_DATA) 3161420Smarks buf[0] = 'r'; 3171420Smarks else 3181420Smarks buf[0] = '-'; 3191420Smarks if (mask & ACE_WRITE_DATA) 3201420Smarks buf[1] = 'w'; 3211420Smarks else 3221420Smarks buf[1] = '-'; 3231420Smarks if (mask & ACE_EXECUTE) 3241420Smarks buf[2] = 'x'; 3251420Smarks else 3261420Smarks buf[2] = '-'; 3271420Smarks if (mask & ACE_APPEND_DATA) 3281420Smarks buf[3] = 'p'; 3291420Smarks else 3301420Smarks buf[3] = '-'; 3311420Smarks if (mask & ACE_DELETE) 3321420Smarks buf[4] = 'd'; 3331420Smarks else 3341420Smarks buf[4] = '-'; 3351420Smarks if (mask & ACE_DELETE_CHILD) 3361420Smarks buf[5] = 'D'; 3371420Smarks else 3381420Smarks buf[5] = '-'; 3391420Smarks if (mask & ACE_READ_ATTRIBUTES) 3401420Smarks buf[6] = 'a'; 3411420Smarks else 3421420Smarks buf[6] = '-'; 3431420Smarks if (mask & ACE_WRITE_ATTRIBUTES) 3441420Smarks buf[7] = 'A'; 3451420Smarks else 3461420Smarks buf[7] = '-'; 3471420Smarks if (mask & ACE_READ_NAMED_ATTRS) 3481420Smarks buf[8] = 'R'; 3491420Smarks else 3501420Smarks buf[8] = '-'; 3511420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) 3521420Smarks buf[9] = 'W'; 3531420Smarks else 3541420Smarks buf[9] = '-'; 3551420Smarks if (mask & ACE_READ_ACL) 3561420Smarks buf[10] = 'c'; 3571420Smarks else 3581420Smarks buf[10] = '-'; 3591420Smarks if (mask & ACE_WRITE_ACL) 3601420Smarks buf[11] = 'C'; 3611420Smarks else 3621420Smarks buf[11] = '-'; 3631420Smarks if (mask & ACE_WRITE_OWNER) 3641420Smarks buf[12] = 'o'; 3651420Smarks else 3661420Smarks buf[12] = '-'; 3671420Smarks if (mask & ACE_SYNCHRONIZE) 3681420Smarks buf[13] = 's'; 3691420Smarks else 3701420Smarks buf[13] = '-'; 3711420Smarks buf[14] = '\0'; 3721420Smarks *endp = buf + 14; 3731420Smarks return (buf); 3741420Smarks } else { 3751420Smarks /* 3761420Smarks * If ACE is a directory, but inheritance indicates its 3771420Smarks * for a file then print permissions for file rather than 3781420Smarks * dir. 3791420Smarks */ 3801420Smarks if (isdir) { 3811420Smarks if (mask & ACE_LIST_DIRECTORY) { 3821420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 3831420Smarks strcpy(lend, READ_DATA_TXT); 3841420Smarks lend += sizeof (READ_DATA_TXT) - 1; 3851420Smarks } else { 3861420Smarks strcpy(lend, READ_DIR_TXT); 3871420Smarks lend += sizeof (READ_DIR_TXT) - 1; 3881420Smarks } 3891420Smarks } 3901420Smarks if (mask & ACE_ADD_FILE) { 3911420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 3921420Smarks strcpy(lend, WRITE_DATA_TXT); 3931420Smarks lend += sizeof (WRITE_DATA_TXT) - 1; 3941420Smarks } else { 3951420Smarks strcpy(lend, ADD_FILE_TXT); 3961420Smarks lend += 3971420Smarks sizeof (ADD_FILE_TXT) -1; 3981420Smarks } 3991420Smarks } 4001420Smarks if (mask & ACE_ADD_SUBDIRECTORY) { 4011420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 4021420Smarks strcpy(lend, APPEND_DATA_TXT); 4031420Smarks lend += sizeof (APPEND_DATA_TXT) - 1; 4041420Smarks } else { 4051420Smarks strcpy(lend, ADD_DIR_TXT); 4061420Smarks lend += sizeof (ADD_DIR_TXT) - 1; 4071420Smarks } 4081420Smarks } 4091420Smarks } else { 4101420Smarks if (mask & ACE_READ_DATA) { 4111420Smarks strcpy(lend, READ_DATA_TXT); 4121420Smarks lend += sizeof (READ_DATA_TXT) - 1; 4131420Smarks } 4141420Smarks if (mask & ACE_WRITE_DATA) { 4151420Smarks strcpy(lend, WRITE_DATA_TXT); 4161420Smarks lend += sizeof (WRITE_DATA_TXT) - 1; 4171420Smarks } 4181420Smarks if (mask & ACE_APPEND_DATA) { 4191420Smarks strcpy(lend, APPEND_DATA_TXT); 4201420Smarks lend += sizeof (APPEND_DATA_TXT) - 1; 4211420Smarks } 4221420Smarks } 4231420Smarks if (mask & ACE_READ_NAMED_ATTRS) { 4241420Smarks strcpy(lend, READ_XATTR_TXT); 4251420Smarks lend += sizeof (READ_XATTR_TXT) - 1; 4261420Smarks } 4271420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) { 4281420Smarks strcpy(lend, WRITE_XATTR_TXT); 4291420Smarks lend += sizeof (WRITE_XATTR_TXT) - 1; 4301420Smarks } 4311420Smarks if (mask & ACE_EXECUTE) { 4321420Smarks strcpy(lend, EXECUTE_TXT); 4331420Smarks lend += sizeof (EXECUTE_TXT) - 1; 4341420Smarks } 4351420Smarks if (mask & ACE_DELETE_CHILD) { 4361420Smarks strcpy(lend, DELETE_CHILD_TXT); 4371420Smarks lend += sizeof (DELETE_CHILD_TXT) - 1; 4381420Smarks } 4391420Smarks if (mask & ACE_READ_ATTRIBUTES) { 4401420Smarks strcpy(lend, READ_ATTRIBUTES_TXT); 4411420Smarks lend += sizeof (READ_ATTRIBUTES_TXT) - 1; 4421420Smarks } 4431420Smarks if (mask & ACE_WRITE_ATTRIBUTES) { 4441420Smarks strcpy(lend, WRITE_ATTRIBUTES_TXT); 4451420Smarks lend += sizeof (WRITE_ATTRIBUTES_TXT) - 1; 4461420Smarks } 4471420Smarks if (mask & ACE_DELETE) { 4481420Smarks strcpy(lend, DELETE_TXT); 4491420Smarks lend += sizeof (DELETE_TXT) - 1; 4501420Smarks } 4511420Smarks if (mask & ACE_READ_ACL) { 4521420Smarks strcpy(lend, READ_ACL_TXT); 4531420Smarks lend += sizeof (READ_ACL_TXT) - 1; 4541420Smarks } 4551420Smarks if (mask & ACE_WRITE_ACL) { 4561420Smarks strcpy(lend, WRITE_ACL_TXT); 4571420Smarks lend += sizeof (WRITE_ACL_TXT) - 1; 4581420Smarks } 4591420Smarks if (mask & ACE_WRITE_OWNER) { 4601420Smarks strcpy(lend, WRITE_OWNER_TXT); 4611420Smarks lend += sizeof (WRITE_OWNER_TXT) - 1; 4621420Smarks } 4631420Smarks if (mask & ACE_SYNCHRONIZE) { 4641420Smarks strcpy(lend, SYNCHRONIZE_TXT); 4651420Smarks lend += sizeof (SYNCHRONIZE_TXT) - 1; 4661420Smarks } 467789Sahrens 4681420Smarks if (*(lend - 1) == '/') 4691420Smarks *--lend = '\0'; 4701420Smarks } 4711420Smarks 4721420Smarks *endp = lend; 4731420Smarks return (buf); 4741420Smarks } 4751420Smarks 4761420Smarks #define ALLOW_TXT "allow" 4771420Smarks #define DENY_TXT "deny" 4781420Smarks #define ALARM_TXT "alarm" 4791420Smarks #define AUDIT_TXT "audit" 4801420Smarks #define UNKNOWN_TXT "unknown" 4811420Smarks char * 4821420Smarks ace_access_txt(char *buf, char **endp, int type) 4831420Smarks { 4841420Smarks 4851420Smarks if (buf == NULL) 4861420Smarks return (NULL); 4871420Smarks 4881420Smarks if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 4891420Smarks strcpy(buf, ALLOW_TXT); 4901420Smarks *endp += sizeof (ALLOW_TXT) - 1; 4911420Smarks } else if (type == ACE_ACCESS_DENIED_ACE_TYPE) { 4921420Smarks strcpy(buf, DENY_TXT); 4931420Smarks *endp += sizeof (DENY_TXT) - 1; 4941420Smarks } else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) { 4951420Smarks strcpy(buf, AUDIT_TXT); 4961420Smarks *endp += sizeof (AUDIT_TXT) - 1; 4971420Smarks } else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) { 4981420Smarks strcpy(buf, ALARM_TXT); 4991420Smarks *endp += sizeof (ALARM_TXT) - 1; 5001420Smarks } else { 5011420Smarks strcpy(buf, UNKNOWN_TXT); 5021420Smarks *endp += sizeof (UNKNOWN_TXT) - 1; 5031420Smarks } 5041420Smarks 5051420Smarks return (buf); 5061420Smarks } 5071420Smarks 5081420Smarks static char * 5091420Smarks ace_inherit_txt(char *buf, char **endp, uint32_t iflags, int flags) 5101420Smarks { 5111420Smarks 5121420Smarks char *lend = buf; 5131420Smarks 5141420Smarks if (buf == NULL) { 5151420Smarks return (NULL); 5161420Smarks } 517789Sahrens 5181420Smarks if (flags & ACL_COMPACT_FMT) { 5191420Smarks if (iflags & ACE_FILE_INHERIT_ACE) 5201420Smarks buf[0] = 'f'; 5211420Smarks else 5221420Smarks buf[0] = '-'; 5231420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) 5241420Smarks buf[1] = 'd'; 5251420Smarks else 5261420Smarks buf[1] = '-'; 5271420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) 5281420Smarks buf[2] = 'i'; 5291420Smarks else 5301420Smarks buf[2] = '-'; 5311420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) 5321420Smarks buf[3] = 'n'; 5331420Smarks else 5341420Smarks buf[3] = '-'; 5351420Smarks if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 5361420Smarks buf[4] = 'S'; 5371420Smarks else 5381420Smarks buf[4] = '-'; 5391420Smarks if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) 5401420Smarks buf[5] = 'F'; 5411420Smarks else 5421420Smarks buf[5] = '-'; 543*5331Samw if (iflags & ACE_INHERITED_ACE) 544*5331Samw buf[6] = 'I'; 545*5331Samw else 546*5331Samw buf[6] = '-'; 547*5331Samw buf[7] = '\0'; 548*5331Samw *endp = buf + 7; 5491420Smarks } else { 5501420Smarks if (iflags & ACE_FILE_INHERIT_ACE) { 5511420Smarks strcpy(lend, "file_inherit/"); 5521420Smarks lend += sizeof ("file_inherit/") - 1; 5531420Smarks } 5541420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) { 5551420Smarks strcpy(lend, "dir_inherit/"); 5561420Smarks lend += sizeof ("dir_inherit/") - 1; 5571420Smarks } 5581420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) { 5591420Smarks strcpy(lend, "no_propagate/"); 5601420Smarks lend += sizeof ("no_propagate/") - 1; 5611420Smarks } 5621420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) { 5631420Smarks strcpy(lend, "inherit_only/"); 5641420Smarks lend += sizeof ("inherit_only/") - 1; 5651420Smarks } 566*5331Samw if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) { 567*5331Samw strcpy(lend, "successful_access/"); 568*5331Samw lend += sizeof ("successful_access/") - 1; 569*5331Samw } 570*5331Samw if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) { 571*5331Samw strcpy(lend, "failed_access/"); 572*5331Samw lend += sizeof ("failed_access/") - 1; 573*5331Samw } 574*5331Samw if (iflags & ACE_INHERITED_ACE) { 575*5331Samw strcpy(lend, "inherited/"); 576*5331Samw lend += sizeof ("inherited/") - 1; 577*5331Samw } 578789Sahrens 5791420Smarks if (*(lend - 1) == '/') 5801420Smarks *--lend = '\0'; 5811420Smarks *endp = lend; 5821420Smarks } 5831420Smarks 5841420Smarks return (buf); 585789Sahrens } 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate /* 5880Sstevel@tonic-gate * Convert internal acl representation to external representation. 5890Sstevel@tonic-gate * 5900Sstevel@tonic-gate * The length of a non-owning user name or non-owning group name ie entries 5910Sstevel@tonic-gate * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We 5920Sstevel@tonic-gate * thus check the length of these entries, and if greater than LOGNAME_MAX, 5930Sstevel@tonic-gate * we realloc() via increase_length(). 5940Sstevel@tonic-gate * 5950Sstevel@tonic-gate * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always 5960Sstevel@tonic-gate * adhered to. 5970Sstevel@tonic-gate */ 5981420Smarks 5991420Smarks /* 6001420Smarks * acltotext() converts each ACL entry to look like this: 6011420Smarks * 6021420Smarks * entry_type:uid^gid^name:perms[:id] 6031420Smarks * 6041420Smarks * The maximum length of entry_type is 14 ("defaultgroup::" and 6051420Smarks * "defaultother::") hence ENTRYTYPELEN is set to 14. 6061420Smarks * 6071420Smarks * The max length of a uid^gid^name entry (in theory) is 8, hence we use, 6081420Smarks * however the ID could be a number so we therefore use ID_STR_MAX 6091420Smarks * 6101420Smarks * The length of a perms entry is 4 to allow for the comma appended to each 6111420Smarks * to each acl entry. Hence PERMS is set to 4. 6121420Smarks */ 6131420Smarks 6141420Smarks #define ENTRYTYPELEN 14 6151420Smarks #define PERMS 4 6161420Smarks #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX) 6171420Smarks #define UPDATE_WHERE where = dstr->aclexport + strlen(dstr->aclexport) 6181420Smarks 6190Sstevel@tonic-gate char * 6201420Smarks aclent_acltotext(aclent_t *aclp, int aclcnt, int flags) 6210Sstevel@tonic-gate { 6220Sstevel@tonic-gate char *aclexport; 6230Sstevel@tonic-gate char *where; 6241507Sgjelinek struct group *groupp = NULL; 6251507Sgjelinek struct passwd *passwdp = NULL; 6260Sstevel@tonic-gate struct dynaclstr *dstr; 6270Sstevel@tonic-gate int i, rtn; 6280Sstevel@tonic-gate size_t excess = 0; 6291535Smarks char id[ID_STR_MAX], *idstr; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate if (aclp == NULL) 6320Sstevel@tonic-gate return (NULL); 6330Sstevel@tonic-gate if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL) 6340Sstevel@tonic-gate return (NULL); 6350Sstevel@tonic-gate dstr->bufsize = aclcnt * ACL_ENTRY_SIZE; 6360Sstevel@tonic-gate if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) { 6370Sstevel@tonic-gate free(dstr); 6380Sstevel@tonic-gate return (NULL); 6390Sstevel@tonic-gate } 6400Sstevel@tonic-gate *dstr->aclexport = '\0'; 6410Sstevel@tonic-gate where = dstr->aclexport; 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate for (i = 0; i < aclcnt; i++, aclp++) { 6440Sstevel@tonic-gate switch (aclp->a_type) { 6450Sstevel@tonic-gate case DEF_USER_OBJ: 6460Sstevel@tonic-gate case USER_OBJ: 6470Sstevel@tonic-gate if (aclp->a_type == USER_OBJ) 6480Sstevel@tonic-gate where = strappend(where, "user::"); 6490Sstevel@tonic-gate else 6500Sstevel@tonic-gate where = strappend(where, "defaultuser::"); 6510Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6520Sstevel@tonic-gate break; 6530Sstevel@tonic-gate case DEF_USER: 6540Sstevel@tonic-gate case USER: 6550Sstevel@tonic-gate if (aclp->a_type == USER) 6560Sstevel@tonic-gate where = strappend(where, "user:"); 6570Sstevel@tonic-gate else 6580Sstevel@tonic-gate where = strappend(where, "defaultuser:"); 6591507Sgjelinek if ((flags & ACL_NORESOLVE) == 0) 6601507Sgjelinek passwdp = getpwuid(aclp->a_id); 6610Sstevel@tonic-gate if (passwdp == (struct passwd *)NULL) { 6620Sstevel@tonic-gate /* put in uid instead */ 6630Sstevel@tonic-gate (void) sprintf(where, "%d", aclp->a_id); 664922Shm123892 UPDATE_WHERE; 6650Sstevel@tonic-gate } else { 6660Sstevel@tonic-gate excess = strlen(passwdp->pw_name) - LOGNAME_MAX; 6670Sstevel@tonic-gate if (excess > 0) { 6680Sstevel@tonic-gate rtn = increase_length(dstr, excess); 6690Sstevel@tonic-gate if (rtn == 1) { 670922Shm123892 UPDATE_WHERE; 6710Sstevel@tonic-gate } else { 6720Sstevel@tonic-gate free(dstr->aclexport); 6730Sstevel@tonic-gate free(dstr); 6740Sstevel@tonic-gate return (NULL); 6750Sstevel@tonic-gate } 6760Sstevel@tonic-gate } 6770Sstevel@tonic-gate where = strappend(where, passwdp->pw_name); 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate where = strappend(where, ":"); 6800Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6810Sstevel@tonic-gate break; 6820Sstevel@tonic-gate case DEF_GROUP_OBJ: 6830Sstevel@tonic-gate case GROUP_OBJ: 6840Sstevel@tonic-gate if (aclp->a_type == GROUP_OBJ) 6850Sstevel@tonic-gate where = strappend(where, "group::"); 6860Sstevel@tonic-gate else 6870Sstevel@tonic-gate where = strappend(where, "defaultgroup::"); 6880Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6890Sstevel@tonic-gate break; 6900Sstevel@tonic-gate case DEF_GROUP: 6910Sstevel@tonic-gate case GROUP: 6920Sstevel@tonic-gate if (aclp->a_type == GROUP) 6930Sstevel@tonic-gate where = strappend(where, "group:"); 6940Sstevel@tonic-gate else 6950Sstevel@tonic-gate where = strappend(where, "defaultgroup:"); 6961507Sgjelinek if ((flags & ACL_NORESOLVE) == 0) 6971507Sgjelinek groupp = getgrgid(aclp->a_id); 6980Sstevel@tonic-gate if (groupp == (struct group *)NULL) { 6990Sstevel@tonic-gate /* put in gid instead */ 7000Sstevel@tonic-gate (void) sprintf(where, "%d", aclp->a_id); 701922Shm123892 UPDATE_WHERE; 7020Sstevel@tonic-gate } else { 7030Sstevel@tonic-gate excess = strlen(groupp->gr_name) - LOGNAME_MAX; 7040Sstevel@tonic-gate if (excess > 0) { 7050Sstevel@tonic-gate rtn = increase_length(dstr, excess); 7060Sstevel@tonic-gate if (rtn == 1) { 707922Shm123892 UPDATE_WHERE; 7080Sstevel@tonic-gate } else { 7090Sstevel@tonic-gate free(dstr->aclexport); 7100Sstevel@tonic-gate free(dstr); 7110Sstevel@tonic-gate return (NULL); 7120Sstevel@tonic-gate } 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate where = strappend(where, groupp->gr_name); 7150Sstevel@tonic-gate } 7160Sstevel@tonic-gate where = strappend(where, ":"); 7170Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7180Sstevel@tonic-gate break; 7190Sstevel@tonic-gate case DEF_CLASS_OBJ: 7200Sstevel@tonic-gate case CLASS_OBJ: 7210Sstevel@tonic-gate if (aclp->a_type == CLASS_OBJ) 7220Sstevel@tonic-gate where = strappend(where, "mask:"); 7230Sstevel@tonic-gate else 7240Sstevel@tonic-gate where = strappend(where, "defaultmask:"); 7250Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7260Sstevel@tonic-gate break; 7270Sstevel@tonic-gate case DEF_OTHER_OBJ: 7280Sstevel@tonic-gate case OTHER_OBJ: 7290Sstevel@tonic-gate if (aclp->a_type == OTHER_OBJ) 7300Sstevel@tonic-gate where = strappend(where, "other:"); 7310Sstevel@tonic-gate else 7320Sstevel@tonic-gate where = strappend(where, "defaultother:"); 7330Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7340Sstevel@tonic-gate break; 7350Sstevel@tonic-gate default: 7360Sstevel@tonic-gate free(dstr->aclexport); 7370Sstevel@tonic-gate free(dstr); 7380Sstevel@tonic-gate return (NULL); 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate } 7411420Smarks 7421420Smarks if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) || 7431420Smarks (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) || 7441420Smarks (aclp->a_type == DEF_GROUP))) { 7451420Smarks where = strappend(where, ":"); 7461420Smarks id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */ 7471420Smarks idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]); 7481420Smarks where = strappend(where, idstr); 7491420Smarks } 7500Sstevel@tonic-gate if (i < aclcnt - 1) 7510Sstevel@tonic-gate where = strappend(where, ","); 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate aclexport = dstr->aclexport; 7540Sstevel@tonic-gate free(dstr); 7550Sstevel@tonic-gate return (aclexport); 7561420Smarks 7571420Smarks 7581420Smarks 7591420Smarks 7600Sstevel@tonic-gate } 7610Sstevel@tonic-gate 7621420Smarks char * 7631420Smarks acltotext(aclent_t *aclp, int aclcnt) 7640Sstevel@tonic-gate { 7651420Smarks return (aclent_acltotext(aclp, aclcnt, 0)); 7661420Smarks } 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate 769789Sahrens aclent_t * 770789Sahrens aclfromtext(char *aclstr, int *aclcnt) 771789Sahrens { 772789Sahrens acl_t *aclp; 773789Sahrens aclent_t *aclentp; 774789Sahrens int error; 775789Sahrens 7761420Smarks error = acl_fromtext(aclstr, &aclp); 777789Sahrens if (error) 778789Sahrens return (NULL); 779789Sahrens 780789Sahrens aclentp = aclp->acl_aclp; 781789Sahrens aclp->acl_aclp = NULL; 7821420Smarks *aclcnt = aclp->acl_cnt; 783789Sahrens 7841420Smarks acl_free(aclp); 785789Sahrens return (aclentp); 786789Sahrens } 787789Sahrens 788789Sahrens 7890Sstevel@tonic-gate static char * 7900Sstevel@tonic-gate strappend(char *where, char *newstr) 7910Sstevel@tonic-gate { 7920Sstevel@tonic-gate (void) strcat(where, newstr); 7930Sstevel@tonic-gate return (where + strlen(newstr)); 7940Sstevel@tonic-gate } 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate static char * 7970Sstevel@tonic-gate convert_perm(char *where, o_mode_t perm) 7980Sstevel@tonic-gate { 7991420Smarks if (perm & S_IROTH) 8000Sstevel@tonic-gate where = strappend(where, "r"); 8010Sstevel@tonic-gate else 8020Sstevel@tonic-gate where = strappend(where, "-"); 8031420Smarks if (perm & S_IWOTH) 8040Sstevel@tonic-gate where = strappend(where, "w"); 8050Sstevel@tonic-gate else 8060Sstevel@tonic-gate where = strappend(where, "-"); 8071420Smarks if (perm & S_IXOTH) 8080Sstevel@tonic-gate where = strappend(where, "x"); 8090Sstevel@tonic-gate else 8100Sstevel@tonic-gate where = strappend(where, "-"); 8110Sstevel@tonic-gate /* perm is the last field */ 8120Sstevel@tonic-gate return (where); 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate 8150Sstevel@tonic-gate /* 8160Sstevel@tonic-gate * Callers should check the return code as this routine may change the string 8170Sstevel@tonic-gate * pointer in dynaclstr. 8180Sstevel@tonic-gate */ 8190Sstevel@tonic-gate static int 8200Sstevel@tonic-gate increase_length(struct dynaclstr *dacl, size_t increase) 8210Sstevel@tonic-gate { 8220Sstevel@tonic-gate char *tptr; 8230Sstevel@tonic-gate size_t newsize; 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate newsize = dacl->bufsize + increase; 8260Sstevel@tonic-gate tptr = realloc(dacl->aclexport, newsize); 8270Sstevel@tonic-gate if (tptr != NULL) { 8280Sstevel@tonic-gate dacl->aclexport = tptr; 8290Sstevel@tonic-gate dacl->bufsize = newsize; 8300Sstevel@tonic-gate return (1); 8310Sstevel@tonic-gate } else 8320Sstevel@tonic-gate return (0); 8330Sstevel@tonic-gate } 834789Sahrens 835789Sahrens /* 8361420Smarks * ace_acltotext() convert each ace formatted acl to look like this: 837789Sahrens * 8381420Smarks * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,] 839789Sahrens * 840789Sahrens * The maximum length of entry_type is 5 ("group") 841789Sahrens * 8421420Smarks * The max length of a uid^gid^name entry (in theory) is 8, 8431420Smarks * however id could be a number so we therefore use ID_STR_MAX 844789Sahrens * 845789Sahrens * The length of a perms entry is 144 i.e read_data/write_data... 846789Sahrens * to each acl entry. 847789Sahrens * 848*5331Samw * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access 849*5331Samw * /failed_access 850789Sahrens * 851789Sahrens */ 852789Sahrens 853789Sahrens #define ACE_ENTRYTYPLEN 6 854*5331Samw #define IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \ 855*5331Samw "successful_access/failed_access/inherited" 856*5331Samw #define IFLAGS_SIZE (sizeof (IFLAGS_STR) - 1) 8571420Smarks #define ACCESS_TYPE_SIZE 7 /* if unknown */ 858789Sahrens #define COLON_CNT 3 859789Sahrens #define PERMS_LEN 216 860*5331Samw #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \ 8611420Smarks ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX) 862789Sahrens 863789Sahrens static char * 8641420Smarks ace_acltotext(acl_t *aceaclp, int flags) 865789Sahrens { 866789Sahrens ace_t *aclp = aceaclp->acl_aclp; 867789Sahrens int aclcnt = aceaclp->acl_cnt; 868789Sahrens char *aclexport; 8691420Smarks char *endp; 8701420Smarks int i; 8711420Smarks char id[ID_STR_MAX], *idstr; 872789Sahrens int isdir = (aceaclp->acl_flags & ACL_IS_DIR); 873789Sahrens 874789Sahrens if (aclp == NULL) 875789Sahrens return (NULL); 8761420Smarks if ((aclexport = malloc(aclcnt * ACE_ENTRY_SIZE)) == NULL) 877789Sahrens return (NULL); 878789Sahrens 8791420Smarks aclexport[0] = '\0'; 8801420Smarks endp = aclexport; 881789Sahrens for (i = 0; i < aclcnt; i++, aclp++) { 8821420Smarks 8831515Sgjelinek (void) ace_type_txt(endp, &endp, aclp, flags); 8841420Smarks *endp++ = ':'; 8851420Smarks *endp = '\0'; 8861420Smarks (void) ace_perm_txt(endp, &endp, aclp->a_access_mask, 8871420Smarks aclp->a_flags, isdir, flags); 8881420Smarks *endp++ = ':'; 8891420Smarks *endp = '\0'; 8901420Smarks (void) ace_inherit_txt(endp, &endp, aclp->a_flags, flags); 8911420Smarks if (flags & ACL_COMPACT_FMT || aclp->a_flags & 8921420Smarks (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE | 893*5331Samw (ACE_INHERIT_ONLY_ACE | ACE_NO_PROPAGATE_INHERIT_ACE | 894*5331Samw ACE_INHERITED_ACE | ACE_SUCCESSFUL_ACCESS_ACE_FLAG | 895*5331Samw ACE_FAILED_ACCESS_ACE_FLAG))) { 8961420Smarks *endp++ = ':'; 8971420Smarks *endp = '\0'; 8981420Smarks } 8991420Smarks (void) ace_access_txt(endp, &endp, aclp->a_type); 900789Sahrens 9011420Smarks if ((flags & ACL_APPEND_ID) && 9021420Smarks (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) || 9031420Smarks ((aclp->a_flags & ACE_TYPE_FLAGS) == 9041420Smarks ACE_IDENTIFIER_GROUP))) { 9051420Smarks *endp++ = ':'; 9061420Smarks *endp = '\0'; 9071420Smarks id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */ 9081420Smarks idstr = lltostr(aclp->a_who, &id[ID_STR_MAX - 1]); 9091420Smarks strcpy(endp, idstr); 9101420Smarks endp += strlen(idstr); 911789Sahrens } 9121420Smarks if (i < aclcnt - 1) { 9131420Smarks *endp++ = ','; 9141420Smarks *(endp + 1) = '\0'; 915789Sahrens } 916789Sahrens } 917789Sahrens return (aclexport); 918789Sahrens } 919789Sahrens 9201420Smarks char * 9211420Smarks acl_totext(acl_t *aclp, int flags) 922789Sahrens { 923789Sahrens 9241420Smarks char *txtp; 925789Sahrens 926789Sahrens if (aclp == NULL) 927789Sahrens return (NULL); 928789Sahrens 929789Sahrens switch (aclp->acl_type) { 930789Sahrens case ACE_T: 9311420Smarks txtp = ace_acltotext(aclp, flags); 9321420Smarks break; 933789Sahrens case ACLENT_T: 9341420Smarks txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags); 9351420Smarks break; 936789Sahrens } 9371420Smarks 9381420Smarks return (txtp); 939789Sahrens } 940789Sahrens 941789Sahrens int 942789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp) 943789Sahrens { 9441420Smarks int error; 9451420Smarks char *buf; 9461420Smarks 9471420Smarks buf = malloc(strlen(acltextp) + 2); 9481420Smarks if (buf == NULL) 9491420Smarks return (EACL_MEM_ERROR); 9501420Smarks strcpy(buf, acltextp); 9511420Smarks strcat(buf, "\n"); 9521420Smarks yybuf = buf; 9531420Smarks yyreset(); 9541420Smarks error = yyparse(); 9551420Smarks free(buf); 9561420Smarks 9571420Smarks if (yyacl) { 9581420Smarks if (error == 0) 9591420Smarks *ret_aclp = yyacl; 9601420Smarks else { 9611420Smarks acl_free(yyacl); 9621420Smarks } 9631420Smarks yyacl = NULL; 9641420Smarks } 9651420Smarks return (error); 9661420Smarks } 9671420Smarks 9681420Smarks int 9691420Smarks acl_parse(const char *acltextp, acl_t **aclp) 9701420Smarks { 971789Sahrens int error; 972789Sahrens 9731420Smarks yyinteractive = 1; 9741420Smarks error = acl_fromtext(acltextp, aclp); 9751420Smarks yyinteractive = 0; 9761420Smarks return (error); 9771420Smarks } 9781420Smarks 9791420Smarks static void 9801420Smarks ace_compact_printacl(acl_t *aclp) 9811420Smarks { 9821420Smarks int cnt; 9831420Smarks ace_t *acep; 9841420Smarks char *endp; 9851420Smarks char buf[ACE_ENTRY_SIZE]; 986789Sahrens 9871420Smarks for (cnt = 0, acep = aclp->acl_aclp; 9881420Smarks cnt != aclp->acl_cnt; cnt++, acep++) { 9891420Smarks buf[0] = '\0'; 9901515Sgjelinek (void) printf(" %14s:", ace_type_txt(buf, &endp, acep, 0)); 9911420Smarks (void) printf("%s:", ace_perm_txt(endp, &endp, 9921420Smarks acep->a_access_mask, acep->a_flags, 9931420Smarks aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT)); 9941420Smarks (void) printf("%s:", 9951420Smarks ace_inherit_txt(endp, &endp, acep->a_flags, 996*5331Samw ACL_COMPACT_FMT)); 9971420Smarks (void) printf("%s\n", ace_access_txt(endp, &endp, 9981420Smarks acep->a_type)); 9991420Smarks } 10001420Smarks } 1001789Sahrens 10021420Smarks static void 10031420Smarks ace_printacl(acl_t *aclp, int cols, int compact) 10041420Smarks { 10051420Smarks int slot = 0; 10061420Smarks char *token; 10071420Smarks char *acltext; 10081420Smarks 10091420Smarks if (compact) { 10101420Smarks ace_compact_printacl(aclp); 10111420Smarks return; 1012789Sahrens } 1013789Sahrens 10141420Smarks acltext = acl_totext(aclp, 0); 10151420Smarks 10161420Smarks if (acltext == NULL) 10171420Smarks return; 10181420Smarks 10191420Smarks token = strtok(acltext, ","); 10201420Smarks if (token == NULL) { 10211420Smarks free(acltext); 10221420Smarks return; 1023789Sahrens } 1024789Sahrens 10251420Smarks do { 10261420Smarks (void) printf(" %d:", slot++); 10271420Smarks split_line(token, cols - 5); 10281420Smarks } while (token = strtok(NULL, ",")); 10291420Smarks free(acltext); 10301420Smarks } 10311420Smarks 10321420Smarks /* 10331420Smarks * pretty print an ACL. 10341420Smarks * For aclent_t ACL's the format is 10351420Smarks * similar to the old format used by getfacl, 10361420Smarks * with the addition of adding a "slot" number 10371420Smarks * before each entry. 10381420Smarks * 10391420Smarks * for ace_t ACL's the cols variable will break up 10401420Smarks * the long lines into multiple lines and will also 10411420Smarks * print a "slot" number. 10421420Smarks */ 10431420Smarks void 10441420Smarks acl_printacl(acl_t *aclp, int cols, int compact) 10451420Smarks { 10461420Smarks 10471420Smarks switch (aclp->acl_type) { 10481420Smarks case ACLENT_T: 10491420Smarks aclent_printacl(aclp); 10501420Smarks break; 10511420Smarks case ACE_T: 10521420Smarks ace_printacl(aclp, cols, compact); 10531420Smarks break; 10541420Smarks } 10551420Smarks } 10561420Smarks 10571420Smarks typedef struct value_table { 10581420Smarks char p_letter; /* perm letter such as 'r' */ 10591420Smarks uint32_t p_value; /* value for perm when pletter found */ 10601420Smarks } value_table_t; 10611420Smarks 10621420Smarks /* 1063*5331Samw * The permission tables are laid out in positional order 10641420Smarks * a '-' character will indicate a permission at a given 10651420Smarks * position is not specified. The '-' is not part of the 10661420Smarks * table, but will be checked for in the permission computation 10671420Smarks * routine. 10681420Smarks */ 1069*5331Samw value_table_t ace_perm_table[] = { 10701420Smarks { 'r', ACE_READ_DATA}, 10711420Smarks { 'w', ACE_WRITE_DATA}, 10721420Smarks { 'x', ACE_EXECUTE}, 10731420Smarks { 'p', ACE_APPEND_DATA}, 10741420Smarks { 'd', ACE_DELETE}, 10751420Smarks { 'D', ACE_DELETE_CHILD}, 10761420Smarks { 'a', ACE_READ_ATTRIBUTES}, 10771420Smarks { 'A', ACE_WRITE_ATTRIBUTES}, 10781420Smarks { 'R', ACE_READ_NAMED_ATTRS}, 10791420Smarks { 'W', ACE_WRITE_NAMED_ATTRS}, 10801420Smarks { 'c', ACE_READ_ACL}, 10811420Smarks { 'C', ACE_WRITE_ACL}, 10821420Smarks { 'o', ACE_WRITE_OWNER}, 10831420Smarks { 's', ACE_SYNCHRONIZE} 10841420Smarks }; 10851420Smarks 1086*5331Samw #define ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t)) 10871420Smarks 1088*5331Samw value_table_t aclent_perm_table[] = { 10891420Smarks { 'r', S_IROTH}, 10901420Smarks { 'w', S_IWOTH}, 10911420Smarks { 'x', S_IXOTH} 10921420Smarks }; 10931420Smarks 1094*5331Samw #define ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t)) 1095*5331Samw 1096*5331Samw value_table_t inherit_table[] = { 10971420Smarks {'f', ACE_FILE_INHERIT_ACE}, 10981420Smarks {'d', ACE_DIRECTORY_INHERIT_ACE}, 10991420Smarks {'i', ACE_INHERIT_ONLY_ACE}, 11001420Smarks {'n', ACE_NO_PROPAGATE_INHERIT_ACE}, 11011420Smarks {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 1102*5331Samw {'F', ACE_FAILED_ACCESS_ACE_FLAG}, 1103*5331Samw {'I', ACE_INHERITED_ACE} 11041420Smarks }; 11051420Smarks 1106*5331Samw #define IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t)) 1107*5331Samw 11081420Smarks /* 11091420Smarks * compute value from a permission table or inheritance table 11101420Smarks * based on string passed in. If positional is set then 11111420Smarks * string must match order in permtab, otherwise any order 11121420Smarks * is allowed. 11131420Smarks */ 11141420Smarks int 11151420Smarks compute_values(value_table_t *permtab, int count, 11161420Smarks char *permstr, int positional, uint32_t *mask) 11171420Smarks { 11181420Smarks uint32_t perm_val = 0; 11191420Smarks char *pstr; 11201420Smarks int i, found; 11211420Smarks 11221420Smarks if (count < 0) 11231420Smarks return (1); 11241420Smarks 11251420Smarks if (positional) { 11261420Smarks for (i = 0, pstr = permstr; i != count && pstr && 11271420Smarks *pstr; i++, pstr++) { 11281420Smarks if (*pstr == permtab[i].p_letter) { 11291420Smarks perm_val |= permtab[i].p_value; 11301420Smarks } else if (*pstr != '-') { 11311420Smarks return (1); 11321420Smarks } 1133789Sahrens } 11341420Smarks } else { /* random order single letters with no '-' */ 11351420Smarks for (pstr = permstr; pstr && *pstr; pstr++) { 11361420Smarks for (found = 0, i = 0; i != count; i++) { 11371420Smarks if (*pstr == permtab[i].p_letter) { 11381420Smarks perm_val |= permtab[i].p_value; 11391420Smarks found = 1; 11401420Smarks break; 11411420Smarks } 11421420Smarks } 11431420Smarks if (found == 0) 11441420Smarks return (1); 11451420Smarks } 1146789Sahrens } 1147789Sahrens 11481420Smarks *mask = perm_val; 11491420Smarks return (0); 11501420Smarks } 1151789Sahrens 11521420Smarks /* 11531420Smarks * compute value for inheritance flags. 11541420Smarks */ 11551420Smarks int 11561420Smarks compute_ace_inherit(char *str, uint32_t *imask) 11571420Smarks { 11581420Smarks int error; 11591420Smarks int positional = 0; 1160789Sahrens 11611420Smarks if (strlen(str) == IFLAG_COUNT) 11621420Smarks positional = 1; 11631420Smarks 11641420Smarks error = compute_values(inherit_table, IFLAG_COUNT, 11651420Smarks str, positional, imask); 11661420Smarks 11671420Smarks if (error) 11681420Smarks return (EACL_INHERIT_ERROR); 11691420Smarks 1170789Sahrens return (error); 1171789Sahrens } 11721420Smarks 11731420Smarks 11741420Smarks /* 11751420Smarks * compute value for ACE permissions. 11761420Smarks */ 11771420Smarks int 11781420Smarks compute_ace_perms(char *str, uint32_t *mask) 11791420Smarks { 11801420Smarks int positional = 0; 11811420Smarks int error; 11821420Smarks 11831420Smarks if (strlen(str) == ACE_PERM_COUNT) 11841420Smarks positional = 1; 11851420Smarks 11861420Smarks error = compute_values(ace_perm_table, ACE_PERM_COUNT, 11871420Smarks str, positional, mask); 11881420Smarks 11891420Smarks if (error && positional) { 11901420Smarks /* 11911420Smarks * If positional was set, then make sure permissions 11921420Smarks * aren't actually valid in non positional case where 11931420Smarks * all permissions are specified, just in random order. 11941420Smarks */ 11951420Smarks error = compute_values(ace_perm_table, 11961420Smarks ACE_PERM_COUNT, str, 0, mask); 11971420Smarks } 11981420Smarks if (error) 11991420Smarks error = EACL_PERM_MASK_ERROR; 12001420Smarks 12011420Smarks return (error); 12021420Smarks } 12031420Smarks 12041420Smarks 12051420Smarks 12061420Smarks /* 12071420Smarks * compute values for aclent permissions. 12081420Smarks */ 12091420Smarks int 12101420Smarks compute_aclent_perms(char *str, o_mode_t *mask) 12111420Smarks { 12121420Smarks int error; 12131420Smarks uint32_t pmask; 12141420Smarks 12151420Smarks if (strlen(str) != ACLENT_PERM_COUNT) 12161420Smarks return (EACL_PERM_MASK_ERROR); 12171420Smarks 12181420Smarks *mask = 0; 12191420Smarks error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT, 12201420Smarks str, 1, &pmask); 12211420Smarks if (error == 0) { 12221420Smarks *mask = (o_mode_t)pmask; 12231420Smarks } else 12241420Smarks error = EACL_PERM_MASK_ERROR; 12251420Smarks return (error); 12261420Smarks } 12271420Smarks 12281420Smarks /* 12291420Smarks * determine ACE permissions. 12301420Smarks */ 12311420Smarks int 12321420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask) 12331420Smarks { 12341420Smarks int error; 12351420Smarks 12361420Smarks if (aclperm->perm_style == PERM_TYPE_EMPTY) { 12371420Smarks *mask = 0; 12381420Smarks return (0); 12391420Smarks } 12401420Smarks 12411420Smarks if (aclperm->perm_style == PERM_TYPE_ACE) { 12421420Smarks *mask = aclperm->perm_val; 12431420Smarks return (0); 12441420Smarks } 12451420Smarks 12461420Smarks error = compute_ace_perms(aclperm->perm_str, mask); 12471420Smarks if (error) { 12481567Smarks acl_error(dgettext(TEXT_DOMAIN, 12491567Smarks "Invalid permission(s) '%s' specified\n"), 12501420Smarks aclperm->perm_str); 12511420Smarks return (EACL_PERM_MASK_ERROR); 12521420Smarks } 12531420Smarks 12541420Smarks return (0); 12551420Smarks } 1256