xref: /titanic_44/usr/src/lib/libsec/common/acltext.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
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 /*
22f48205beScasper  * Copyright 2007 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 *
84afe1f701Smarks pruname(uid_t uid, char *uidp, size_t buflen, int noresolve)
855a5eeccaSmarks {
8645a17f45Sgjelinek 	struct passwd	*passwdp = NULL;
87fa9e4066Sahrens 
8845a17f45Sgjelinek 	if (noresolve == 0)
895a5eeccaSmarks 		passwdp = getpwuid(uid);
905a5eeccaSmarks 	if (passwdp == (struct passwd *)NULL) {
915a5eeccaSmarks 		/* could not get passwd information: display uid instead */
92f48205beScasper 		(void) snprintf(uidp, buflen, "%u", uid);
93afe1f701Smarks 	} else {
94afe1f701Smarks 		(void) strlcpy(uidp, passwdp->pw_name, buflen);
95afe1f701Smarks 	}
965a5eeccaSmarks 	return (uidp);
975a5eeccaSmarks }
98fa9e4066Sahrens 
995a5eeccaSmarks static char *
100afe1f701Smarks prgname(gid_t gid, char *gidp, size_t buflen, int noresolve)
1015a5eeccaSmarks {
10245a17f45Sgjelinek 	struct group	*groupp = NULL;
103fa9e4066Sahrens 
10445a17f45Sgjelinek 	if (noresolve == 0)
1055a5eeccaSmarks 		groupp = getgrgid(gid);
1065a5eeccaSmarks 	if (groupp == (struct group *)NULL) {
1075a5eeccaSmarks 		/* could not get group information: display gid instead */
108f48205beScasper 		(void) snprintf(gidp, buflen, "%u", gid);
109afe1f701Smarks 	} else {
110afe1f701Smarks 		(void) strlcpy(gidp, groupp->gr_name, buflen);
111afe1f701Smarks 	}
1125a5eeccaSmarks 	return (gidp);
1135a5eeccaSmarks }
1145a5eeccaSmarks static void
1155a5eeccaSmarks aclent_printacl(acl_t *aclp)
1165a5eeccaSmarks {
1175a5eeccaSmarks 	aclent_t *tp;
1185a5eeccaSmarks 	int aclcnt;
1195a5eeccaSmarks 	int mask;
1205a5eeccaSmarks 	int slot = 0;
1215a5eeccaSmarks 	char perm[4];
122afe1f701Smarks 	char uidp[ID_STR_MAX];
123afe1f701Smarks 	char gidp[ID_STR_MAX];
1245a5eeccaSmarks 
1255a5eeccaSmarks 	/* display ACL: assume it is sorted. */
1265a5eeccaSmarks 	aclcnt = aclp->acl_cnt;
1275a5eeccaSmarks 	for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) {
1285a5eeccaSmarks 		if (tp->a_type == CLASS_OBJ)
1295a5eeccaSmarks 			mask = tp->a_perm;
1305a5eeccaSmarks 	}
1315a5eeccaSmarks 	aclcnt = aclp->acl_cnt;
1325a5eeccaSmarks 	for (tp = aclp->acl_aclp; aclcnt--; tp++) {
1335a5eeccaSmarks 		(void) printf("     %d:", slot++);
1345a5eeccaSmarks 		switch (tp->a_type) {
1355a5eeccaSmarks 		case USER:
1365a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1375a5eeccaSmarks 			(void) printf("user:%s:%s\t\t",
138afe1f701Smarks 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
1395a5eeccaSmarks 			aclent_perms((tp->a_perm & mask), perm);
1405a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
1415a5eeccaSmarks 			break;
1425a5eeccaSmarks 		case USER_OBJ:
1435a5eeccaSmarks 			/* no need to display uid */
1445a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1455a5eeccaSmarks 			(void) printf("user::%s\n", perm);
1465a5eeccaSmarks 			break;
1475a5eeccaSmarks 		case GROUP:
1485a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1495a5eeccaSmarks 			(void) printf("group:%s:%s\t\t",
150afe1f701Smarks 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
1515a5eeccaSmarks 			aclent_perms(tp->a_perm & mask, perm);
1525a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
1535a5eeccaSmarks 			break;
1545a5eeccaSmarks 		case GROUP_OBJ:
1555a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1565a5eeccaSmarks 			(void) printf("group::%s\t\t", perm);
1575a5eeccaSmarks 			aclent_perms(tp->a_perm & mask, perm);
1585a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
1595a5eeccaSmarks 			break;
1605a5eeccaSmarks 		case CLASS_OBJ:
1615a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1625a5eeccaSmarks 			(void) printf("mask:%s\n", perm);
1635a5eeccaSmarks 			break;
1645a5eeccaSmarks 		case OTHER_OBJ:
1655a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1665a5eeccaSmarks 			(void) printf("other:%s\n", perm);
1675a5eeccaSmarks 			break;
1685a5eeccaSmarks 		case DEF_USER:
1695a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1705a5eeccaSmarks 			(void) printf("default:user:%s:%s\n",
171afe1f701Smarks 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
1725a5eeccaSmarks 			break;
1735a5eeccaSmarks 		case DEF_USER_OBJ:
1745a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1755a5eeccaSmarks 			(void) printf("default:user::%s\n", perm);
1765a5eeccaSmarks 			break;
1775a5eeccaSmarks 		case DEF_GROUP:
1785a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1795a5eeccaSmarks 			(void) printf("default:group:%s:%s\n",
180afe1f701Smarks 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
1815a5eeccaSmarks 			break;
1825a5eeccaSmarks 		case DEF_GROUP_OBJ:
1835a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1845a5eeccaSmarks 			(void) printf("default:group::%s\n", perm);
1855a5eeccaSmarks 			break;
1865a5eeccaSmarks 		case DEF_CLASS_OBJ:
1875a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1885a5eeccaSmarks 			(void) printf("default:mask:%s\n", perm);
1895a5eeccaSmarks 			break;
1905a5eeccaSmarks 		case DEF_OTHER_OBJ:
1915a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
1925a5eeccaSmarks 			(void) printf("default:other:%s\n", perm);
1935a5eeccaSmarks 			break;
1945a5eeccaSmarks 		default:
1955a5eeccaSmarks 			(void) fprintf(stderr,
1965b233e2dSmarks 			    dgettext(TEXT_DOMAIN, "unrecognized entry\n"));
1975a5eeccaSmarks 			break;
1985a5eeccaSmarks 		}
1995a5eeccaSmarks 	}
2005a5eeccaSmarks }
2015a5eeccaSmarks 
2025a5eeccaSmarks static void
2035a5eeccaSmarks split_line(char *str, int cols)
2045a5eeccaSmarks {
2055a5eeccaSmarks 	char *ptr;
2065a5eeccaSmarks 	int len;
2075a5eeccaSmarks 	int i;
2085a5eeccaSmarks 	int last_split;
2095a5eeccaSmarks 	char *pad = "";
2105a5eeccaSmarks 	int pad_len;
2115a5eeccaSmarks 
2125a5eeccaSmarks 	len = strlen(str);
2135a5eeccaSmarks 	ptr = str;
2145a5eeccaSmarks 	pad_len = 0;
2155a5eeccaSmarks 
2165a5eeccaSmarks 	ptr = str;
2175a5eeccaSmarks 	last_split = 0;
2185a5eeccaSmarks 	for (i = 0; i != len; i++) {
2195a5eeccaSmarks 		if ((i + pad_len + 4) >= cols) {
2205a5eeccaSmarks 			(void) printf("%s%.*s\n", pad, last_split, ptr);
2215a5eeccaSmarks 			ptr = &ptr[last_split];
2225a5eeccaSmarks 			len = strlen(ptr);
2235a5eeccaSmarks 			i = 0;
2245a5eeccaSmarks 			pad_len = 4;
2255a5eeccaSmarks 			pad = "         ";
2265a5eeccaSmarks 		} else {
2275a5eeccaSmarks 			if (ptr[i] == '/' || ptr[i] == ':') {
2285a5eeccaSmarks 				last_split = i;
2295a5eeccaSmarks 			}
2305a5eeccaSmarks 		}
2315a5eeccaSmarks 	}
2325a5eeccaSmarks 	if (i == len) {
2335a5eeccaSmarks 		(void) printf("%s%s\n", pad, ptr);
2345a5eeccaSmarks 	}
2355a5eeccaSmarks }
2365a5eeccaSmarks 
2375a5eeccaSmarks #define	OWNERAT_TXT	"owner@"
2385a5eeccaSmarks #define	GROUPAT_TXT	"group@"
2395a5eeccaSmarks #define	EVERYONEAT_TXT	"everyone@"
2405a5eeccaSmarks #define	GROUP_TXT	"group:"
2415a5eeccaSmarks #define	USER_TXT	"user:"
2425a5eeccaSmarks 
2435a5eeccaSmarks char *
24445a17f45Sgjelinek ace_type_txt(char *buf, char **endp, ace_t *acep, int flags)
2455a5eeccaSmarks {
2465a5eeccaSmarks 
247afe1f701Smarks 	char idp[ID_STR_MAX];
2485a5eeccaSmarks 
2495a5eeccaSmarks 	if (buf == NULL)
2505a5eeccaSmarks 		return (NULL);
2515a5eeccaSmarks 
2525a5eeccaSmarks 	switch (acep->a_flags & ACE_TYPE_FLAGS) {
2535a5eeccaSmarks 	case ACE_OWNER:
2545a5eeccaSmarks 		strcpy(buf, OWNERAT_TXT);
2555a5eeccaSmarks 		*endp = buf + sizeof (OWNERAT_TXT) - 1;
2565a5eeccaSmarks 		break;
2575a5eeccaSmarks 
2585a5eeccaSmarks 	case ACE_GROUP|ACE_IDENTIFIER_GROUP:
2595a5eeccaSmarks 		strcpy(buf, GROUPAT_TXT);
2605a5eeccaSmarks 		*endp = buf + sizeof (GROUPAT_TXT) - 1;
2615a5eeccaSmarks 		break;
2625a5eeccaSmarks 
2635a5eeccaSmarks 	case ACE_IDENTIFIER_GROUP:
2645a5eeccaSmarks 		strcpy(buf, GROUP_TXT);
265afe1f701Smarks 		strcat(buf, prgname(acep->a_who, idp,
266afe1f701Smarks 		    sizeof (idp), flags & ACL_NORESOLVE));
2675a5eeccaSmarks 		*endp = buf + strlen(buf);
2685a5eeccaSmarks 		break;
2695a5eeccaSmarks 
2705a5eeccaSmarks 	case ACE_EVERYONE:
2715a5eeccaSmarks 		strcpy(buf, EVERYONEAT_TXT);
2725a5eeccaSmarks 		*endp = buf + sizeof (EVERYONEAT_TXT) - 1;
2735a5eeccaSmarks 		break;
2745a5eeccaSmarks 
2755a5eeccaSmarks 	case 0:
2765a5eeccaSmarks 		strcpy(buf, USER_TXT);
277afe1f701Smarks 		strcat(buf, pruname(acep->a_who, idp,
278afe1f701Smarks 		    sizeof (idp), flags & ACL_NORESOLVE));
2795a5eeccaSmarks 		*endp = buf + strlen(buf);
2805a5eeccaSmarks 		break;
2815a5eeccaSmarks 	}
2825a5eeccaSmarks 
2835a5eeccaSmarks 	return (buf);
2845a5eeccaSmarks }
2855a5eeccaSmarks 
2865a5eeccaSmarks #define	READ_DATA_TXT	"read_data/"
2875a5eeccaSmarks #define	WRITE_DATA_TXT	"write_data/"
2885a5eeccaSmarks #define	EXECUTE_TXT	"execute/"
2895a5eeccaSmarks #define	READ_XATTR_TXT	"read_xattr/"
2905a5eeccaSmarks #define	WRITE_XATTR_TXT	"write_xattr/"
2915a5eeccaSmarks #define	READ_ATTRIBUTES_TXT "read_attributes/"
2925a5eeccaSmarks #define	WRITE_ATTRIBUTES_TXT "write_attributes/"
2935a5eeccaSmarks #define	DELETE_TXT	"delete/"
2945a5eeccaSmarks #define	DELETE_CHILD_TXT "delete_child/"
2955a5eeccaSmarks #define	WRITE_OWNER_TXT "write_owner/"
2965a5eeccaSmarks #define	READ_ACL_TXT	"read_acl/"
2975a5eeccaSmarks #define	WRITE_ACL_TXT	"write_acl/"
2985a5eeccaSmarks #define	APPEND_DATA_TXT "append_data/"
2995a5eeccaSmarks #define	READ_DIR_TXT	"list_directory/read_data/"
3005a5eeccaSmarks #define	ADD_DIR_TXT	"add_subdirectory/append_data/"
3015a5eeccaSmarks #define	ADD_FILE_TXT	"add_file/write_data/"
3025a5eeccaSmarks #define	SYNCHRONIZE_TXT "synchronize"	/* not slash on this one */
3035a5eeccaSmarks 
3045a5eeccaSmarks char *
3055a5eeccaSmarks ace_perm_txt(char *buf, char **endp, uint32_t mask,
3065a5eeccaSmarks     uint32_t iflags, int isdir, int flags)
3075a5eeccaSmarks {
3085a5eeccaSmarks 	char *lend = buf;		/* local end */
3095a5eeccaSmarks 
3105a5eeccaSmarks 	if (buf == NULL)
3115a5eeccaSmarks 		return (NULL);
3125a5eeccaSmarks 
3135a5eeccaSmarks 	if (flags & ACL_COMPACT_FMT) {
3145a5eeccaSmarks 
3155a5eeccaSmarks 		if (mask & ACE_READ_DATA)
3165a5eeccaSmarks 			buf[0] = 'r';
3175a5eeccaSmarks 		else
3185a5eeccaSmarks 			buf[0] = '-';
3195a5eeccaSmarks 		if (mask & ACE_WRITE_DATA)
3205a5eeccaSmarks 			buf[1] = 'w';
3215a5eeccaSmarks 		else
3225a5eeccaSmarks 			buf[1] = '-';
3235a5eeccaSmarks 		if (mask & ACE_EXECUTE)
3245a5eeccaSmarks 			buf[2] = 'x';
3255a5eeccaSmarks 		else
3265a5eeccaSmarks 			buf[2] = '-';
3275a5eeccaSmarks 		if (mask & ACE_APPEND_DATA)
3285a5eeccaSmarks 			buf[3] = 'p';
3295a5eeccaSmarks 		else
3305a5eeccaSmarks 			buf[3] = '-';
3315a5eeccaSmarks 		if (mask & ACE_DELETE)
3325a5eeccaSmarks 			buf[4] = 'd';
3335a5eeccaSmarks 		else
3345a5eeccaSmarks 			buf[4] = '-';
3355a5eeccaSmarks 		if (mask & ACE_DELETE_CHILD)
3365a5eeccaSmarks 			buf[5] = 'D';
3375a5eeccaSmarks 		else
3385a5eeccaSmarks 			buf[5] = '-';
3395a5eeccaSmarks 		if (mask & ACE_READ_ATTRIBUTES)
3405a5eeccaSmarks 			buf[6] = 'a';
3415a5eeccaSmarks 		else
3425a5eeccaSmarks 			buf[6] = '-';
3435a5eeccaSmarks 		if (mask & ACE_WRITE_ATTRIBUTES)
3445a5eeccaSmarks 			buf[7] = 'A';
3455a5eeccaSmarks 		else
3465a5eeccaSmarks 			buf[7] = '-';
3475a5eeccaSmarks 		if (mask & ACE_READ_NAMED_ATTRS)
3485a5eeccaSmarks 			buf[8] = 'R';
3495a5eeccaSmarks 		else
3505a5eeccaSmarks 			buf[8] = '-';
3515a5eeccaSmarks 		if (mask & ACE_WRITE_NAMED_ATTRS)
3525a5eeccaSmarks 			buf[9] = 'W';
3535a5eeccaSmarks 		else
3545a5eeccaSmarks 			buf[9] = '-';
3555a5eeccaSmarks 		if (mask & ACE_READ_ACL)
3565a5eeccaSmarks 			buf[10] = 'c';
3575a5eeccaSmarks 		else
3585a5eeccaSmarks 			buf[10] = '-';
3595a5eeccaSmarks 		if (mask & ACE_WRITE_ACL)
3605a5eeccaSmarks 			buf[11] = 'C';
3615a5eeccaSmarks 		else
3625a5eeccaSmarks 			buf[11] = '-';
3635a5eeccaSmarks 		if (mask & ACE_WRITE_OWNER)
3645a5eeccaSmarks 			buf[12] = 'o';
3655a5eeccaSmarks 		else
3665a5eeccaSmarks 			buf[12] = '-';
3675a5eeccaSmarks 		if (mask & ACE_SYNCHRONIZE)
3685a5eeccaSmarks 			buf[13] = 's';
3695a5eeccaSmarks 		else
3705a5eeccaSmarks 			buf[13] = '-';
3715a5eeccaSmarks 		buf[14] = '\0';
3725a5eeccaSmarks 		*endp = buf + 14;
3735a5eeccaSmarks 		return (buf);
3745a5eeccaSmarks 	} else {
3755a5eeccaSmarks 		/*
3765a5eeccaSmarks 		 * If ACE is a directory, but inheritance indicates its
3775a5eeccaSmarks 		 * for a file then print permissions for file rather than
3785a5eeccaSmarks 		 * dir.
3795a5eeccaSmarks 		 */
3805a5eeccaSmarks 		if (isdir) {
3815a5eeccaSmarks 			if (mask & ACE_LIST_DIRECTORY) {
3825a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
3835a5eeccaSmarks 					strcpy(lend, READ_DATA_TXT);
3845a5eeccaSmarks 					lend += sizeof (READ_DATA_TXT) - 1;
3855a5eeccaSmarks 				} else {
3865a5eeccaSmarks 					strcpy(lend, READ_DIR_TXT);
3875a5eeccaSmarks 					lend += sizeof (READ_DIR_TXT) - 1;
3885a5eeccaSmarks 				}
3895a5eeccaSmarks 			}
3905a5eeccaSmarks 			if (mask & ACE_ADD_FILE) {
3915a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
3925a5eeccaSmarks 					strcpy(lend, WRITE_DATA_TXT);
3935a5eeccaSmarks 					lend += sizeof (WRITE_DATA_TXT) - 1;
3945a5eeccaSmarks 				} else {
3955a5eeccaSmarks 					strcpy(lend, ADD_FILE_TXT);
3965a5eeccaSmarks 					lend +=
3975a5eeccaSmarks 					    sizeof (ADD_FILE_TXT) -1;
3985a5eeccaSmarks 				}
3995a5eeccaSmarks 			}
4005a5eeccaSmarks 			if (mask & ACE_ADD_SUBDIRECTORY) {
4015a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
4025a5eeccaSmarks 					strcpy(lend, APPEND_DATA_TXT);
4035a5eeccaSmarks 					lend += sizeof (APPEND_DATA_TXT) - 1;
4045a5eeccaSmarks 				} else {
4055a5eeccaSmarks 					strcpy(lend, ADD_DIR_TXT);
4065a5eeccaSmarks 					lend += sizeof (ADD_DIR_TXT) - 1;
4075a5eeccaSmarks 				}
4085a5eeccaSmarks 			}
4095a5eeccaSmarks 		} else {
4105a5eeccaSmarks 			if (mask & ACE_READ_DATA) {
4115a5eeccaSmarks 				strcpy(lend, READ_DATA_TXT);
4125a5eeccaSmarks 				lend += sizeof (READ_DATA_TXT) - 1;
4135a5eeccaSmarks 			}
4145a5eeccaSmarks 			if (mask & ACE_WRITE_DATA) {
4155a5eeccaSmarks 				strcpy(lend, WRITE_DATA_TXT);
4165a5eeccaSmarks 				lend += sizeof (WRITE_DATA_TXT) - 1;
4175a5eeccaSmarks 			}
4185a5eeccaSmarks 			if (mask & ACE_APPEND_DATA) {
4195a5eeccaSmarks 				strcpy(lend, APPEND_DATA_TXT);
4205a5eeccaSmarks 				lend += sizeof (APPEND_DATA_TXT) - 1;
4215a5eeccaSmarks 			}
4225a5eeccaSmarks 		}
4235a5eeccaSmarks 		if (mask & ACE_READ_NAMED_ATTRS) {
4245a5eeccaSmarks 			strcpy(lend, READ_XATTR_TXT);
4255a5eeccaSmarks 			lend += sizeof (READ_XATTR_TXT) - 1;
4265a5eeccaSmarks 		}
4275a5eeccaSmarks 		if (mask & ACE_WRITE_NAMED_ATTRS) {
4285a5eeccaSmarks 			strcpy(lend, WRITE_XATTR_TXT);
4295a5eeccaSmarks 			lend += sizeof (WRITE_XATTR_TXT) - 1;
4305a5eeccaSmarks 		}
4315a5eeccaSmarks 		if (mask & ACE_EXECUTE) {
4325a5eeccaSmarks 			strcpy(lend, EXECUTE_TXT);
4335a5eeccaSmarks 			lend += sizeof (EXECUTE_TXT) - 1;
4345a5eeccaSmarks 		}
4355a5eeccaSmarks 		if (mask & ACE_DELETE_CHILD) {
4365a5eeccaSmarks 			strcpy(lend, DELETE_CHILD_TXT);
4375a5eeccaSmarks 			lend += sizeof (DELETE_CHILD_TXT) - 1;
4385a5eeccaSmarks 		}
4395a5eeccaSmarks 		if (mask & ACE_READ_ATTRIBUTES) {
4405a5eeccaSmarks 			strcpy(lend, READ_ATTRIBUTES_TXT);
4415a5eeccaSmarks 			lend += sizeof (READ_ATTRIBUTES_TXT) - 1;
4425a5eeccaSmarks 		}
4435a5eeccaSmarks 		if (mask & ACE_WRITE_ATTRIBUTES) {
4445a5eeccaSmarks 			strcpy(lend, WRITE_ATTRIBUTES_TXT);
4455a5eeccaSmarks 			lend += sizeof (WRITE_ATTRIBUTES_TXT) - 1;
4465a5eeccaSmarks 		}
4475a5eeccaSmarks 		if (mask & ACE_DELETE) {
4485a5eeccaSmarks 			strcpy(lend, DELETE_TXT);
4495a5eeccaSmarks 			lend += sizeof (DELETE_TXT) - 1;
4505a5eeccaSmarks 		}
4515a5eeccaSmarks 		if (mask & ACE_READ_ACL) {
4525a5eeccaSmarks 			strcpy(lend, READ_ACL_TXT);
4535a5eeccaSmarks 			lend += sizeof (READ_ACL_TXT) - 1;
4545a5eeccaSmarks 		}
4555a5eeccaSmarks 		if (mask & ACE_WRITE_ACL) {
4565a5eeccaSmarks 			strcpy(lend, WRITE_ACL_TXT);
4575a5eeccaSmarks 			lend += sizeof (WRITE_ACL_TXT) - 1;
4585a5eeccaSmarks 		}
4595a5eeccaSmarks 		if (mask & ACE_WRITE_OWNER) {
4605a5eeccaSmarks 			strcpy(lend, WRITE_OWNER_TXT);
4615a5eeccaSmarks 			lend += sizeof (WRITE_OWNER_TXT) - 1;
4625a5eeccaSmarks 		}
4635a5eeccaSmarks 		if (mask & ACE_SYNCHRONIZE) {
4645a5eeccaSmarks 			strcpy(lend, SYNCHRONIZE_TXT);
4655a5eeccaSmarks 			lend += sizeof (SYNCHRONIZE_TXT) - 1;
4665a5eeccaSmarks 		}
4675a5eeccaSmarks 
4685a5eeccaSmarks 		if (*(lend - 1) == '/')
4695a5eeccaSmarks 			*--lend = '\0';
4705a5eeccaSmarks 	}
4715a5eeccaSmarks 
4725a5eeccaSmarks 	*endp = lend;
4735a5eeccaSmarks 	return (buf);
4745a5eeccaSmarks }
4755a5eeccaSmarks 
4765a5eeccaSmarks #define	ALLOW_TXT	"allow"
4775a5eeccaSmarks #define	DENY_TXT	"deny"
4785a5eeccaSmarks #define	ALARM_TXT	"alarm"
4795a5eeccaSmarks #define	AUDIT_TXT	"audit"
4805a5eeccaSmarks #define	UNKNOWN_TXT	"unknown"
4815a5eeccaSmarks char *
4825a5eeccaSmarks ace_access_txt(char *buf, char **endp, int type)
4835a5eeccaSmarks {
4845a5eeccaSmarks 
4855a5eeccaSmarks 	if (buf == NULL)
4865a5eeccaSmarks 		return (NULL);
4875a5eeccaSmarks 
4885a5eeccaSmarks 	if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
4895a5eeccaSmarks 		strcpy(buf, ALLOW_TXT);
4905a5eeccaSmarks 		*endp += sizeof (ALLOW_TXT) - 1;
4915a5eeccaSmarks 	} else if (type == ACE_ACCESS_DENIED_ACE_TYPE) {
4925a5eeccaSmarks 		strcpy(buf, DENY_TXT);
4935a5eeccaSmarks 		*endp += sizeof (DENY_TXT) - 1;
4945a5eeccaSmarks 	} else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) {
4955a5eeccaSmarks 		strcpy(buf, AUDIT_TXT);
4965a5eeccaSmarks 		*endp += sizeof (AUDIT_TXT) - 1;
4975a5eeccaSmarks 	} else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) {
4985a5eeccaSmarks 		strcpy(buf, ALARM_TXT);
4995a5eeccaSmarks 		*endp += sizeof (ALARM_TXT) - 1;
5005a5eeccaSmarks 	} else {
5015a5eeccaSmarks 		strcpy(buf, UNKNOWN_TXT);
5025a5eeccaSmarks 		*endp += sizeof (UNKNOWN_TXT) - 1;
5035a5eeccaSmarks 	}
5045a5eeccaSmarks 
5055a5eeccaSmarks 	return (buf);
5065a5eeccaSmarks }
5075a5eeccaSmarks 
5085a5eeccaSmarks static char *
5095a5eeccaSmarks ace_inherit_txt(char *buf, char **endp, uint32_t iflags, int flags)
5105a5eeccaSmarks {
5115a5eeccaSmarks 
5125a5eeccaSmarks 	char *lend = buf;
5135a5eeccaSmarks 
5145a5eeccaSmarks 	if (buf == NULL) {
5155a5eeccaSmarks 		return (NULL);
5165a5eeccaSmarks 	}
5175a5eeccaSmarks 
5185a5eeccaSmarks 	if (flags & ACL_COMPACT_FMT) {
5195a5eeccaSmarks 		if (iflags & ACE_FILE_INHERIT_ACE)
5205a5eeccaSmarks 			buf[0] = 'f';
5215a5eeccaSmarks 		else
5225a5eeccaSmarks 			buf[0] = '-';
5235a5eeccaSmarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE)
5245a5eeccaSmarks 			buf[1] = 'd';
5255a5eeccaSmarks 		else
5265a5eeccaSmarks 			buf[1] = '-';
5275a5eeccaSmarks 		if (iflags & ACE_INHERIT_ONLY_ACE)
5285a5eeccaSmarks 			buf[2] = 'i';
5295a5eeccaSmarks 		else
5305a5eeccaSmarks 			buf[2] = '-';
5315a5eeccaSmarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)
5325a5eeccaSmarks 			buf[3] = 'n';
5335a5eeccaSmarks 		else
5345a5eeccaSmarks 			buf[3] = '-';
5355a5eeccaSmarks 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
5365a5eeccaSmarks 			buf[4] = 'S';
5375a5eeccaSmarks 		else
5385a5eeccaSmarks 			buf[4] = '-';
5395a5eeccaSmarks 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG)
5405a5eeccaSmarks 			buf[5] = 'F';
5415a5eeccaSmarks 		else
5425a5eeccaSmarks 			buf[5] = '-';
543*da6c28aaSamw 		if (iflags & ACE_INHERITED_ACE)
544*da6c28aaSamw 			buf[6] = 'I';
545*da6c28aaSamw 		else
546*da6c28aaSamw 			buf[6] = '-';
547*da6c28aaSamw 		buf[7] = '\0';
548*da6c28aaSamw 		*endp = buf + 7;
5495a5eeccaSmarks 	} else {
5505a5eeccaSmarks 		if (iflags & ACE_FILE_INHERIT_ACE) {
5515a5eeccaSmarks 			strcpy(lend, "file_inherit/");
5525a5eeccaSmarks 			lend += sizeof ("file_inherit/") - 1;
5535a5eeccaSmarks 		}
5545a5eeccaSmarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE) {
5555a5eeccaSmarks 			strcpy(lend, "dir_inherit/");
5565a5eeccaSmarks 			lend += sizeof ("dir_inherit/") - 1;
5575a5eeccaSmarks 		}
5585a5eeccaSmarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) {
5595a5eeccaSmarks 			strcpy(lend, "no_propagate/");
5605a5eeccaSmarks 			lend += sizeof ("no_propagate/") - 1;
5615a5eeccaSmarks 		}
5625a5eeccaSmarks 		if (iflags & ACE_INHERIT_ONLY_ACE) {
5635a5eeccaSmarks 			strcpy(lend, "inherit_only/");
5645a5eeccaSmarks 			lend += sizeof ("inherit_only/") - 1;
5655a5eeccaSmarks 		}
566*da6c28aaSamw 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) {
567*da6c28aaSamw 			strcpy(lend, "successful_access/");
568*da6c28aaSamw 			lend += sizeof ("successful_access/") - 1;
569*da6c28aaSamw 		}
570*da6c28aaSamw 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) {
571*da6c28aaSamw 			strcpy(lend, "failed_access/");
572*da6c28aaSamw 			lend += sizeof ("failed_access/") - 1;
573*da6c28aaSamw 		}
574*da6c28aaSamw 		if (iflags & ACE_INHERITED_ACE) {
575*da6c28aaSamw 			strcpy(lend, "inherited/");
576*da6c28aaSamw 			lend += sizeof ("inherited/") - 1;
577*da6c28aaSamw 		}
5785a5eeccaSmarks 
5795a5eeccaSmarks 		if (*(lend - 1) == '/')
5805a5eeccaSmarks 			*--lend = '\0';
5815a5eeccaSmarks 		*endp = lend;
5825a5eeccaSmarks 	}
5835a5eeccaSmarks 
5845a5eeccaSmarks 	return (buf);
585fa9e4066Sahrens }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate /*
5887c478bd9Sstevel@tonic-gate  * Convert internal acl representation to external representation.
5897c478bd9Sstevel@tonic-gate  *
5907c478bd9Sstevel@tonic-gate  * The length of a non-owning user name or non-owning group name ie entries
5917c478bd9Sstevel@tonic-gate  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
5927c478bd9Sstevel@tonic-gate  * thus check the length of these entries, and if greater than LOGNAME_MAX,
5937c478bd9Sstevel@tonic-gate  * we realloc() via increase_length().
5947c478bd9Sstevel@tonic-gate  *
5957c478bd9Sstevel@tonic-gate  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
5967c478bd9Sstevel@tonic-gate  * adhered to.
5977c478bd9Sstevel@tonic-gate  */
5985a5eeccaSmarks 
5995a5eeccaSmarks /*
6005a5eeccaSmarks  * acltotext() converts each ACL entry to look like this:
6015a5eeccaSmarks  *
6025a5eeccaSmarks  *    entry_type:uid^gid^name:perms[:id]
6035a5eeccaSmarks  *
6045a5eeccaSmarks  * The maximum length of entry_type is 14 ("defaultgroup::" and
6055a5eeccaSmarks  * "defaultother::") hence ENTRYTYPELEN is set to 14.
6065a5eeccaSmarks  *
6075a5eeccaSmarks  * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
6085a5eeccaSmarks  * however the ID could be a number so we therefore use ID_STR_MAX
6095a5eeccaSmarks  *
6105a5eeccaSmarks  * The length of a perms entry is 4 to allow for the comma appended to each
6115a5eeccaSmarks  * to each acl entry.  Hence PERMS is set to 4.
6125a5eeccaSmarks  */
6135a5eeccaSmarks 
6145a5eeccaSmarks #define	ENTRYTYPELEN	14
6155a5eeccaSmarks #define	PERMS		4
6165a5eeccaSmarks #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
6175a5eeccaSmarks #define	UPDATE_WHERE	where = dstr->aclexport + strlen(dstr->aclexport)
6185a5eeccaSmarks 
6197c478bd9Sstevel@tonic-gate char *
6205a5eeccaSmarks aclent_acltotext(aclent_t  *aclp, int aclcnt, int flags)
6217c478bd9Sstevel@tonic-gate {
6227c478bd9Sstevel@tonic-gate 	char		*aclexport;
6237c478bd9Sstevel@tonic-gate 	char		*where;
624ee519a1fSgjelinek 	struct group	*groupp = NULL;
625ee519a1fSgjelinek 	struct passwd	*passwdp = NULL;
6267c478bd9Sstevel@tonic-gate 	struct dynaclstr *dstr;
6277c478bd9Sstevel@tonic-gate 	int		i, rtn;
6287c478bd9Sstevel@tonic-gate 	size_t		excess = 0;
629afe1f701Smarks 	char		id[ID_STR_MAX], *idstr;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	if (aclp == NULL)
6327c478bd9Sstevel@tonic-gate 		return (NULL);
6337c478bd9Sstevel@tonic-gate 	if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL)
6347c478bd9Sstevel@tonic-gate 		return (NULL);
6357c478bd9Sstevel@tonic-gate 	dstr->bufsize = aclcnt * ACL_ENTRY_SIZE;
6367c478bd9Sstevel@tonic-gate 	if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) {
6377c478bd9Sstevel@tonic-gate 		free(dstr);
6387c478bd9Sstevel@tonic-gate 		return (NULL);
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 	*dstr->aclexport = '\0';
6417c478bd9Sstevel@tonic-gate 	where = dstr->aclexport;
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	for (i = 0; i < aclcnt; i++, aclp++) {
6447c478bd9Sstevel@tonic-gate 		switch (aclp->a_type) {
6457c478bd9Sstevel@tonic-gate 		case DEF_USER_OBJ:
6467c478bd9Sstevel@tonic-gate 		case USER_OBJ:
6477c478bd9Sstevel@tonic-gate 			if (aclp->a_type == USER_OBJ)
6487c478bd9Sstevel@tonic-gate 				where = strappend(where, "user::");
6497c478bd9Sstevel@tonic-gate 			else
6507c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultuser::");
6517c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6527c478bd9Sstevel@tonic-gate 			break;
6537c478bd9Sstevel@tonic-gate 		case DEF_USER:
6547c478bd9Sstevel@tonic-gate 		case USER:
6557c478bd9Sstevel@tonic-gate 			if (aclp->a_type == USER)
6567c478bd9Sstevel@tonic-gate 				where = strappend(where, "user:");
6577c478bd9Sstevel@tonic-gate 			else
6587c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultuser:");
659ee519a1fSgjelinek 			if ((flags & ACL_NORESOLVE) == 0)
6607c478bd9Sstevel@tonic-gate 				passwdp = getpwuid(aclp->a_id);
6617c478bd9Sstevel@tonic-gate 			if (passwdp == (struct passwd *)NULL) {
6627c478bd9Sstevel@tonic-gate 				/* put in uid instead */
6637c478bd9Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
66411e32170Shm123892 				UPDATE_WHERE;
6657c478bd9Sstevel@tonic-gate 			} else {
6667c478bd9Sstevel@tonic-gate 				excess = strlen(passwdp->pw_name) - LOGNAME_MAX;
6677c478bd9Sstevel@tonic-gate 				if (excess > 0) {
6687c478bd9Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
6697c478bd9Sstevel@tonic-gate 					if (rtn == 1) {
67011e32170Shm123892 						UPDATE_WHERE;
6717c478bd9Sstevel@tonic-gate 					} else {
6727c478bd9Sstevel@tonic-gate 						free(dstr->aclexport);
6737c478bd9Sstevel@tonic-gate 						free(dstr);
6747c478bd9Sstevel@tonic-gate 						return (NULL);
6757c478bd9Sstevel@tonic-gate 					}
6767c478bd9Sstevel@tonic-gate 				}
6777c478bd9Sstevel@tonic-gate 				where = strappend(where, passwdp->pw_name);
6787c478bd9Sstevel@tonic-gate 			}
6797c478bd9Sstevel@tonic-gate 			where = strappend(where, ":");
6807c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6817c478bd9Sstevel@tonic-gate 			break;
6827c478bd9Sstevel@tonic-gate 		case DEF_GROUP_OBJ:
6837c478bd9Sstevel@tonic-gate 		case GROUP_OBJ:
6847c478bd9Sstevel@tonic-gate 			if (aclp->a_type == GROUP_OBJ)
6857c478bd9Sstevel@tonic-gate 				where = strappend(where, "group::");
6867c478bd9Sstevel@tonic-gate 			else
6877c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultgroup::");
6887c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6897c478bd9Sstevel@tonic-gate 			break;
6907c478bd9Sstevel@tonic-gate 		case DEF_GROUP:
6917c478bd9Sstevel@tonic-gate 		case GROUP:
6927c478bd9Sstevel@tonic-gate 			if (aclp->a_type == GROUP)
6937c478bd9Sstevel@tonic-gate 				where = strappend(where, "group:");
6947c478bd9Sstevel@tonic-gate 			else
6957c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultgroup:");
696ee519a1fSgjelinek 			if ((flags & ACL_NORESOLVE) == 0)
6977c478bd9Sstevel@tonic-gate 				groupp = getgrgid(aclp->a_id);
6987c478bd9Sstevel@tonic-gate 			if (groupp == (struct group *)NULL) {
6997c478bd9Sstevel@tonic-gate 				/* put in gid instead */
7007c478bd9Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
70111e32170Shm123892 				UPDATE_WHERE;
7027c478bd9Sstevel@tonic-gate 			} else {
7037c478bd9Sstevel@tonic-gate 				excess = strlen(groupp->gr_name) - LOGNAME_MAX;
7047c478bd9Sstevel@tonic-gate 				if (excess > 0) {
7057c478bd9Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
7067c478bd9Sstevel@tonic-gate 					if (rtn == 1) {
70711e32170Shm123892 						UPDATE_WHERE;
7087c478bd9Sstevel@tonic-gate 					} else {
7097c478bd9Sstevel@tonic-gate 						free(dstr->aclexport);
7107c478bd9Sstevel@tonic-gate 						free(dstr);
7117c478bd9Sstevel@tonic-gate 						return (NULL);
7127c478bd9Sstevel@tonic-gate 					}
7137c478bd9Sstevel@tonic-gate 				}
7147c478bd9Sstevel@tonic-gate 				where = strappend(where, groupp->gr_name);
7157c478bd9Sstevel@tonic-gate 			}
7167c478bd9Sstevel@tonic-gate 			where = strappend(where, ":");
7177c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
7187c478bd9Sstevel@tonic-gate 			break;
7197c478bd9Sstevel@tonic-gate 		case DEF_CLASS_OBJ:
7207c478bd9Sstevel@tonic-gate 		case CLASS_OBJ:
7217c478bd9Sstevel@tonic-gate 			if (aclp->a_type == CLASS_OBJ)
7227c478bd9Sstevel@tonic-gate 				where = strappend(where, "mask:");
7237c478bd9Sstevel@tonic-gate 			else
7247c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultmask:");
7257c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
7267c478bd9Sstevel@tonic-gate 			break;
7277c478bd9Sstevel@tonic-gate 		case DEF_OTHER_OBJ:
7287c478bd9Sstevel@tonic-gate 		case OTHER_OBJ:
7297c478bd9Sstevel@tonic-gate 			if (aclp->a_type == OTHER_OBJ)
7307c478bd9Sstevel@tonic-gate 				where = strappend(where, "other:");
7317c478bd9Sstevel@tonic-gate 			else
7327c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultother:");
7337c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
7347c478bd9Sstevel@tonic-gate 			break;
7357c478bd9Sstevel@tonic-gate 		default:
7367c478bd9Sstevel@tonic-gate 			free(dstr->aclexport);
7377c478bd9Sstevel@tonic-gate 			free(dstr);
7387c478bd9Sstevel@tonic-gate 			return (NULL);
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 		}
7415a5eeccaSmarks 
7425a5eeccaSmarks 		if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) ||
7435a5eeccaSmarks 		    (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) ||
7445a5eeccaSmarks 		    (aclp->a_type == DEF_GROUP))) {
7455a5eeccaSmarks 			where = strappend(where, ":");
7465a5eeccaSmarks 			id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */
7475a5eeccaSmarks 			idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]);
7485a5eeccaSmarks 			where = strappend(where, idstr);
7495a5eeccaSmarks 		}
7507c478bd9Sstevel@tonic-gate 		if (i < aclcnt - 1)
7517c478bd9Sstevel@tonic-gate 			where = strappend(where, ",");
7527c478bd9Sstevel@tonic-gate 	}
7537c478bd9Sstevel@tonic-gate 	aclexport = dstr->aclexport;
7547c478bd9Sstevel@tonic-gate 	free(dstr);
7557c478bd9Sstevel@tonic-gate 	return (aclexport);
7565a5eeccaSmarks 
7575a5eeccaSmarks 
7585a5eeccaSmarks 
7595a5eeccaSmarks 
7607c478bd9Sstevel@tonic-gate }
7617c478bd9Sstevel@tonic-gate 
7625a5eeccaSmarks char *
7635a5eeccaSmarks acltotext(aclent_t *aclp, int aclcnt)
7647c478bd9Sstevel@tonic-gate {
7655a5eeccaSmarks 	return (aclent_acltotext(aclp, aclcnt, 0));
766fa9e4066Sahrens }
767fa9e4066Sahrens 
7687c478bd9Sstevel@tonic-gate 
769fa9e4066Sahrens aclent_t *
770fa9e4066Sahrens aclfromtext(char *aclstr, int *aclcnt)
771fa9e4066Sahrens {
772fa9e4066Sahrens 	acl_t *aclp;
773fa9e4066Sahrens 	aclent_t *aclentp;
774fa9e4066Sahrens 	int error;
775fa9e4066Sahrens 
7765a5eeccaSmarks 	error = acl_fromtext(aclstr, &aclp);
777fa9e4066Sahrens 	if (error)
778fa9e4066Sahrens 		return (NULL);
779fa9e4066Sahrens 
780fa9e4066Sahrens 	aclentp = aclp->acl_aclp;
781fa9e4066Sahrens 	aclp->acl_aclp = NULL;
782fa9e4066Sahrens 	*aclcnt = aclp->acl_cnt;
7835a5eeccaSmarks 
7845a5eeccaSmarks 	acl_free(aclp);
785fa9e4066Sahrens 	return (aclentp);
786fa9e4066Sahrens }
787fa9e4066Sahrens 
788fa9e4066Sahrens 
7897c478bd9Sstevel@tonic-gate static char *
7907c478bd9Sstevel@tonic-gate strappend(char *where, char *newstr)
7917c478bd9Sstevel@tonic-gate {
7927c478bd9Sstevel@tonic-gate 	(void) strcat(where, newstr);
7937c478bd9Sstevel@tonic-gate 	return (where + strlen(newstr));
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate static char *
7977c478bd9Sstevel@tonic-gate convert_perm(char *where, o_mode_t perm)
7987c478bd9Sstevel@tonic-gate {
7995a5eeccaSmarks 	if (perm & S_IROTH)
8007c478bd9Sstevel@tonic-gate 		where = strappend(where, "r");
8017c478bd9Sstevel@tonic-gate 	else
8027c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
8035a5eeccaSmarks 	if (perm & S_IWOTH)
8047c478bd9Sstevel@tonic-gate 		where = strappend(where, "w");
8057c478bd9Sstevel@tonic-gate 	else
8067c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
8075a5eeccaSmarks 	if (perm & S_IXOTH)
8087c478bd9Sstevel@tonic-gate 		where = strappend(where, "x");
8097c478bd9Sstevel@tonic-gate 	else
8107c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
8117c478bd9Sstevel@tonic-gate 	/* perm is the last field */
8127c478bd9Sstevel@tonic-gate 	return (where);
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate /*
8167c478bd9Sstevel@tonic-gate  * Callers should check the return code as this routine may change the string
8177c478bd9Sstevel@tonic-gate  * pointer in dynaclstr.
8187c478bd9Sstevel@tonic-gate  */
8197c478bd9Sstevel@tonic-gate static int
8207c478bd9Sstevel@tonic-gate increase_length(struct dynaclstr *dacl, size_t increase)
8217c478bd9Sstevel@tonic-gate {
8227c478bd9Sstevel@tonic-gate 	char *tptr;
8237c478bd9Sstevel@tonic-gate 	size_t newsize;
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 	newsize = dacl->bufsize + increase;
8267c478bd9Sstevel@tonic-gate 	tptr = realloc(dacl->aclexport, newsize);
8277c478bd9Sstevel@tonic-gate 	if (tptr != NULL) {
8287c478bd9Sstevel@tonic-gate 		dacl->aclexport = tptr;
8297c478bd9Sstevel@tonic-gate 		dacl->bufsize = newsize;
8307c478bd9Sstevel@tonic-gate 		return (1);
8317c478bd9Sstevel@tonic-gate 	} else
8327c478bd9Sstevel@tonic-gate 		return (0);
8337c478bd9Sstevel@tonic-gate }
834fa9e4066Sahrens 
835fa9e4066Sahrens /*
8365a5eeccaSmarks  * ace_acltotext() convert each ace formatted acl to look like this:
837fa9e4066Sahrens  *
8385a5eeccaSmarks  * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
839fa9e4066Sahrens  *
840fa9e4066Sahrens  * The maximum length of entry_type is 5 ("group")
841fa9e4066Sahrens  *
8425a5eeccaSmarks  * The max length of a uid^gid^name entry (in theory) is 8,
8435a5eeccaSmarks  * however id could be a number so we therefore use ID_STR_MAX
844fa9e4066Sahrens  *
845fa9e4066Sahrens  * The length of a perms entry is 144 i.e read_data/write_data...
846fa9e4066Sahrens  * to each acl entry.
847fa9e4066Sahrens  *
848*da6c28aaSamw  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access
849*da6c28aaSamw  *         /failed_access
850fa9e4066Sahrens  *
851fa9e4066Sahrens  */
852fa9e4066Sahrens 
853fa9e4066Sahrens #define	ACE_ENTRYTYPLEN		6
854*da6c28aaSamw #define	IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \
855*da6c28aaSamw 	"successful_access/failed_access/inherited"
856*da6c28aaSamw #define	IFLAGS_SIZE		(sizeof (IFLAGS_STR) - 1)
8575a5eeccaSmarks #define	ACCESS_TYPE_SIZE	7	/* if unknown */
858fa9e4066Sahrens #define	COLON_CNT		3
859fa9e4066Sahrens #define	PERMS_LEN		216
8605a5eeccaSmarks #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \
8615a5eeccaSmarks     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
862fa9e4066Sahrens 
863fa9e4066Sahrens static char *
8645a5eeccaSmarks ace_acltotext(acl_t *aceaclp, int flags)
865fa9e4066Sahrens {
866fa9e4066Sahrens 	ace_t		*aclp = aceaclp->acl_aclp;
867fa9e4066Sahrens 	int		aclcnt = aceaclp->acl_cnt;
868fa9e4066Sahrens 	char		*aclexport;
8695a5eeccaSmarks 	char		*endp;
8705a5eeccaSmarks 	int		i;
8715a5eeccaSmarks 	char		id[ID_STR_MAX], *idstr;
872fa9e4066Sahrens 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
873fa9e4066Sahrens 
874fa9e4066Sahrens 	if (aclp == NULL)
875fa9e4066Sahrens 		return (NULL);
8765a5eeccaSmarks 	if ((aclexport = malloc(aclcnt * ACE_ENTRY_SIZE)) == NULL)
877fa9e4066Sahrens 		return (NULL);
878fa9e4066Sahrens 
8795a5eeccaSmarks 	aclexport[0] = '\0';
8805a5eeccaSmarks 	endp = aclexport;
881fa9e4066Sahrens 	for (i = 0; i < aclcnt; i++, aclp++) {
882fa9e4066Sahrens 
88345a17f45Sgjelinek 		(void) ace_type_txt(endp, &endp, aclp, flags);
8845a5eeccaSmarks 		*endp++ = ':';
8855a5eeccaSmarks 		*endp = '\0';
8865a5eeccaSmarks 		(void) ace_perm_txt(endp, &endp, aclp->a_access_mask,
8875a5eeccaSmarks 		    aclp->a_flags, isdir, flags);
8885a5eeccaSmarks 		*endp++ = ':';
8895a5eeccaSmarks 		*endp = '\0';
8905a5eeccaSmarks 		(void) ace_inherit_txt(endp, &endp, aclp->a_flags, flags);
8915a5eeccaSmarks 		if (flags & ACL_COMPACT_FMT || aclp->a_flags &
8925a5eeccaSmarks 		    (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE |
893*da6c28aaSamw 		    (ACE_INHERIT_ONLY_ACE | ACE_NO_PROPAGATE_INHERIT_ACE |
894*da6c28aaSamw 		    ACE_INHERITED_ACE | ACE_SUCCESSFUL_ACCESS_ACE_FLAG |
895*da6c28aaSamw 		    ACE_FAILED_ACCESS_ACE_FLAG))) {
8965a5eeccaSmarks 			*endp++ = ':';
8975a5eeccaSmarks 			*endp = '\0';
898fa9e4066Sahrens 		}
8995a5eeccaSmarks 		(void) ace_access_txt(endp, &endp, aclp->a_type);
900fa9e4066Sahrens 
9015a5eeccaSmarks 		if ((flags & ACL_APPEND_ID) &&
9025a5eeccaSmarks 		    (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ||
9035a5eeccaSmarks 		    ((aclp->a_flags & ACE_TYPE_FLAGS) ==
9045a5eeccaSmarks 		    ACE_IDENTIFIER_GROUP))) {
9055a5eeccaSmarks 			*endp++ = ':';
9065a5eeccaSmarks 			*endp = '\0';
9075a5eeccaSmarks 			id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */
9085a5eeccaSmarks 			idstr = lltostr(aclp->a_who, &id[ID_STR_MAX - 1]);
9095a5eeccaSmarks 			strcpy(endp, idstr);
9105a5eeccaSmarks 			endp += strlen(idstr);
9115a5eeccaSmarks 		}
9125a5eeccaSmarks 		if (i < aclcnt - 1) {
9135a5eeccaSmarks 			*endp++ = ',';
9145a5eeccaSmarks 			*(endp + 1) = '\0';
915fa9e4066Sahrens 		}
916fa9e4066Sahrens 	}
917fa9e4066Sahrens 	return (aclexport);
918fa9e4066Sahrens }
919fa9e4066Sahrens 
9205a5eeccaSmarks char *
9215a5eeccaSmarks acl_totext(acl_t *aclp, int flags)
922fa9e4066Sahrens {
923fa9e4066Sahrens 
9245a5eeccaSmarks 	char *txtp;
925fa9e4066Sahrens 
926fa9e4066Sahrens 	if (aclp == NULL)
927fa9e4066Sahrens 		return (NULL);
928fa9e4066Sahrens 
929fa9e4066Sahrens 	switch (aclp->acl_type) {
930fa9e4066Sahrens 	case ACE_T:
9315a5eeccaSmarks 		txtp = ace_acltotext(aclp, flags);
9325a5eeccaSmarks 		break;
933fa9e4066Sahrens 	case ACLENT_T:
9345a5eeccaSmarks 		txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags);
9355a5eeccaSmarks 		break;
936fa9e4066Sahrens 	}
9375a5eeccaSmarks 
9385a5eeccaSmarks 	return (txtp);
939fa9e4066Sahrens }
940fa9e4066Sahrens 
941fa9e4066Sahrens int
942fa9e4066Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp)
943fa9e4066Sahrens {
9445a5eeccaSmarks 	int error;
9455a5eeccaSmarks 	char *buf;
9465a5eeccaSmarks 
9475a5eeccaSmarks 	buf = malloc(strlen(acltextp) + 2);
9485a5eeccaSmarks 	if (buf == NULL)
9495a5eeccaSmarks 		return (EACL_MEM_ERROR);
9505a5eeccaSmarks 	strcpy(buf, acltextp);
9515a5eeccaSmarks 	strcat(buf, "\n");
9525a5eeccaSmarks 	yybuf = buf;
9535a5eeccaSmarks 	yyreset();
9545a5eeccaSmarks 	error = yyparse();
9555a5eeccaSmarks 	free(buf);
9565a5eeccaSmarks 
9575a5eeccaSmarks 	if (yyacl) {
9585a5eeccaSmarks 		if (error == 0)
9595a5eeccaSmarks 			*ret_aclp = yyacl;
9605a5eeccaSmarks 		else {
9615a5eeccaSmarks 			acl_free(yyacl);
9625a5eeccaSmarks 		}
9635a5eeccaSmarks 		yyacl = NULL;
9645a5eeccaSmarks 	}
9655a5eeccaSmarks 	return (error);
9665a5eeccaSmarks }
9675a5eeccaSmarks 
9685a5eeccaSmarks int
9695a5eeccaSmarks acl_parse(const char *acltextp, acl_t **aclp)
9705a5eeccaSmarks {
971fa9e4066Sahrens 	int error;
972fa9e4066Sahrens 
9735a5eeccaSmarks 	yyinteractive = 1;
9745a5eeccaSmarks 	error = acl_fromtext(acltextp, aclp);
9755a5eeccaSmarks 	yyinteractive = 0;
976fa9e4066Sahrens 	return (error);
977fa9e4066Sahrens }
9785a5eeccaSmarks 
9795a5eeccaSmarks static void
9805a5eeccaSmarks ace_compact_printacl(acl_t *aclp)
9815a5eeccaSmarks {
9825a5eeccaSmarks 	int cnt;
9835a5eeccaSmarks 	ace_t *acep;
9845a5eeccaSmarks 	char *endp;
9855a5eeccaSmarks 	char buf[ACE_ENTRY_SIZE];
9865a5eeccaSmarks 
9875a5eeccaSmarks 	for (cnt = 0, acep = aclp->acl_aclp;
9885a5eeccaSmarks 	    cnt != aclp->acl_cnt; cnt++, acep++) {
9895a5eeccaSmarks 		buf[0] = '\0';
99045a17f45Sgjelinek 		(void) printf("    %14s:", ace_type_txt(buf, &endp, acep, 0));
9915a5eeccaSmarks 		(void) printf("%s:", ace_perm_txt(endp, &endp,
9925a5eeccaSmarks 		    acep->a_access_mask, acep->a_flags,
9935a5eeccaSmarks 		    aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT));
9945a5eeccaSmarks 		(void) printf("%s:",
9955a5eeccaSmarks 		    ace_inherit_txt(endp, &endp, acep->a_flags,
9965a5eeccaSmarks 		    ACL_COMPACT_FMT));
9975a5eeccaSmarks 		(void) printf("%s\n", ace_access_txt(endp, &endp,
9985a5eeccaSmarks 		    acep->a_type));
9995a5eeccaSmarks 	}
10005a5eeccaSmarks }
10015a5eeccaSmarks 
10025a5eeccaSmarks static void
10035a5eeccaSmarks ace_printacl(acl_t *aclp, int cols, int compact)
10045a5eeccaSmarks {
10055a5eeccaSmarks 	int  slot = 0;
10065a5eeccaSmarks 	char *token;
10075a5eeccaSmarks 	char *acltext;
10085a5eeccaSmarks 
10095a5eeccaSmarks 	if (compact) {
10105a5eeccaSmarks 		ace_compact_printacl(aclp);
10115a5eeccaSmarks 		return;
10125a5eeccaSmarks 	}
10135a5eeccaSmarks 
10145a5eeccaSmarks 	acltext = acl_totext(aclp, 0);
10155a5eeccaSmarks 
10165a5eeccaSmarks 	if (acltext == NULL)
10175a5eeccaSmarks 		return;
10185a5eeccaSmarks 
10195a5eeccaSmarks 	token = strtok(acltext, ",");
10205a5eeccaSmarks 	if (token == NULL) {
10215a5eeccaSmarks 		free(acltext);
10225a5eeccaSmarks 		return;
10235a5eeccaSmarks 	}
10245a5eeccaSmarks 
10255a5eeccaSmarks 	do {
10265a5eeccaSmarks 		(void) printf("     %d:", slot++);
10275a5eeccaSmarks 		split_line(token, cols - 5);
10285a5eeccaSmarks 	} while (token = strtok(NULL, ","));
10295a5eeccaSmarks 	free(acltext);
10305a5eeccaSmarks }
10315a5eeccaSmarks 
10325a5eeccaSmarks /*
10335a5eeccaSmarks  * pretty print an ACL.
10345a5eeccaSmarks  * For aclent_t ACL's the format is
10355a5eeccaSmarks  * similar to the old format used by getfacl,
10365a5eeccaSmarks  * with the addition of adding a "slot" number
10375a5eeccaSmarks  * before each entry.
10385a5eeccaSmarks  *
10395a5eeccaSmarks  * for ace_t ACL's the cols variable will break up
10405a5eeccaSmarks  * the long lines into multiple lines and will also
10415a5eeccaSmarks  * print a "slot" number.
10425a5eeccaSmarks  */
10435a5eeccaSmarks void
10445a5eeccaSmarks acl_printacl(acl_t *aclp, int cols, int compact)
10455a5eeccaSmarks {
10465a5eeccaSmarks 
10475a5eeccaSmarks 	switch (aclp->acl_type) {
10485a5eeccaSmarks 	case ACLENT_T:
10495a5eeccaSmarks 		aclent_printacl(aclp);
10505a5eeccaSmarks 		break;
10515a5eeccaSmarks 	case ACE_T:
10525a5eeccaSmarks 		ace_printacl(aclp, cols, compact);
10535a5eeccaSmarks 		break;
10545a5eeccaSmarks 	}
10555a5eeccaSmarks }
10565a5eeccaSmarks 
10575a5eeccaSmarks typedef struct value_table {
10585a5eeccaSmarks 	char		p_letter; /* perm letter such as 'r' */
10595a5eeccaSmarks 	uint32_t	p_value; /* value for perm when pletter found */
10605a5eeccaSmarks } value_table_t;
10615a5eeccaSmarks 
10625a5eeccaSmarks /*
1063*da6c28aaSamw  * The permission tables are laid out in positional order
10645a5eeccaSmarks  * a '-' character will indicate a permission at a given
10655a5eeccaSmarks  * position is not specified.  The '-' is not part of the
10665a5eeccaSmarks  * table, but will be checked for in the permission computation
10675a5eeccaSmarks  * routine.
10685a5eeccaSmarks  */
1069*da6c28aaSamw value_table_t ace_perm_table[] = {
10705a5eeccaSmarks 	{ 'r', ACE_READ_DATA},
10715a5eeccaSmarks 	{ 'w', ACE_WRITE_DATA},
10725a5eeccaSmarks 	{ 'x', ACE_EXECUTE},
10735a5eeccaSmarks 	{ 'p', ACE_APPEND_DATA},
10745a5eeccaSmarks 	{ 'd', ACE_DELETE},
10755a5eeccaSmarks 	{ 'D', ACE_DELETE_CHILD},
10765a5eeccaSmarks 	{ 'a', ACE_READ_ATTRIBUTES},
10775a5eeccaSmarks 	{ 'A', ACE_WRITE_ATTRIBUTES},
10785a5eeccaSmarks 	{ 'R', ACE_READ_NAMED_ATTRS},
10795a5eeccaSmarks 	{ 'W', ACE_WRITE_NAMED_ATTRS},
10805a5eeccaSmarks 	{ 'c', ACE_READ_ACL},
10815a5eeccaSmarks 	{ 'C', ACE_WRITE_ACL},
10825a5eeccaSmarks 	{ 'o', ACE_WRITE_OWNER},
10835a5eeccaSmarks 	{ 's', ACE_SYNCHRONIZE}
10845a5eeccaSmarks };
10855a5eeccaSmarks 
1086*da6c28aaSamw #define	ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t))
10875a5eeccaSmarks 
1088*da6c28aaSamw value_table_t aclent_perm_table[] = {
10895a5eeccaSmarks 	{ 'r', S_IROTH},
10905a5eeccaSmarks 	{ 'w', S_IWOTH},
10915a5eeccaSmarks 	{ 'x', S_IXOTH}
10925a5eeccaSmarks };
10935a5eeccaSmarks 
1094*da6c28aaSamw #define	ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t))
1095*da6c28aaSamw 
1096*da6c28aaSamw value_table_t inherit_table[] = {
10975a5eeccaSmarks 	{'f', ACE_FILE_INHERIT_ACE},
10985a5eeccaSmarks 	{'d', ACE_DIRECTORY_INHERIT_ACE},
10995a5eeccaSmarks 	{'i', ACE_INHERIT_ONLY_ACE},
11005a5eeccaSmarks 	{'n', ACE_NO_PROPAGATE_INHERIT_ACE},
11015a5eeccaSmarks 	{'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
1102*da6c28aaSamw 	{'F', ACE_FAILED_ACCESS_ACE_FLAG},
1103*da6c28aaSamw 	{'I', ACE_INHERITED_ACE}
11045a5eeccaSmarks };
11055a5eeccaSmarks 
1106*da6c28aaSamw #define	IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t))
1107*da6c28aaSamw 
11085a5eeccaSmarks /*
11095a5eeccaSmarks  * compute value from a permission table or inheritance table
11105a5eeccaSmarks  * based on string passed in.  If positional is set then
11115a5eeccaSmarks  * string must match order in permtab, otherwise any order
11125a5eeccaSmarks  * is allowed.
11135a5eeccaSmarks  */
11145a5eeccaSmarks int
11155a5eeccaSmarks compute_values(value_table_t *permtab, int count,
11165a5eeccaSmarks     char *permstr, int positional, uint32_t *mask)
11175a5eeccaSmarks {
11185a5eeccaSmarks 	uint32_t perm_val = 0;
11195a5eeccaSmarks 	char *pstr;
11205a5eeccaSmarks 	int i, found;
11215a5eeccaSmarks 
11225a5eeccaSmarks 	if (count < 0)
11235a5eeccaSmarks 		return (1);
11245a5eeccaSmarks 
11255a5eeccaSmarks 	if (positional) {
11265a5eeccaSmarks 		for (i = 0, pstr = permstr; i != count && pstr &&
11275a5eeccaSmarks 		    *pstr; i++, pstr++) {
11285a5eeccaSmarks 			if (*pstr == permtab[i].p_letter) {
11295a5eeccaSmarks 				perm_val |= permtab[i].p_value;
11305a5eeccaSmarks 			} else if (*pstr != '-') {
11315a5eeccaSmarks 				return (1);
11325a5eeccaSmarks 			}
11335a5eeccaSmarks 		}
11345a5eeccaSmarks 	} else {  /* random order single letters with no '-' */
11355a5eeccaSmarks 		for (pstr = permstr; pstr && *pstr; pstr++) {
11365a5eeccaSmarks 			for (found = 0, i = 0; i != count; i++) {
11375a5eeccaSmarks 				if (*pstr == permtab[i].p_letter) {
11385a5eeccaSmarks 					perm_val |= permtab[i].p_value;
11395a5eeccaSmarks 					found = 1;
11405a5eeccaSmarks 					break;
11415a5eeccaSmarks 				}
11425a5eeccaSmarks 			}
11435a5eeccaSmarks 			if (found == 0)
11445a5eeccaSmarks 				return (1);
11455a5eeccaSmarks 		}
11465a5eeccaSmarks 	}
11475a5eeccaSmarks 
11485a5eeccaSmarks 	*mask = perm_val;
11495a5eeccaSmarks 	return (0);
11505a5eeccaSmarks }
11515a5eeccaSmarks 
11525a5eeccaSmarks /*
11535a5eeccaSmarks  * compute value for inheritance flags.
11545a5eeccaSmarks  */
11555a5eeccaSmarks int
11565a5eeccaSmarks compute_ace_inherit(char *str, uint32_t *imask)
11575a5eeccaSmarks {
11585a5eeccaSmarks 	int error;
11595a5eeccaSmarks 	int positional = 0;
11605a5eeccaSmarks 
11615a5eeccaSmarks 	if (strlen(str) == IFLAG_COUNT)
11625a5eeccaSmarks 		positional = 1;
11635a5eeccaSmarks 
11645a5eeccaSmarks 	error = compute_values(inherit_table, IFLAG_COUNT,
11655a5eeccaSmarks 	    str, positional, imask);
11665a5eeccaSmarks 
11675a5eeccaSmarks 	if (error)
11685a5eeccaSmarks 		return (EACL_INHERIT_ERROR);
11695a5eeccaSmarks 
11705a5eeccaSmarks 	return (error);
11715a5eeccaSmarks }
11725a5eeccaSmarks 
11735a5eeccaSmarks 
11745a5eeccaSmarks /*
11755a5eeccaSmarks  * compute value for ACE permissions.
11765a5eeccaSmarks  */
11775a5eeccaSmarks int
11785a5eeccaSmarks compute_ace_perms(char *str, uint32_t *mask)
11795a5eeccaSmarks {
11805a5eeccaSmarks 	int positional = 0;
11815a5eeccaSmarks 	int error;
11825a5eeccaSmarks 
11835a5eeccaSmarks 	if (strlen(str) == ACE_PERM_COUNT)
11845a5eeccaSmarks 		positional = 1;
11855a5eeccaSmarks 
11865a5eeccaSmarks 	error = compute_values(ace_perm_table, ACE_PERM_COUNT,
11875a5eeccaSmarks 	    str, positional, mask);
11885a5eeccaSmarks 
11895a5eeccaSmarks 	if (error && positional) {
11905a5eeccaSmarks 		/*
11915a5eeccaSmarks 		 * If positional was set, then make sure permissions
11925a5eeccaSmarks 		 * aren't actually valid in non positional case where
11935a5eeccaSmarks 		 * all permissions are specified, just in random order.
11945a5eeccaSmarks 		 */
11955a5eeccaSmarks 		error = compute_values(ace_perm_table,
11965a5eeccaSmarks 		    ACE_PERM_COUNT, str, 0, mask);
11975a5eeccaSmarks 	}
11985a5eeccaSmarks 	if (error)
11995a5eeccaSmarks 		error = EACL_PERM_MASK_ERROR;
12005a5eeccaSmarks 
12015a5eeccaSmarks 	return (error);
12025a5eeccaSmarks }
12035a5eeccaSmarks 
12045a5eeccaSmarks 
12055a5eeccaSmarks 
12065a5eeccaSmarks /*
12075a5eeccaSmarks  * compute values for aclent permissions.
12085a5eeccaSmarks  */
12095a5eeccaSmarks int
12105a5eeccaSmarks compute_aclent_perms(char *str, o_mode_t *mask)
12115a5eeccaSmarks {
12125a5eeccaSmarks 	int error;
12135a5eeccaSmarks 	uint32_t pmask;
12145a5eeccaSmarks 
12155a5eeccaSmarks 	if (strlen(str) != ACLENT_PERM_COUNT)
12165a5eeccaSmarks 		return (EACL_PERM_MASK_ERROR);
12175a5eeccaSmarks 
12185a5eeccaSmarks 	*mask = 0;
12195a5eeccaSmarks 	error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT,
12205a5eeccaSmarks 	    str, 1, &pmask);
12215a5eeccaSmarks 	if (error == 0) {
12225a5eeccaSmarks 		*mask = (o_mode_t)pmask;
12235a5eeccaSmarks 	} else
12245a5eeccaSmarks 		error = EACL_PERM_MASK_ERROR;
12255a5eeccaSmarks 	return (error);
12265a5eeccaSmarks }
12275a5eeccaSmarks 
12285a5eeccaSmarks /*
12295a5eeccaSmarks  * determine ACE permissions.
12305a5eeccaSmarks  */
12315a5eeccaSmarks int
12325a5eeccaSmarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask)
12335a5eeccaSmarks {
12345a5eeccaSmarks 	int error;
12355a5eeccaSmarks 
12365a5eeccaSmarks 	if (aclperm->perm_style == PERM_TYPE_EMPTY) {
12375a5eeccaSmarks 		*mask = 0;
12385a5eeccaSmarks 		return (0);
12395a5eeccaSmarks 	}
12405a5eeccaSmarks 
12415a5eeccaSmarks 	if (aclperm->perm_style == PERM_TYPE_ACE) {
12425a5eeccaSmarks 		*mask = aclperm->perm_val;
12435a5eeccaSmarks 		return (0);
12445a5eeccaSmarks 	}
12455a5eeccaSmarks 
12465a5eeccaSmarks 	error = compute_ace_perms(aclperm->perm_str, mask);
12475a5eeccaSmarks 	if (error) {
12485b233e2dSmarks 		acl_error(dgettext(TEXT_DOMAIN,
12495b233e2dSmarks 		    "Invalid permission(s) '%s' specified\n"),
12505a5eeccaSmarks 		    aclperm->perm_str);
12515a5eeccaSmarks 		return (EACL_PERM_MASK_ERROR);
12525a5eeccaSmarks 	}
12535a5eeccaSmarks 
12545a5eeccaSmarks 	return (0);
12555a5eeccaSmarks }
1256