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 /*
22*6269Smarks  * Copyright 2008 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 char *
2381515Sgjelinek ace_type_txt(char *buf, char **endp, ace_t *acep, int flags)
2391420Smarks {
2401420Smarks 
2411535Smarks 	char idp[ID_STR_MAX];
2421420Smarks 
2431420Smarks 	if (buf == NULL)
2441420Smarks 		return (NULL);
2451420Smarks 
2461420Smarks 	switch (acep->a_flags & ACE_TYPE_FLAGS) {
2471420Smarks 	case ACE_OWNER:
2481420Smarks 		strcpy(buf, OWNERAT_TXT);
2491420Smarks 		*endp = buf + sizeof (OWNERAT_TXT) - 1;
2501420Smarks 		break;
2511420Smarks 
2521420Smarks 	case ACE_GROUP|ACE_IDENTIFIER_GROUP:
2531420Smarks 		strcpy(buf, GROUPAT_TXT);
2541420Smarks 		*endp = buf + sizeof (GROUPAT_TXT) - 1;
2551420Smarks 		break;
2561420Smarks 
2571420Smarks 	case ACE_IDENTIFIER_GROUP:
2581420Smarks 		strcpy(buf, GROUP_TXT);
2591535Smarks 		strcat(buf, prgname(acep->a_who, idp,
2601535Smarks 		    sizeof (idp), flags & ACL_NORESOLVE));
2611420Smarks 		*endp = buf + strlen(buf);
2621420Smarks 		break;
2631420Smarks 
2641420Smarks 	case ACE_EVERYONE:
2651420Smarks 		strcpy(buf, EVERYONEAT_TXT);
2661420Smarks 		*endp = buf + sizeof (EVERYONEAT_TXT) - 1;
2671420Smarks 		break;
2681420Smarks 
2691420Smarks 	case 0:
2701420Smarks 		strcpy(buf, USER_TXT);
2711535Smarks 		strcat(buf, pruname(acep->a_who, idp,
2721535Smarks 		    sizeof (idp), flags & ACL_NORESOLVE));
2731420Smarks 		*endp = buf + strlen(buf);
2741420Smarks 		break;
2751420Smarks 	}
2761420Smarks 
2771420Smarks 	return (buf);
2781420Smarks }
2791420Smarks 
2801420Smarks char *
2811420Smarks ace_perm_txt(char *buf, char **endp, uint32_t mask,
2821420Smarks     uint32_t iflags, int isdir, int flags)
2831420Smarks {
2841420Smarks 	char *lend = buf;		/* local end */
2851420Smarks 
2861420Smarks 	if (buf == NULL)
2871420Smarks 		return (NULL);
2881420Smarks 
2891420Smarks 	if (flags & ACL_COMPACT_FMT) {
290789Sahrens 
2911420Smarks 		if (mask & ACE_READ_DATA)
2921420Smarks 			buf[0] = 'r';
2931420Smarks 		else
2941420Smarks 			buf[0] = '-';
2951420Smarks 		if (mask & ACE_WRITE_DATA)
2961420Smarks 			buf[1] = 'w';
2971420Smarks 		else
2981420Smarks 			buf[1] = '-';
2991420Smarks 		if (mask & ACE_EXECUTE)
3001420Smarks 			buf[2] = 'x';
3011420Smarks 		else
3021420Smarks 			buf[2] = '-';
3031420Smarks 		if (mask & ACE_APPEND_DATA)
3041420Smarks 			buf[3] = 'p';
3051420Smarks 		else
3061420Smarks 			buf[3] = '-';
3071420Smarks 		if (mask & ACE_DELETE)
3081420Smarks 			buf[4] = 'd';
3091420Smarks 		else
3101420Smarks 			buf[4] = '-';
3111420Smarks 		if (mask & ACE_DELETE_CHILD)
3121420Smarks 			buf[5] = 'D';
3131420Smarks 		else
3141420Smarks 			buf[5] = '-';
3151420Smarks 		if (mask & ACE_READ_ATTRIBUTES)
3161420Smarks 			buf[6] = 'a';
3171420Smarks 		else
3181420Smarks 			buf[6] = '-';
3191420Smarks 		if (mask & ACE_WRITE_ATTRIBUTES)
3201420Smarks 			buf[7] = 'A';
3211420Smarks 		else
3221420Smarks 			buf[7] = '-';
3231420Smarks 		if (mask & ACE_READ_NAMED_ATTRS)
3241420Smarks 			buf[8] = 'R';
3251420Smarks 		else
3261420Smarks 			buf[8] = '-';
3271420Smarks 		if (mask & ACE_WRITE_NAMED_ATTRS)
3281420Smarks 			buf[9] = 'W';
3291420Smarks 		else
3301420Smarks 			buf[9] = '-';
3311420Smarks 		if (mask & ACE_READ_ACL)
3321420Smarks 			buf[10] = 'c';
3331420Smarks 		else
3341420Smarks 			buf[10] = '-';
3351420Smarks 		if (mask & ACE_WRITE_ACL)
3361420Smarks 			buf[11] = 'C';
3371420Smarks 		else
3381420Smarks 			buf[11] = '-';
3391420Smarks 		if (mask & ACE_WRITE_OWNER)
3401420Smarks 			buf[12] = 'o';
3411420Smarks 		else
3421420Smarks 			buf[12] = '-';
3431420Smarks 		if (mask & ACE_SYNCHRONIZE)
3441420Smarks 			buf[13] = 's';
3451420Smarks 		else
3461420Smarks 			buf[13] = '-';
3471420Smarks 		buf[14] = '\0';
3481420Smarks 		*endp = buf + 14;
3491420Smarks 		return (buf);
3501420Smarks 	} else {
3511420Smarks 		/*
3521420Smarks 		 * If ACE is a directory, but inheritance indicates its
3531420Smarks 		 * for a file then print permissions for file rather than
3541420Smarks 		 * dir.
3551420Smarks 		 */
3561420Smarks 		if (isdir) {
3571420Smarks 			if (mask & ACE_LIST_DIRECTORY) {
3581420Smarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
3591420Smarks 					strcpy(lend, READ_DATA_TXT);
3601420Smarks 					lend += sizeof (READ_DATA_TXT) - 1;
3611420Smarks 				} else {
3621420Smarks 					strcpy(lend, READ_DIR_TXT);
3631420Smarks 					lend += sizeof (READ_DIR_TXT) - 1;
3641420Smarks 				}
3651420Smarks 			}
3661420Smarks 			if (mask & ACE_ADD_FILE) {
3671420Smarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
3681420Smarks 					strcpy(lend, WRITE_DATA_TXT);
3691420Smarks 					lend += sizeof (WRITE_DATA_TXT) - 1;
3701420Smarks 				} else {
3711420Smarks 					strcpy(lend, ADD_FILE_TXT);
3721420Smarks 					lend +=
3731420Smarks 					    sizeof (ADD_FILE_TXT) -1;
3741420Smarks 				}
3751420Smarks 			}
3761420Smarks 			if (mask & ACE_ADD_SUBDIRECTORY) {
3771420Smarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
3781420Smarks 					strcpy(lend, APPEND_DATA_TXT);
3791420Smarks 					lend += sizeof (APPEND_DATA_TXT) - 1;
3801420Smarks 				} else {
3811420Smarks 					strcpy(lend, ADD_DIR_TXT);
3821420Smarks 					lend += sizeof (ADD_DIR_TXT) - 1;
3831420Smarks 				}
3841420Smarks 			}
3851420Smarks 		} else {
3861420Smarks 			if (mask & ACE_READ_DATA) {
3871420Smarks 				strcpy(lend, READ_DATA_TXT);
3881420Smarks 				lend += sizeof (READ_DATA_TXT) - 1;
3891420Smarks 			}
3901420Smarks 			if (mask & ACE_WRITE_DATA) {
3911420Smarks 				strcpy(lend, WRITE_DATA_TXT);
3921420Smarks 				lend += sizeof (WRITE_DATA_TXT) - 1;
3931420Smarks 			}
3941420Smarks 			if (mask & ACE_APPEND_DATA) {
3951420Smarks 				strcpy(lend, APPEND_DATA_TXT);
3961420Smarks 				lend += sizeof (APPEND_DATA_TXT) - 1;
3971420Smarks 			}
3981420Smarks 		}
3991420Smarks 		if (mask & ACE_READ_NAMED_ATTRS) {
4001420Smarks 			strcpy(lend, READ_XATTR_TXT);
4011420Smarks 			lend += sizeof (READ_XATTR_TXT) - 1;
4021420Smarks 		}
4031420Smarks 		if (mask & ACE_WRITE_NAMED_ATTRS) {
4041420Smarks 			strcpy(lend, WRITE_XATTR_TXT);
4051420Smarks 			lend += sizeof (WRITE_XATTR_TXT) - 1;
4061420Smarks 		}
4071420Smarks 		if (mask & ACE_EXECUTE) {
4081420Smarks 			strcpy(lend, EXECUTE_TXT);
4091420Smarks 			lend += sizeof (EXECUTE_TXT) - 1;
4101420Smarks 		}
4111420Smarks 		if (mask & ACE_DELETE_CHILD) {
4121420Smarks 			strcpy(lend, DELETE_CHILD_TXT);
4131420Smarks 			lend += sizeof (DELETE_CHILD_TXT) - 1;
4141420Smarks 		}
4151420Smarks 		if (mask & ACE_READ_ATTRIBUTES) {
4161420Smarks 			strcpy(lend, READ_ATTRIBUTES_TXT);
4171420Smarks 			lend += sizeof (READ_ATTRIBUTES_TXT) - 1;
4181420Smarks 		}
4191420Smarks 		if (mask & ACE_WRITE_ATTRIBUTES) {
4201420Smarks 			strcpy(lend, WRITE_ATTRIBUTES_TXT);
4211420Smarks 			lend += sizeof (WRITE_ATTRIBUTES_TXT) - 1;
4221420Smarks 		}
4231420Smarks 		if (mask & ACE_DELETE) {
4241420Smarks 			strcpy(lend, DELETE_TXT);
4251420Smarks 			lend += sizeof (DELETE_TXT) - 1;
4261420Smarks 		}
4271420Smarks 		if (mask & ACE_READ_ACL) {
4281420Smarks 			strcpy(lend, READ_ACL_TXT);
4291420Smarks 			lend += sizeof (READ_ACL_TXT) - 1;
4301420Smarks 		}
4311420Smarks 		if (mask & ACE_WRITE_ACL) {
4321420Smarks 			strcpy(lend, WRITE_ACL_TXT);
4331420Smarks 			lend += sizeof (WRITE_ACL_TXT) - 1;
4341420Smarks 		}
4351420Smarks 		if (mask & ACE_WRITE_OWNER) {
4361420Smarks 			strcpy(lend, WRITE_OWNER_TXT);
4371420Smarks 			lend += sizeof (WRITE_OWNER_TXT) - 1;
4381420Smarks 		}
4391420Smarks 		if (mask & ACE_SYNCHRONIZE) {
4401420Smarks 			strcpy(lend, SYNCHRONIZE_TXT);
4411420Smarks 			lend += sizeof (SYNCHRONIZE_TXT) - 1;
4421420Smarks 		}
443789Sahrens 
4441420Smarks 		if (*(lend - 1) == '/')
4451420Smarks 			*--lend = '\0';
4461420Smarks 	}
4471420Smarks 
4481420Smarks 	*endp = lend;
4491420Smarks 	return (buf);
4501420Smarks }
4511420Smarks 
4521420Smarks char *
4531420Smarks ace_access_txt(char *buf, char **endp, int type)
4541420Smarks {
4551420Smarks 
4561420Smarks 	if (buf == NULL)
4571420Smarks 		return (NULL);
4581420Smarks 
4591420Smarks 	if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
4601420Smarks 		strcpy(buf, ALLOW_TXT);
4611420Smarks 		*endp += sizeof (ALLOW_TXT) - 1;
4621420Smarks 	} else if (type == ACE_ACCESS_DENIED_ACE_TYPE) {
4631420Smarks 		strcpy(buf, DENY_TXT);
4641420Smarks 		*endp += sizeof (DENY_TXT) - 1;
4651420Smarks 	} else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) {
4661420Smarks 		strcpy(buf, AUDIT_TXT);
4671420Smarks 		*endp += sizeof (AUDIT_TXT) - 1;
4681420Smarks 	} else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) {
4691420Smarks 		strcpy(buf, ALARM_TXT);
4701420Smarks 		*endp += sizeof (ALARM_TXT) - 1;
4711420Smarks 	} else {
4721420Smarks 		strcpy(buf, UNKNOWN_TXT);
4731420Smarks 		*endp += sizeof (UNKNOWN_TXT) - 1;
4741420Smarks 	}
4751420Smarks 
4761420Smarks 	return (buf);
4771420Smarks }
4781420Smarks 
4791420Smarks static char *
4801420Smarks ace_inherit_txt(char *buf, char **endp, uint32_t iflags, int flags)
4811420Smarks {
4821420Smarks 
4831420Smarks 	char *lend = buf;
4841420Smarks 
4851420Smarks 	if (buf == NULL) {
4861420Smarks 		return (NULL);
4871420Smarks 	}
488789Sahrens 
4891420Smarks 	if (flags & ACL_COMPACT_FMT) {
4901420Smarks 		if (iflags & ACE_FILE_INHERIT_ACE)
4911420Smarks 			buf[0] = 'f';
4921420Smarks 		else
4931420Smarks 			buf[0] = '-';
4941420Smarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE)
4951420Smarks 			buf[1] = 'd';
4961420Smarks 		else
4971420Smarks 			buf[1] = '-';
4981420Smarks 		if (iflags & ACE_INHERIT_ONLY_ACE)
4991420Smarks 			buf[2] = 'i';
5001420Smarks 		else
5011420Smarks 			buf[2] = '-';
5021420Smarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)
5031420Smarks 			buf[3] = 'n';
5041420Smarks 		else
5051420Smarks 			buf[3] = '-';
5061420Smarks 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
5071420Smarks 			buf[4] = 'S';
5081420Smarks 		else
5091420Smarks 			buf[4] = '-';
5101420Smarks 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG)
5111420Smarks 			buf[5] = 'F';
5121420Smarks 		else
5131420Smarks 			buf[5] = '-';
5145331Samw 		if (iflags & ACE_INHERITED_ACE)
5155331Samw 			buf[6] = 'I';
5165331Samw 		else
5175331Samw 			buf[6] = '-';
5185331Samw 		buf[7] = '\0';
5195331Samw 		*endp = buf + 7;
5201420Smarks 	} else {
5211420Smarks 		if (iflags & ACE_FILE_INHERIT_ACE) {
5221420Smarks 			strcpy(lend, "file_inherit/");
5231420Smarks 			lend += sizeof ("file_inherit/") - 1;
5241420Smarks 		}
5251420Smarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE) {
5261420Smarks 			strcpy(lend, "dir_inherit/");
5271420Smarks 			lend += sizeof ("dir_inherit/") - 1;
5281420Smarks 		}
5291420Smarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) {
5301420Smarks 			strcpy(lend, "no_propagate/");
5311420Smarks 			lend += sizeof ("no_propagate/") - 1;
5321420Smarks 		}
5331420Smarks 		if (iflags & ACE_INHERIT_ONLY_ACE) {
5341420Smarks 			strcpy(lend, "inherit_only/");
5351420Smarks 			lend += sizeof ("inherit_only/") - 1;
5361420Smarks 		}
5375331Samw 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) {
5385331Samw 			strcpy(lend, "successful_access/");
5395331Samw 			lend += sizeof ("successful_access/") - 1;
5405331Samw 		}
5415331Samw 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) {
5425331Samw 			strcpy(lend, "failed_access/");
5435331Samw 			lend += sizeof ("failed_access/") - 1;
5445331Samw 		}
5455331Samw 		if (iflags & ACE_INHERITED_ACE) {
5465331Samw 			strcpy(lend, "inherited/");
5475331Samw 			lend += sizeof ("inherited/") - 1;
5485331Samw 		}
549789Sahrens 
5501420Smarks 		if (*(lend - 1) == '/')
5511420Smarks 			*--lend = '\0';
5521420Smarks 		*endp = lend;
5531420Smarks 	}
5541420Smarks 
5551420Smarks 	return (buf);
556789Sahrens }
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate /*
5590Sstevel@tonic-gate  * Convert internal acl representation to external representation.
5600Sstevel@tonic-gate  *
5610Sstevel@tonic-gate  * The length of a non-owning user name or non-owning group name ie entries
5620Sstevel@tonic-gate  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
5630Sstevel@tonic-gate  * thus check the length of these entries, and if greater than LOGNAME_MAX,
5640Sstevel@tonic-gate  * we realloc() via increase_length().
5650Sstevel@tonic-gate  *
5660Sstevel@tonic-gate  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
5670Sstevel@tonic-gate  * adhered to.
5680Sstevel@tonic-gate  */
5691420Smarks 
5701420Smarks /*
5711420Smarks  * acltotext() converts each ACL entry to look like this:
5721420Smarks  *
5731420Smarks  *    entry_type:uid^gid^name:perms[:id]
5741420Smarks  *
5751420Smarks  * The maximum length of entry_type is 14 ("defaultgroup::" and
5761420Smarks  * "defaultother::") hence ENTRYTYPELEN is set to 14.
5771420Smarks  *
5781420Smarks  * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
5791420Smarks  * however the ID could be a number so we therefore use ID_STR_MAX
5801420Smarks  *
5811420Smarks  * The length of a perms entry is 4 to allow for the comma appended to each
5821420Smarks  * to each acl entry.  Hence PERMS is set to 4.
5831420Smarks  */
5841420Smarks 
5851420Smarks #define	ENTRYTYPELEN	14
5861420Smarks #define	PERMS		4
5871420Smarks #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
5881420Smarks #define	UPDATE_WHERE	where = dstr->aclexport + strlen(dstr->aclexport)
5891420Smarks 
5900Sstevel@tonic-gate char *
5911420Smarks aclent_acltotext(aclent_t  *aclp, int aclcnt, int flags)
5920Sstevel@tonic-gate {
5930Sstevel@tonic-gate 	char		*aclexport;
5940Sstevel@tonic-gate 	char		*where;
5951507Sgjelinek 	struct group	*groupp = NULL;
5961507Sgjelinek 	struct passwd	*passwdp = NULL;
5970Sstevel@tonic-gate 	struct dynaclstr *dstr;
5980Sstevel@tonic-gate 	int		i, rtn;
5990Sstevel@tonic-gate 	size_t		excess = 0;
6001535Smarks 	char		id[ID_STR_MAX], *idstr;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	if (aclp == NULL)
6030Sstevel@tonic-gate 		return (NULL);
6040Sstevel@tonic-gate 	if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL)
6050Sstevel@tonic-gate 		return (NULL);
6060Sstevel@tonic-gate 	dstr->bufsize = aclcnt * ACL_ENTRY_SIZE;
6070Sstevel@tonic-gate 	if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) {
6080Sstevel@tonic-gate 		free(dstr);
6090Sstevel@tonic-gate 		return (NULL);
6100Sstevel@tonic-gate 	}
6110Sstevel@tonic-gate 	*dstr->aclexport = '\0';
6120Sstevel@tonic-gate 	where = dstr->aclexport;
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 	for (i = 0; i < aclcnt; i++, aclp++) {
6150Sstevel@tonic-gate 		switch (aclp->a_type) {
6160Sstevel@tonic-gate 		case DEF_USER_OBJ:
6170Sstevel@tonic-gate 		case USER_OBJ:
6180Sstevel@tonic-gate 			if (aclp->a_type == USER_OBJ)
6190Sstevel@tonic-gate 				where = strappend(where, "user::");
6200Sstevel@tonic-gate 			else
6210Sstevel@tonic-gate 				where = strappend(where, "defaultuser::");
6220Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6230Sstevel@tonic-gate 			break;
6240Sstevel@tonic-gate 		case DEF_USER:
6250Sstevel@tonic-gate 		case USER:
6260Sstevel@tonic-gate 			if (aclp->a_type == USER)
6270Sstevel@tonic-gate 				where = strappend(where, "user:");
6280Sstevel@tonic-gate 			else
6290Sstevel@tonic-gate 				where = strappend(where, "defaultuser:");
6301507Sgjelinek 			if ((flags & ACL_NORESOLVE) == 0)
6311507Sgjelinek 				passwdp = getpwuid(aclp->a_id);
6320Sstevel@tonic-gate 			if (passwdp == (struct passwd *)NULL) {
6330Sstevel@tonic-gate 				/* put in uid instead */
6340Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
635922Shm123892 				UPDATE_WHERE;
6360Sstevel@tonic-gate 			} else {
6370Sstevel@tonic-gate 				excess = strlen(passwdp->pw_name) - LOGNAME_MAX;
6380Sstevel@tonic-gate 				if (excess > 0) {
6390Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
6400Sstevel@tonic-gate 					if (rtn == 1) {
641922Shm123892 						UPDATE_WHERE;
6420Sstevel@tonic-gate 					} else {
6430Sstevel@tonic-gate 						free(dstr->aclexport);
6440Sstevel@tonic-gate 						free(dstr);
6450Sstevel@tonic-gate 						return (NULL);
6460Sstevel@tonic-gate 					}
6470Sstevel@tonic-gate 				}
6480Sstevel@tonic-gate 				where = strappend(where, passwdp->pw_name);
6490Sstevel@tonic-gate 			}
6500Sstevel@tonic-gate 			where = strappend(where, ":");
6510Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6520Sstevel@tonic-gate 			break;
6530Sstevel@tonic-gate 		case DEF_GROUP_OBJ:
6540Sstevel@tonic-gate 		case GROUP_OBJ:
6550Sstevel@tonic-gate 			if (aclp->a_type == GROUP_OBJ)
6560Sstevel@tonic-gate 				where = strappend(where, "group::");
6570Sstevel@tonic-gate 			else
6580Sstevel@tonic-gate 				where = strappend(where, "defaultgroup::");
6590Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6600Sstevel@tonic-gate 			break;
6610Sstevel@tonic-gate 		case DEF_GROUP:
6620Sstevel@tonic-gate 		case GROUP:
6630Sstevel@tonic-gate 			if (aclp->a_type == GROUP)
6640Sstevel@tonic-gate 				where = strappend(where, "group:");
6650Sstevel@tonic-gate 			else
6660Sstevel@tonic-gate 				where = strappend(where, "defaultgroup:");
6671507Sgjelinek 			if ((flags & ACL_NORESOLVE) == 0)
6681507Sgjelinek 				groupp = getgrgid(aclp->a_id);
6690Sstevel@tonic-gate 			if (groupp == (struct group *)NULL) {
6700Sstevel@tonic-gate 				/* put in gid instead */
6710Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
672922Shm123892 				UPDATE_WHERE;
6730Sstevel@tonic-gate 			} else {
6740Sstevel@tonic-gate 				excess = strlen(groupp->gr_name) - LOGNAME_MAX;
6750Sstevel@tonic-gate 				if (excess > 0) {
6760Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
6770Sstevel@tonic-gate 					if (rtn == 1) {
678922Shm123892 						UPDATE_WHERE;
6790Sstevel@tonic-gate 					} else {
6800Sstevel@tonic-gate 						free(dstr->aclexport);
6810Sstevel@tonic-gate 						free(dstr);
6820Sstevel@tonic-gate 						return (NULL);
6830Sstevel@tonic-gate 					}
6840Sstevel@tonic-gate 				}
6850Sstevel@tonic-gate 				where = strappend(where, groupp->gr_name);
6860Sstevel@tonic-gate 			}
6870Sstevel@tonic-gate 			where = strappend(where, ":");
6880Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6890Sstevel@tonic-gate 			break;
6900Sstevel@tonic-gate 		case DEF_CLASS_OBJ:
6910Sstevel@tonic-gate 		case CLASS_OBJ:
6920Sstevel@tonic-gate 			if (aclp->a_type == CLASS_OBJ)
6930Sstevel@tonic-gate 				where = strappend(where, "mask:");
6940Sstevel@tonic-gate 			else
6950Sstevel@tonic-gate 				where = strappend(where, "defaultmask:");
6960Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6970Sstevel@tonic-gate 			break;
6980Sstevel@tonic-gate 		case DEF_OTHER_OBJ:
6990Sstevel@tonic-gate 		case OTHER_OBJ:
7000Sstevel@tonic-gate 			if (aclp->a_type == OTHER_OBJ)
7010Sstevel@tonic-gate 				where = strappend(where, "other:");
7020Sstevel@tonic-gate 			else
7030Sstevel@tonic-gate 				where = strappend(where, "defaultother:");
7040Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
7050Sstevel@tonic-gate 			break;
7060Sstevel@tonic-gate 		default:
7070Sstevel@tonic-gate 			free(dstr->aclexport);
7080Sstevel@tonic-gate 			free(dstr);
7090Sstevel@tonic-gate 			return (NULL);
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 		}
7121420Smarks 
7131420Smarks 		if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) ||
7141420Smarks 		    (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) ||
7151420Smarks 		    (aclp->a_type == DEF_GROUP))) {
7161420Smarks 			where = strappend(where, ":");
7171420Smarks 			id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */
7181420Smarks 			idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]);
7191420Smarks 			where = strappend(where, idstr);
7201420Smarks 		}
7210Sstevel@tonic-gate 		if (i < aclcnt - 1)
7220Sstevel@tonic-gate 			where = strappend(where, ",");
7230Sstevel@tonic-gate 	}
7240Sstevel@tonic-gate 	aclexport = dstr->aclexport;
7250Sstevel@tonic-gate 	free(dstr);
7260Sstevel@tonic-gate 	return (aclexport);
7271420Smarks 
7281420Smarks 
7291420Smarks 
7301420Smarks 
7310Sstevel@tonic-gate }
7320Sstevel@tonic-gate 
7331420Smarks char *
7341420Smarks acltotext(aclent_t *aclp, int aclcnt)
7350Sstevel@tonic-gate {
7361420Smarks 	return (aclent_acltotext(aclp, aclcnt, 0));
7371420Smarks }
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate 
740789Sahrens aclent_t *
741789Sahrens aclfromtext(char *aclstr, int *aclcnt)
742789Sahrens {
743789Sahrens 	acl_t *aclp;
744789Sahrens 	aclent_t *aclentp;
745789Sahrens 	int error;
746789Sahrens 
7471420Smarks 	error = acl_fromtext(aclstr, &aclp);
748789Sahrens 	if (error)
749789Sahrens 		return (NULL);
750789Sahrens 
751789Sahrens 	aclentp = aclp->acl_aclp;
752789Sahrens 	aclp->acl_aclp = NULL;
7531420Smarks 	*aclcnt = aclp->acl_cnt;
754789Sahrens 
7551420Smarks 	acl_free(aclp);
756789Sahrens 	return (aclentp);
757789Sahrens }
758789Sahrens 
759789Sahrens 
7600Sstevel@tonic-gate static char *
7610Sstevel@tonic-gate strappend(char *where, char *newstr)
7620Sstevel@tonic-gate {
7630Sstevel@tonic-gate 	(void) strcat(where, newstr);
7640Sstevel@tonic-gate 	return (where + strlen(newstr));
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate static char *
7680Sstevel@tonic-gate convert_perm(char *where, o_mode_t perm)
7690Sstevel@tonic-gate {
7701420Smarks 	if (perm & S_IROTH)
7710Sstevel@tonic-gate 		where = strappend(where, "r");
7720Sstevel@tonic-gate 	else
7730Sstevel@tonic-gate 		where = strappend(where, "-");
7741420Smarks 	if (perm & S_IWOTH)
7750Sstevel@tonic-gate 		where = strappend(where, "w");
7760Sstevel@tonic-gate 	else
7770Sstevel@tonic-gate 		where = strappend(where, "-");
7781420Smarks 	if (perm & S_IXOTH)
7790Sstevel@tonic-gate 		where = strappend(where, "x");
7800Sstevel@tonic-gate 	else
7810Sstevel@tonic-gate 		where = strappend(where, "-");
7820Sstevel@tonic-gate 	/* perm is the last field */
7830Sstevel@tonic-gate 	return (where);
7840Sstevel@tonic-gate }
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate /*
7870Sstevel@tonic-gate  * Callers should check the return code as this routine may change the string
7880Sstevel@tonic-gate  * pointer in dynaclstr.
7890Sstevel@tonic-gate  */
7900Sstevel@tonic-gate static int
7910Sstevel@tonic-gate increase_length(struct dynaclstr *dacl, size_t increase)
7920Sstevel@tonic-gate {
7930Sstevel@tonic-gate 	char *tptr;
7940Sstevel@tonic-gate 	size_t newsize;
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 	newsize = dacl->bufsize + increase;
7970Sstevel@tonic-gate 	tptr = realloc(dacl->aclexport, newsize);
7980Sstevel@tonic-gate 	if (tptr != NULL) {
7990Sstevel@tonic-gate 		dacl->aclexport = tptr;
8000Sstevel@tonic-gate 		dacl->bufsize = newsize;
8010Sstevel@tonic-gate 		return (1);
8020Sstevel@tonic-gate 	} else
8030Sstevel@tonic-gate 		return (0);
8040Sstevel@tonic-gate }
805789Sahrens 
806789Sahrens /*
8071420Smarks  * ace_acltotext() convert each ace formatted acl to look like this:
808789Sahrens  *
8091420Smarks  * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
810789Sahrens  *
811789Sahrens  * The maximum length of entry_type is 5 ("group")
812789Sahrens  *
8131420Smarks  * The max length of a uid^gid^name entry (in theory) is 8,
8141420Smarks  * however id could be a number so we therefore use ID_STR_MAX
815789Sahrens  *
816789Sahrens  * The length of a perms entry is 144 i.e read_data/write_data...
817789Sahrens  * to each acl entry.
818789Sahrens  *
8195331Samw  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access
8205331Samw  *         /failed_access
821789Sahrens  *
822789Sahrens  */
823789Sahrens 
824789Sahrens #define	ACE_ENTRYTYPLEN		6
8255331Samw #define	IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \
8265331Samw 	"successful_access/failed_access/inherited"
8275331Samw #define	IFLAGS_SIZE		(sizeof (IFLAGS_STR) - 1)
8281420Smarks #define	ACCESS_TYPE_SIZE	7	/* if unknown */
829789Sahrens #define	COLON_CNT		3
830789Sahrens #define	PERMS_LEN		216
8315331Samw #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \
8321420Smarks     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
833789Sahrens 
834789Sahrens static char *
8351420Smarks ace_acltotext(acl_t *aceaclp, int flags)
836789Sahrens {
837789Sahrens 	ace_t		*aclp = aceaclp->acl_aclp;
838789Sahrens 	int		aclcnt = aceaclp->acl_cnt;
839789Sahrens 	char		*aclexport;
8401420Smarks 	char		*endp;
8411420Smarks 	int		i;
8421420Smarks 	char		id[ID_STR_MAX], *idstr;
843789Sahrens 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
844789Sahrens 
845789Sahrens 	if (aclp == NULL)
846789Sahrens 		return (NULL);
8471420Smarks 	if ((aclexport = malloc(aclcnt * ACE_ENTRY_SIZE)) == NULL)
848789Sahrens 		return (NULL);
849789Sahrens 
8501420Smarks 	aclexport[0] = '\0';
8511420Smarks 	endp = aclexport;
852789Sahrens 	for (i = 0; i < aclcnt; i++, aclp++) {
8531420Smarks 
8541515Sgjelinek 		(void) ace_type_txt(endp, &endp, aclp, flags);
8551420Smarks 		*endp++ = ':';
8561420Smarks 		*endp = '\0';
8571420Smarks 		(void) ace_perm_txt(endp, &endp, aclp->a_access_mask,
8581420Smarks 		    aclp->a_flags, isdir, flags);
8591420Smarks 		*endp++ = ':';
8601420Smarks 		*endp = '\0';
8611420Smarks 		(void) ace_inherit_txt(endp, &endp, aclp->a_flags, flags);
8621420Smarks 		if (flags & ACL_COMPACT_FMT || aclp->a_flags &
8631420Smarks 		    (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE |
8645331Samw 		    (ACE_INHERIT_ONLY_ACE | ACE_NO_PROPAGATE_INHERIT_ACE |
8655331Samw 		    ACE_INHERITED_ACE | ACE_SUCCESSFUL_ACCESS_ACE_FLAG |
8665331Samw 		    ACE_FAILED_ACCESS_ACE_FLAG))) {
8671420Smarks 			*endp++ = ':';
8681420Smarks 			*endp = '\0';
8691420Smarks 		}
8701420Smarks 		(void) ace_access_txt(endp, &endp, aclp->a_type);
871789Sahrens 
8721420Smarks 		if ((flags & ACL_APPEND_ID) &&
8731420Smarks 		    (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ||
8741420Smarks 		    ((aclp->a_flags & ACE_TYPE_FLAGS) ==
8751420Smarks 		    ACE_IDENTIFIER_GROUP))) {
8761420Smarks 			*endp++ = ':';
8771420Smarks 			*endp = '\0';
8781420Smarks 			id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */
8791420Smarks 			idstr = lltostr(aclp->a_who, &id[ID_STR_MAX - 1]);
8801420Smarks 			strcpy(endp, idstr);
8811420Smarks 			endp += strlen(idstr);
882789Sahrens 		}
8831420Smarks 		if (i < aclcnt - 1) {
8841420Smarks 			*endp++ = ',';
8851420Smarks 			*(endp + 1) = '\0';
886789Sahrens 		}
887789Sahrens 	}
888789Sahrens 	return (aclexport);
889789Sahrens }
890789Sahrens 
8911420Smarks char *
8921420Smarks acl_totext(acl_t *aclp, int flags)
893789Sahrens {
894789Sahrens 
8951420Smarks 	char *txtp;
896789Sahrens 
897789Sahrens 	if (aclp == NULL)
898789Sahrens 		return (NULL);
899789Sahrens 
900789Sahrens 	switch (aclp->acl_type) {
901789Sahrens 	case ACE_T:
9021420Smarks 		txtp = ace_acltotext(aclp, flags);
9031420Smarks 		break;
904789Sahrens 	case ACLENT_T:
9051420Smarks 		txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags);
9061420Smarks 		break;
907789Sahrens 	}
9081420Smarks 
9091420Smarks 	return (txtp);
910789Sahrens }
911789Sahrens 
912789Sahrens int
913789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp)
914789Sahrens {
9151420Smarks 	int error;
9161420Smarks 	char *buf;
9171420Smarks 
9181420Smarks 	buf = malloc(strlen(acltextp) + 2);
9191420Smarks 	if (buf == NULL)
9201420Smarks 		return (EACL_MEM_ERROR);
9211420Smarks 	strcpy(buf, acltextp);
9221420Smarks 	strcat(buf, "\n");
9231420Smarks 	yybuf = buf;
9241420Smarks 	yyreset();
9251420Smarks 	error = yyparse();
9261420Smarks 	free(buf);
9271420Smarks 
9281420Smarks 	if (yyacl) {
9291420Smarks 		if (error == 0)
9301420Smarks 			*ret_aclp = yyacl;
9311420Smarks 		else {
9321420Smarks 			acl_free(yyacl);
9331420Smarks 		}
9341420Smarks 		yyacl = NULL;
9351420Smarks 	}
9361420Smarks 	return (error);
9371420Smarks }
9381420Smarks 
9391420Smarks int
9401420Smarks acl_parse(const char *acltextp, acl_t **aclp)
9411420Smarks {
942789Sahrens 	int error;
943789Sahrens 
9441420Smarks 	yyinteractive = 1;
9451420Smarks 	error = acl_fromtext(acltextp, aclp);
9461420Smarks 	yyinteractive = 0;
9471420Smarks 	return (error);
9481420Smarks }
9491420Smarks 
9501420Smarks static void
9511420Smarks ace_compact_printacl(acl_t *aclp)
9521420Smarks {
9531420Smarks 	int cnt;
9541420Smarks 	ace_t *acep;
9551420Smarks 	char *endp;
9561420Smarks 	char buf[ACE_ENTRY_SIZE];
957789Sahrens 
9581420Smarks 	for (cnt = 0, acep = aclp->acl_aclp;
9591420Smarks 	    cnt != aclp->acl_cnt; cnt++, acep++) {
9601420Smarks 		buf[0] = '\0';
9611515Sgjelinek 		(void) printf("    %14s:", ace_type_txt(buf, &endp, acep, 0));
9621420Smarks 		(void) printf("%s:", ace_perm_txt(endp, &endp,
9631420Smarks 		    acep->a_access_mask, acep->a_flags,
9641420Smarks 		    aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT));
9651420Smarks 		(void) printf("%s:",
9661420Smarks 		    ace_inherit_txt(endp, &endp, acep->a_flags,
9675331Samw 		    ACL_COMPACT_FMT));
9681420Smarks 		(void) printf("%s\n", ace_access_txt(endp, &endp,
9691420Smarks 		    acep->a_type));
9701420Smarks 	}
9711420Smarks }
972789Sahrens 
9731420Smarks static void
9741420Smarks ace_printacl(acl_t *aclp, int cols, int compact)
9751420Smarks {
9761420Smarks 	int  slot = 0;
9771420Smarks 	char *token;
9781420Smarks 	char *acltext;
9791420Smarks 
9801420Smarks 	if (compact) {
9811420Smarks 		ace_compact_printacl(aclp);
9821420Smarks 		return;
983789Sahrens 	}
984789Sahrens 
9851420Smarks 	acltext = acl_totext(aclp, 0);
9861420Smarks 
9871420Smarks 	if (acltext == NULL)
9881420Smarks 		return;
9891420Smarks 
9901420Smarks 	token = strtok(acltext, ",");
9911420Smarks 	if (token == NULL) {
9921420Smarks 		free(acltext);
9931420Smarks 		return;
994789Sahrens 	}
995789Sahrens 
9961420Smarks 	do {
9971420Smarks 		(void) printf("     %d:", slot++);
9981420Smarks 		split_line(token, cols - 5);
9991420Smarks 	} while (token = strtok(NULL, ","));
10001420Smarks 	free(acltext);
10011420Smarks }
10021420Smarks 
10031420Smarks /*
10041420Smarks  * pretty print an ACL.
10051420Smarks  * For aclent_t ACL's the format is
10061420Smarks  * similar to the old format used by getfacl,
10071420Smarks  * with the addition of adding a "slot" number
10081420Smarks  * before each entry.
10091420Smarks  *
10101420Smarks  * for ace_t ACL's the cols variable will break up
10111420Smarks  * the long lines into multiple lines and will also
10121420Smarks  * print a "slot" number.
10131420Smarks  */
10141420Smarks void
10151420Smarks acl_printacl(acl_t *aclp, int cols, int compact)
10161420Smarks {
10171420Smarks 
10181420Smarks 	switch (aclp->acl_type) {
10191420Smarks 	case ACLENT_T:
10201420Smarks 		aclent_printacl(aclp);
10211420Smarks 		break;
10221420Smarks 	case ACE_T:
10231420Smarks 		ace_printacl(aclp, cols, compact);
10241420Smarks 		break;
10251420Smarks 	}
10261420Smarks }
10271420Smarks 
10281420Smarks typedef struct value_table {
10291420Smarks 	char		p_letter; /* perm letter such as 'r' */
10301420Smarks 	uint32_t	p_value; /* value for perm when pletter found */
10311420Smarks } value_table_t;
10321420Smarks 
10331420Smarks /*
10345331Samw  * The permission tables are laid out in positional order
10351420Smarks  * a '-' character will indicate a permission at a given
10361420Smarks  * position is not specified.  The '-' is not part of the
10371420Smarks  * table, but will be checked for in the permission computation
10381420Smarks  * routine.
10391420Smarks  */
10405331Samw value_table_t ace_perm_table[] = {
10411420Smarks 	{ 'r', ACE_READ_DATA},
10421420Smarks 	{ 'w', ACE_WRITE_DATA},
10431420Smarks 	{ 'x', ACE_EXECUTE},
10441420Smarks 	{ 'p', ACE_APPEND_DATA},
10451420Smarks 	{ 'd', ACE_DELETE},
10461420Smarks 	{ 'D', ACE_DELETE_CHILD},
10471420Smarks 	{ 'a', ACE_READ_ATTRIBUTES},
10481420Smarks 	{ 'A', ACE_WRITE_ATTRIBUTES},
10491420Smarks 	{ 'R', ACE_READ_NAMED_ATTRS},
10501420Smarks 	{ 'W', ACE_WRITE_NAMED_ATTRS},
10511420Smarks 	{ 'c', ACE_READ_ACL},
10521420Smarks 	{ 'C', ACE_WRITE_ACL},
10531420Smarks 	{ 'o', ACE_WRITE_OWNER},
10541420Smarks 	{ 's', ACE_SYNCHRONIZE}
10551420Smarks };
10561420Smarks 
10575331Samw #define	ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t))
10581420Smarks 
10595331Samw value_table_t aclent_perm_table[] = {
10601420Smarks 	{ 'r', S_IROTH},
10611420Smarks 	{ 'w', S_IWOTH},
10621420Smarks 	{ 'x', S_IXOTH}
10631420Smarks };
10641420Smarks 
10655331Samw #define	ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t))
10665331Samw 
10675331Samw value_table_t inherit_table[] = {
10681420Smarks 	{'f', ACE_FILE_INHERIT_ACE},
10691420Smarks 	{'d', ACE_DIRECTORY_INHERIT_ACE},
10701420Smarks 	{'i', ACE_INHERIT_ONLY_ACE},
10711420Smarks 	{'n', ACE_NO_PROPAGATE_INHERIT_ACE},
10721420Smarks 	{'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
10735331Samw 	{'F', ACE_FAILED_ACCESS_ACE_FLAG},
10745331Samw 	{'I', ACE_INHERITED_ACE}
10751420Smarks };
10761420Smarks 
10775331Samw #define	IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t))
1078*6269Smarks #define	IFLAG_COUNT_V1 6 /* Older version compatibility */
10795331Samw 
10801420Smarks /*
10811420Smarks  * compute value from a permission table or inheritance table
10821420Smarks  * based on string passed in.  If positional is set then
10831420Smarks  * string must match order in permtab, otherwise any order
10841420Smarks  * is allowed.
10851420Smarks  */
10861420Smarks int
10871420Smarks compute_values(value_table_t *permtab, int count,
10881420Smarks     char *permstr, int positional, uint32_t *mask)
10891420Smarks {
10901420Smarks 	uint32_t perm_val = 0;
10911420Smarks 	char *pstr;
10921420Smarks 	int i, found;
10931420Smarks 
10941420Smarks 	if (count < 0)
10951420Smarks 		return (1);
10961420Smarks 
10971420Smarks 	if (positional) {
10981420Smarks 		for (i = 0, pstr = permstr; i != count && pstr &&
10991420Smarks 		    *pstr; i++, pstr++) {
11001420Smarks 			if (*pstr == permtab[i].p_letter) {
11011420Smarks 				perm_val |= permtab[i].p_value;
11021420Smarks 			} else if (*pstr != '-') {
11031420Smarks 				return (1);
11041420Smarks 			}
1105789Sahrens 		}
11061420Smarks 	} else {  /* random order single letters with no '-' */
11071420Smarks 		for (pstr = permstr; pstr && *pstr; pstr++) {
11081420Smarks 			for (found = 0, i = 0; i != count; i++) {
11091420Smarks 				if (*pstr == permtab[i].p_letter) {
11101420Smarks 					perm_val |= permtab[i].p_value;
11111420Smarks 					found = 1;
11121420Smarks 					break;
11131420Smarks 				}
11141420Smarks 			}
11151420Smarks 			if (found == 0)
11161420Smarks 				return (1);
11171420Smarks 		}
1118789Sahrens 	}
1119789Sahrens 
11201420Smarks 	*mask = perm_val;
11211420Smarks 	return (0);
11221420Smarks }
1123789Sahrens 
1124*6269Smarks 
1125*6269Smarks int
1126*6269Smarks ace_inherit_helper(char *str, uint32_t *imask, int table_length)
1127*6269Smarks {
1128*6269Smarks 	int rc = 0;
1129*6269Smarks 
1130*6269Smarks 	if (strlen(str) == table_length) {
1131*6269Smarks 		/*
1132*6269Smarks 		 * If the string == table_length then first check to see it's
1133*6269Smarks 		 * in positional format.  If that fails then see if it's in
1134*6269Smarks 		 * non-positional format.
1135*6269Smarks 		 */
1136*6269Smarks 		if (compute_values(inherit_table, table_length, str,
1137*6269Smarks 		    1, imask) && compute_values(inherit_table,
1138*6269Smarks 		    table_length, str, 0, imask)) {
1139*6269Smarks 			rc = 1;
1140*6269Smarks 		}
1141*6269Smarks 	} else {
1142*6269Smarks 		rc = compute_values(inherit_table, table_length, str, 0, imask);
1143*6269Smarks 	}
1144*6269Smarks 
1145*6269Smarks 	return (rc ? EACL_INHERIT_ERROR : 0);
1146*6269Smarks }
1147*6269Smarks 
11481420Smarks /*
11491420Smarks  * compute value for inheritance flags.
11501420Smarks  */
11511420Smarks int
11521420Smarks compute_ace_inherit(char *str, uint32_t *imask)
11531420Smarks {
1154*6269Smarks 	int rc = 0;
1155789Sahrens 
1156*6269Smarks 	rc = ace_inherit_helper(str, imask, IFLAG_COUNT);
1157*6269Smarks 
1158*6269Smarks 	if (rc && strlen(str) != IFLAG_COUNT) {
11591420Smarks 
1160*6269Smarks 		/* is it an old formatted inherit string? */
1161*6269Smarks 		rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1);
1162*6269Smarks 	}
11631420Smarks 
1164*6269Smarks 	return (rc);
1165789Sahrens }
11661420Smarks 
11671420Smarks 
11681420Smarks /*
11691420Smarks  * compute value for ACE permissions.
11701420Smarks  */
11711420Smarks int
11721420Smarks compute_ace_perms(char *str, uint32_t *mask)
11731420Smarks {
11741420Smarks 	int positional = 0;
11751420Smarks 	int error;
11761420Smarks 
11771420Smarks 	if (strlen(str) == ACE_PERM_COUNT)
11781420Smarks 		positional = 1;
11791420Smarks 
11801420Smarks 	error = compute_values(ace_perm_table, ACE_PERM_COUNT,
11811420Smarks 	    str, positional, mask);
11821420Smarks 
11831420Smarks 	if (error && positional) {
11841420Smarks 		/*
11851420Smarks 		 * If positional was set, then make sure permissions
11861420Smarks 		 * aren't actually valid in non positional case where
11871420Smarks 		 * all permissions are specified, just in random order.
11881420Smarks 		 */
11891420Smarks 		error = compute_values(ace_perm_table,
11901420Smarks 		    ACE_PERM_COUNT, str, 0, mask);
11911420Smarks 	}
11921420Smarks 	if (error)
11931420Smarks 		error = EACL_PERM_MASK_ERROR;
11941420Smarks 
11951420Smarks 	return (error);
11961420Smarks }
11971420Smarks 
11981420Smarks 
11991420Smarks 
12001420Smarks /*
12011420Smarks  * compute values for aclent permissions.
12021420Smarks  */
12031420Smarks int
12041420Smarks compute_aclent_perms(char *str, o_mode_t *mask)
12051420Smarks {
12061420Smarks 	int error;
12071420Smarks 	uint32_t pmask;
12081420Smarks 
12091420Smarks 	if (strlen(str) != ACLENT_PERM_COUNT)
12101420Smarks 		return (EACL_PERM_MASK_ERROR);
12111420Smarks 
12121420Smarks 	*mask = 0;
12131420Smarks 	error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT,
12141420Smarks 	    str, 1, &pmask);
12151420Smarks 	if (error == 0) {
12161420Smarks 		*mask = (o_mode_t)pmask;
12171420Smarks 	} else
12181420Smarks 		error = EACL_PERM_MASK_ERROR;
12191420Smarks 	return (error);
12201420Smarks }
12211420Smarks 
12221420Smarks /*
12231420Smarks  * determine ACE permissions.
12241420Smarks  */
12251420Smarks int
12261420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask)
12271420Smarks {
12281420Smarks 	int error;
12291420Smarks 
12301420Smarks 	if (aclperm->perm_style == PERM_TYPE_EMPTY) {
12311420Smarks 		*mask = 0;
12321420Smarks 		return (0);
12331420Smarks 	}
12341420Smarks 
12351420Smarks 	if (aclperm->perm_style == PERM_TYPE_ACE) {
12361420Smarks 		*mask = aclperm->perm_val;
12371420Smarks 		return (0);
12381420Smarks 	}
12391420Smarks 
12401420Smarks 	error = compute_ace_perms(aclperm->perm_str, mask);
12411420Smarks 	if (error) {
12421567Smarks 		acl_error(dgettext(TEXT_DOMAIN,
12431567Smarks 		    "Invalid permission(s) '%s' specified\n"),
12441420Smarks 		    aclperm->perm_str);
12451420Smarks 		return (EACL_PERM_MASK_ERROR);
12461420Smarks 	}
12471420Smarks 
12481420Smarks 	return (0);
12491420Smarks }
1250