xref: /titanic_51/usr/src/lib/libsec/common/acltext.c (revision b249c65cf0a7400e86a36ddab5c3fce085809859)
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 /*
22bf8b6031Smarks  * Copyright 2008 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>
40*b249c65cSmarks #include <idmap.h>
41fa9e4066Sahrens 
425a5eeccaSmarks #define	ID_STR_MAX	20	/* digits in LONG_MAX */
435a5eeccaSmarks 
445a5eeccaSmarks #define	APPENDED_ID_MAX	ID_STR_MAX + 1		/* id + colon */
455a5eeccaSmarks /*
465a5eeccaSmarks  * yyinteractive controls whether yyparse should print out
475a5eeccaSmarks  * error messages to stderr, and whether or not id's should be
485a5eeccaSmarks  * allowed from acl_fromtext().
495a5eeccaSmarks  */
505a5eeccaSmarks int	yyinteractive;
515a5eeccaSmarks acl_t	*yyacl;
525a5eeccaSmarks char	*yybuf;
53fa9e4066Sahrens 
54fa9e4066Sahrens extern acl_t *acl_alloc(enum acl_type);
557c478bd9Sstevel@tonic-gate 
56*b249c65cSmarks /*
57*b249c65cSmarks  * dynamic string that will increase in size on an
58*b249c65cSmarks  * as needed basis.
59*b249c65cSmarks  */
60*b249c65cSmarks typedef struct dynaclstr {
61*b249c65cSmarks 	size_t d_bufsize;		/* current size of aclexport */
62*b249c65cSmarks 	char *d_aclexport;
63*b249c65cSmarks 	int d_pos;
64*b249c65cSmarks } dynaclstr_t;
6511e32170Shm123892 
66*b249c65cSmarks static int str_append(dynaclstr_t *, char *);
67*b249c65cSmarks static int aclent_perm_txt(dynaclstr_t *, o_mode_t);
687c478bd9Sstevel@tonic-gate 
695a5eeccaSmarks static void
705a5eeccaSmarks aclent_perms(int perm, char *txt_perms)
71fa9e4066Sahrens {
725a5eeccaSmarks 	if (perm & S_IROTH)
735a5eeccaSmarks 		txt_perms[0] = 'r';
745a5eeccaSmarks 	else
755a5eeccaSmarks 		txt_perms[0] = '-';
765a5eeccaSmarks 	if (perm & S_IWOTH)
775a5eeccaSmarks 		txt_perms[1] = 'w';
785a5eeccaSmarks 	else
795a5eeccaSmarks 		txt_perms[1] = '-';
805a5eeccaSmarks 	if (perm & S_IXOTH)
815a5eeccaSmarks 		txt_perms[2] = 'x';
825a5eeccaSmarks 	else
835a5eeccaSmarks 		txt_perms[2] = '-';
845a5eeccaSmarks 	txt_perms[3] = '\0';
855a5eeccaSmarks }
86fa9e4066Sahrens 
875a5eeccaSmarks static char *
88afe1f701Smarks pruname(uid_t uid, char *uidp, size_t buflen, int noresolve)
895a5eeccaSmarks {
9045a17f45Sgjelinek 	struct passwd	*passwdp = NULL;
91fa9e4066Sahrens 
9245a17f45Sgjelinek 	if (noresolve == 0)
935a5eeccaSmarks 		passwdp = getpwuid(uid);
945a5eeccaSmarks 	if (passwdp == (struct passwd *)NULL) {
955a5eeccaSmarks 		/* could not get passwd information: display uid instead */
96f48205beScasper 		(void) snprintf(uidp, buflen, "%u", uid);
97afe1f701Smarks 	} else {
98afe1f701Smarks 		(void) strlcpy(uidp, passwdp->pw_name, buflen);
99afe1f701Smarks 	}
1005a5eeccaSmarks 	return (uidp);
1015a5eeccaSmarks }
102fa9e4066Sahrens 
1035a5eeccaSmarks static char *
104afe1f701Smarks prgname(gid_t gid, char *gidp, size_t buflen, int noresolve)
1055a5eeccaSmarks {
10645a17f45Sgjelinek 	struct group	*groupp = NULL;
107fa9e4066Sahrens 
10845a17f45Sgjelinek 	if (noresolve == 0)
1095a5eeccaSmarks 		groupp = getgrgid(gid);
1105a5eeccaSmarks 	if (groupp == (struct group *)NULL) {
1115a5eeccaSmarks 		/* could not get group information: display gid instead */
112f48205beScasper 		(void) snprintf(gidp, buflen, "%u", gid);
113afe1f701Smarks 	} else {
114afe1f701Smarks 		(void) strlcpy(gidp, groupp->gr_name, buflen);
115afe1f701Smarks 	}
1165a5eeccaSmarks 	return (gidp);
1175a5eeccaSmarks }
118*b249c65cSmarks 
119*b249c65cSmarks static char *
120*b249c65cSmarks prsidname(uid_t who, boolean_t user, char **sidp, int noresolve)
121*b249c65cSmarks {
122*b249c65cSmarks 	idmap_handle_t *idmap_hdl = NULL;
123*b249c65cSmarks 	idmap_get_handle_t *get_hdl = NULL;
124*b249c65cSmarks 	idmap_stat status;
125*b249c65cSmarks 	idmap_rid_t rid;
126*b249c65cSmarks 	int error = 1;
127*b249c65cSmarks 	int len;
128*b249c65cSmarks 	char *domain;
129*b249c65cSmarks 	char *name;
130*b249c65cSmarks 
131*b249c65cSmarks 	if (noresolve) {
132*b249c65cSmarks 		len = snprintf(NULL, 0, "%u", who);
133*b249c65cSmarks 		*sidp = malloc(len + 1);
134*b249c65cSmarks 		(void) snprintf(*sidp, len + 1, "%u", who);
135*b249c65cSmarks 		return (*sidp);
136*b249c65cSmarks 	}
137*b249c65cSmarks 
138*b249c65cSmarks 	/*
139*b249c65cSmarks 	 * First try and get windows name
140*b249c65cSmarks 	 */
141*b249c65cSmarks 
142*b249c65cSmarks 	if (user)
143*b249c65cSmarks 		error = idmap_getwinnamebyuid(who, &name, &domain);
144*b249c65cSmarks 	else
145*b249c65cSmarks 		error = idmap_getwinnamebygid(who, &name, &domain);
146*b249c65cSmarks 
147*b249c65cSmarks 	if (error) {
148*b249c65cSmarks 		if (idmap_init(&idmap_hdl) == 0 &&
149*b249c65cSmarks 		    idmap_get_create(idmap_hdl, &get_hdl) == 0) {
150*b249c65cSmarks 			if (user)
151*b249c65cSmarks 				error = idmap_get_sidbyuid(get_hdl, who,
152*b249c65cSmarks 				    0, &domain, &rid, &status);
153*b249c65cSmarks 			else
154*b249c65cSmarks 				error = idmap_get_sidbygid(get_hdl, who,
155*b249c65cSmarks 				    0, &domain, &rid, &status);
156*b249c65cSmarks 			if (error == 0)
157*b249c65cSmarks 				error = idmap_get_mappings(get_hdl);
158*b249c65cSmarks 		}
159*b249c65cSmarks 		if (error == 0) {
160*b249c65cSmarks 			len = snprintf(NULL, 0, "%s-%d", domain, rid);
161*b249c65cSmarks 			*sidp = malloc(len + 1);
162*b249c65cSmarks 			(void) snprintf(*sidp, len + 1, "%s-%d", domain, rid);
163*b249c65cSmarks 		} else {
164*b249c65cSmarks 			*sidp = NULL;
165*b249c65cSmarks 		}
166*b249c65cSmarks 		if (get_hdl)
167*b249c65cSmarks 			idmap_get_destroy(get_hdl);
168*b249c65cSmarks 		if (idmap_hdl)
169*b249c65cSmarks 			(void) idmap_fini(idmap_hdl);
170*b249c65cSmarks 	} else {
171*b249c65cSmarks 		int len;
172*b249c65cSmarks 		len = snprintf(NULL, 0, "%s@%d", name, domain);
173*b249c65cSmarks 		*sidp = malloc(len + 1);
174*b249c65cSmarks 		(void) snprintf(*sidp, len + 1, "%s@%s", name, domain);
175*b249c65cSmarks 	}
176*b249c65cSmarks 	return (*sidp);
177*b249c65cSmarks }
178*b249c65cSmarks 
1795a5eeccaSmarks static void
1805a5eeccaSmarks aclent_printacl(acl_t *aclp)
1815a5eeccaSmarks {
1825a5eeccaSmarks 	aclent_t *tp;
1835a5eeccaSmarks 	int aclcnt;
1845a5eeccaSmarks 	int mask;
1855a5eeccaSmarks 	int slot = 0;
1865a5eeccaSmarks 	char perm[4];
187afe1f701Smarks 	char uidp[ID_STR_MAX];
188afe1f701Smarks 	char gidp[ID_STR_MAX];
1895a5eeccaSmarks 
1905a5eeccaSmarks 	/* display ACL: assume it is sorted. */
1915a5eeccaSmarks 	aclcnt = aclp->acl_cnt;
1925a5eeccaSmarks 	for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) {
1935a5eeccaSmarks 		if (tp->a_type == CLASS_OBJ)
1945a5eeccaSmarks 			mask = tp->a_perm;
1955a5eeccaSmarks 	}
1965a5eeccaSmarks 	aclcnt = aclp->acl_cnt;
1975a5eeccaSmarks 	for (tp = aclp->acl_aclp; aclcnt--; tp++) {
1985a5eeccaSmarks 		(void) printf("     %d:", slot++);
1995a5eeccaSmarks 		switch (tp->a_type) {
2005a5eeccaSmarks 		case USER:
2015a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2025a5eeccaSmarks 			(void) printf("user:%s:%s\t\t",
203afe1f701Smarks 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
2045a5eeccaSmarks 			aclent_perms((tp->a_perm & mask), perm);
2055a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
2065a5eeccaSmarks 			break;
2075a5eeccaSmarks 		case USER_OBJ:
2085a5eeccaSmarks 			/* no need to display uid */
2095a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2105a5eeccaSmarks 			(void) printf("user::%s\n", perm);
2115a5eeccaSmarks 			break;
2125a5eeccaSmarks 		case GROUP:
2135a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2145a5eeccaSmarks 			(void) printf("group:%s:%s\t\t",
215afe1f701Smarks 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
2165a5eeccaSmarks 			aclent_perms(tp->a_perm & mask, perm);
2175a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
2185a5eeccaSmarks 			break;
2195a5eeccaSmarks 		case GROUP_OBJ:
2205a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2215a5eeccaSmarks 			(void) printf("group::%s\t\t", perm);
2225a5eeccaSmarks 			aclent_perms(tp->a_perm & mask, perm);
2235a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
2245a5eeccaSmarks 			break;
2255a5eeccaSmarks 		case CLASS_OBJ:
2265a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2275a5eeccaSmarks 			(void) printf("mask:%s\n", perm);
2285a5eeccaSmarks 			break;
2295a5eeccaSmarks 		case OTHER_OBJ:
2305a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2315a5eeccaSmarks 			(void) printf("other:%s\n", perm);
2325a5eeccaSmarks 			break;
2335a5eeccaSmarks 		case DEF_USER:
2345a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2355a5eeccaSmarks 			(void) printf("default:user:%s:%s\n",
236afe1f701Smarks 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
2375a5eeccaSmarks 			break;
2385a5eeccaSmarks 		case DEF_USER_OBJ:
2395a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2405a5eeccaSmarks 			(void) printf("default:user::%s\n", perm);
2415a5eeccaSmarks 			break;
2425a5eeccaSmarks 		case DEF_GROUP:
2435a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2445a5eeccaSmarks 			(void) printf("default:group:%s:%s\n",
245afe1f701Smarks 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
2465a5eeccaSmarks 			break;
2475a5eeccaSmarks 		case DEF_GROUP_OBJ:
2485a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2495a5eeccaSmarks 			(void) printf("default:group::%s\n", perm);
2505a5eeccaSmarks 			break;
2515a5eeccaSmarks 		case DEF_CLASS_OBJ:
2525a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2535a5eeccaSmarks 			(void) printf("default:mask:%s\n", perm);
2545a5eeccaSmarks 			break;
2555a5eeccaSmarks 		case DEF_OTHER_OBJ:
2565a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2575a5eeccaSmarks 			(void) printf("default:other:%s\n", perm);
2585a5eeccaSmarks 			break;
2595a5eeccaSmarks 		default:
2605a5eeccaSmarks 			(void) fprintf(stderr,
2615b233e2dSmarks 			    dgettext(TEXT_DOMAIN, "unrecognized entry\n"));
2625a5eeccaSmarks 			break;
2635a5eeccaSmarks 		}
2645a5eeccaSmarks 	}
2655a5eeccaSmarks }
2665a5eeccaSmarks 
2675a5eeccaSmarks static void
2685a5eeccaSmarks split_line(char *str, int cols)
2695a5eeccaSmarks {
2705a5eeccaSmarks 	char *ptr;
2715a5eeccaSmarks 	int len;
2725a5eeccaSmarks 	int i;
2735a5eeccaSmarks 	int last_split;
2745a5eeccaSmarks 	char *pad = "";
2755a5eeccaSmarks 	int pad_len;
2765a5eeccaSmarks 
2775a5eeccaSmarks 	len = strlen(str);
2785a5eeccaSmarks 	ptr = str;
2795a5eeccaSmarks 	pad_len = 0;
2805a5eeccaSmarks 
2815a5eeccaSmarks 	ptr = str;
2825a5eeccaSmarks 	last_split = 0;
2835a5eeccaSmarks 	for (i = 0; i != len; i++) {
2845a5eeccaSmarks 		if ((i + pad_len + 4) >= cols) {
2855a5eeccaSmarks 			(void) printf("%s%.*s\n", pad, last_split, ptr);
2865a5eeccaSmarks 			ptr = &ptr[last_split];
2875a5eeccaSmarks 			len = strlen(ptr);
2885a5eeccaSmarks 			i = 0;
2895a5eeccaSmarks 			pad_len = 4;
2905a5eeccaSmarks 			pad = "         ";
2915a5eeccaSmarks 		} else {
2925a5eeccaSmarks 			if (ptr[i] == '/' || ptr[i] == ':') {
2935a5eeccaSmarks 				last_split = i;
2945a5eeccaSmarks 			}
2955a5eeccaSmarks 		}
2965a5eeccaSmarks 	}
2975a5eeccaSmarks 	if (i == len) {
2985a5eeccaSmarks 		(void) printf("%s%s\n", pad, ptr);
2995a5eeccaSmarks 	}
3005a5eeccaSmarks }
3015a5eeccaSmarks 
302*b249c65cSmarks /*
303*b249c65cSmarks  * compute entry type string, such as user:joe, group:staff,...
304*b249c65cSmarks  */
305*b249c65cSmarks static int
306*b249c65cSmarks aclent_type_txt(dynaclstr_t *dstr, aclent_t *aclp, int flags)
3075a5eeccaSmarks {
308afe1f701Smarks 	char idp[ID_STR_MAX];
309*b249c65cSmarks 	int error;
3105a5eeccaSmarks 
311*b249c65cSmarks 	switch (aclp->a_type) {
312*b249c65cSmarks 	case DEF_USER_OBJ:
313*b249c65cSmarks 	case USER_OBJ:
314*b249c65cSmarks 		if (aclp->a_type == USER_OBJ)
315*b249c65cSmarks 			error = str_append(dstr, "user::");
316*b249c65cSmarks 		else
317*b249c65cSmarks 			error = str_append(dstr, "defaultuser::");
318*b249c65cSmarks 		break;
319*b249c65cSmarks 
320*b249c65cSmarks 	case DEF_USER:
321*b249c65cSmarks 	case USER:
322*b249c65cSmarks 		if (aclp->a_type == USER)
323*b249c65cSmarks 			error = str_append(dstr, "user:");
324*b249c65cSmarks 		else
325*b249c65cSmarks 			error = str_append(dstr, "defaultuser:");
326*b249c65cSmarks 		if (error)
327*b249c65cSmarks 			break;
328*b249c65cSmarks 		error = str_append(dstr, pruname(aclp->a_id, idp,
329*b249c65cSmarks 		    sizeof (idp), flags & ACL_NORESOLVE));
330*b249c65cSmarks 		if (error == 0)
331*b249c65cSmarks 			error = str_append(dstr, ":");
332*b249c65cSmarks 		break;
333*b249c65cSmarks 
334*b249c65cSmarks 	case DEF_GROUP_OBJ:
335*b249c65cSmarks 	case GROUP_OBJ:
336*b249c65cSmarks 		if (aclp->a_type == GROUP_OBJ)
337*b249c65cSmarks 			error = str_append(dstr, "group::");
338*b249c65cSmarks 		else
339*b249c65cSmarks 			error = str_append(dstr, "defaultgroup::");
340*b249c65cSmarks 		break;
341*b249c65cSmarks 
342*b249c65cSmarks 	case DEF_GROUP:
343*b249c65cSmarks 	case GROUP:
344*b249c65cSmarks 		if (aclp->a_type == GROUP)
345*b249c65cSmarks 			error = str_append(dstr, "group:");
346*b249c65cSmarks 		else
347*b249c65cSmarks 			error = str_append(dstr, "defaultgroup:");
348*b249c65cSmarks 		if (error)
349*b249c65cSmarks 			break;
350*b249c65cSmarks 		error = str_append(dstr, prgname(aclp->a_id, idp,
351*b249c65cSmarks 		    sizeof (idp), flags & ACL_NORESOLVE));
352*b249c65cSmarks 		if (error == 0)
353*b249c65cSmarks 			error = str_append(dstr, ":");
354*b249c65cSmarks 		break;
355*b249c65cSmarks 
356*b249c65cSmarks 	case DEF_CLASS_OBJ:
357*b249c65cSmarks 	case CLASS_OBJ:
358*b249c65cSmarks 		if (aclp->a_type == CLASS_OBJ)
359*b249c65cSmarks 			error = str_append(dstr, "mask:");
360*b249c65cSmarks 		else
361*b249c65cSmarks 			error = str_append(dstr, "defaultmask:");
362*b249c65cSmarks 		break;
363*b249c65cSmarks 
364*b249c65cSmarks 	case DEF_OTHER_OBJ:
365*b249c65cSmarks 	case OTHER_OBJ:
366*b249c65cSmarks 		if (aclp->a_type == OTHER_OBJ)
367*b249c65cSmarks 			error = str_append(dstr, "other:");
368*b249c65cSmarks 		else
369*b249c65cSmarks 			error = str_append(dstr, "defaultother:");
370*b249c65cSmarks 		break;
371*b249c65cSmarks 
372*b249c65cSmarks 	default:
373*b249c65cSmarks 		error = 1;
374*b249c65cSmarks 		break;
375*b249c65cSmarks 	}
376*b249c65cSmarks 
377*b249c65cSmarks 	return (error);
378*b249c65cSmarks }
379*b249c65cSmarks 
380*b249c65cSmarks /*
381*b249c65cSmarks  * compute entry type string such as, owner@:, user:joe, group:staff,...
382*b249c65cSmarks  */
383*b249c65cSmarks static int
384*b249c65cSmarks ace_type_txt(dynaclstr_t *dynstr, ace_t *acep, int flags)
385*b249c65cSmarks {
386*b249c65cSmarks 	char idp[ID_STR_MAX];
387*b249c65cSmarks 	int error;
388*b249c65cSmarks 	char *sidp = NULL;
3895a5eeccaSmarks 
3905a5eeccaSmarks 	switch (acep->a_flags & ACE_TYPE_FLAGS) {
3915a5eeccaSmarks 	case ACE_OWNER:
392*b249c65cSmarks 		error = str_append(dynstr, OWNERAT_TXT);
3935a5eeccaSmarks 		break;
3945a5eeccaSmarks 
3955a5eeccaSmarks 	case ACE_GROUP|ACE_IDENTIFIER_GROUP:
396*b249c65cSmarks 		error = str_append(dynstr, GROUPAT_TXT);
3975a5eeccaSmarks 		break;
3985a5eeccaSmarks 
3995a5eeccaSmarks 	case ACE_IDENTIFIER_GROUP:
400*b249c65cSmarks 		if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) {
401*b249c65cSmarks 			if (error = str_append(dynstr,
402*b249c65cSmarks 			    GROUPSID_TXT))
403*b249c65cSmarks 				break;
404*b249c65cSmarks 			error = str_append(dynstr, prsidname(acep->a_who,
405*b249c65cSmarks 			    B_FALSE, &sidp, flags & ACL_NORESOLVE));
406*b249c65cSmarks 		} else {
407*b249c65cSmarks 			if (error = str_append(dynstr, GROUP_TXT))
408*b249c65cSmarks 				break;
409*b249c65cSmarks 			error = str_append(dynstr, prgname(acep->a_who, idp,
410afe1f701Smarks 			    sizeof (idp), flags & ACL_NORESOLVE));
411*b249c65cSmarks 		}
412*b249c65cSmarks 		if (error == 0)
413*b249c65cSmarks 			error = str_append(dynstr, ":");
4145a5eeccaSmarks 		break;
4155a5eeccaSmarks 
4165a5eeccaSmarks 	case ACE_EVERYONE:
417*b249c65cSmarks 		error = str_append(dynstr, EVERYONEAT_TXT);
4185a5eeccaSmarks 		break;
4195a5eeccaSmarks 
4205a5eeccaSmarks 	case 0:
421*b249c65cSmarks 		if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) {
422*b249c65cSmarks 			if (error = str_append(dynstr, USERSID_TXT))
423*b249c65cSmarks 				break;
424*b249c65cSmarks 			error = str_append(dynstr, prsidname(acep->a_who,
425*b249c65cSmarks 			    B_TRUE, &sidp, flags & ACL_NORESOLVE));
426*b249c65cSmarks 		} else {
427*b249c65cSmarks 			if (error = str_append(dynstr, USER_TXT))
428*b249c65cSmarks 				break;
429*b249c65cSmarks 			error = str_append(dynstr, pruname(acep->a_who, idp,
430afe1f701Smarks 			    sizeof (idp), flags & ACL_NORESOLVE));
431*b249c65cSmarks 		}
432*b249c65cSmarks 		if (error == 0)
433*b249c65cSmarks 			error = str_append(dynstr, ":");
434*b249c65cSmarks 		break;
435*b249c65cSmarks 	default:
436*b249c65cSmarks 		error = 0;
4375a5eeccaSmarks 		break;
4385a5eeccaSmarks 	}
4395a5eeccaSmarks 
440*b249c65cSmarks 	if (sidp)
441*b249c65cSmarks 		free(sidp);
442*b249c65cSmarks 	return (error);
4435a5eeccaSmarks }
4445a5eeccaSmarks 
445*b249c65cSmarks /*
446*b249c65cSmarks  * compute string of permissions, such as read_data/write_data or
447*b249c65cSmarks  * rwxp,...
448*b249c65cSmarks  * The format depends on the flags field which indicates whether the compact
449*b249c65cSmarks  * or verbose format should be used.
450*b249c65cSmarks  */
451*b249c65cSmarks static int
452*b249c65cSmarks ace_perm_txt(dynaclstr_t *dstr, uint32_t mask,
4535a5eeccaSmarks     uint32_t iflags, int isdir, int flags)
4545a5eeccaSmarks {
455*b249c65cSmarks 	int error = 0;
4565a5eeccaSmarks 
4575a5eeccaSmarks 	if (flags & ACL_COMPACT_FMT) {
458*b249c65cSmarks 		char buf[16];
4595a5eeccaSmarks 
4605a5eeccaSmarks 		if (mask & ACE_READ_DATA)
4615a5eeccaSmarks 			buf[0] = 'r';
4625a5eeccaSmarks 		else
4635a5eeccaSmarks 			buf[0] = '-';
4645a5eeccaSmarks 		if (mask & ACE_WRITE_DATA)
4655a5eeccaSmarks 			buf[1] = 'w';
4665a5eeccaSmarks 		else
4675a5eeccaSmarks 			buf[1] = '-';
4685a5eeccaSmarks 		if (mask & ACE_EXECUTE)
4695a5eeccaSmarks 			buf[2] = 'x';
4705a5eeccaSmarks 		else
4715a5eeccaSmarks 			buf[2] = '-';
4725a5eeccaSmarks 		if (mask & ACE_APPEND_DATA)
4735a5eeccaSmarks 			buf[3] = 'p';
4745a5eeccaSmarks 		else
4755a5eeccaSmarks 			buf[3] = '-';
4765a5eeccaSmarks 		if (mask & ACE_DELETE)
4775a5eeccaSmarks 			buf[4] = 'd';
4785a5eeccaSmarks 		else
4795a5eeccaSmarks 			buf[4] = '-';
4805a5eeccaSmarks 		if (mask & ACE_DELETE_CHILD)
4815a5eeccaSmarks 			buf[5] = 'D';
4825a5eeccaSmarks 		else
4835a5eeccaSmarks 			buf[5] = '-';
4845a5eeccaSmarks 		if (mask & ACE_READ_ATTRIBUTES)
4855a5eeccaSmarks 			buf[6] = 'a';
4865a5eeccaSmarks 		else
4875a5eeccaSmarks 			buf[6] = '-';
4885a5eeccaSmarks 		if (mask & ACE_WRITE_ATTRIBUTES)
4895a5eeccaSmarks 			buf[7] = 'A';
4905a5eeccaSmarks 		else
4915a5eeccaSmarks 			buf[7] = '-';
4925a5eeccaSmarks 		if (mask & ACE_READ_NAMED_ATTRS)
4935a5eeccaSmarks 			buf[8] = 'R';
4945a5eeccaSmarks 		else
4955a5eeccaSmarks 			buf[8] = '-';
4965a5eeccaSmarks 		if (mask & ACE_WRITE_NAMED_ATTRS)
4975a5eeccaSmarks 			buf[9] = 'W';
4985a5eeccaSmarks 		else
4995a5eeccaSmarks 			buf[9] = '-';
5005a5eeccaSmarks 		if (mask & ACE_READ_ACL)
5015a5eeccaSmarks 			buf[10] = 'c';
5025a5eeccaSmarks 		else
5035a5eeccaSmarks 			buf[10] = '-';
5045a5eeccaSmarks 		if (mask & ACE_WRITE_ACL)
5055a5eeccaSmarks 			buf[11] = 'C';
5065a5eeccaSmarks 		else
5075a5eeccaSmarks 			buf[11] = '-';
5085a5eeccaSmarks 		if (mask & ACE_WRITE_OWNER)
5095a5eeccaSmarks 			buf[12] = 'o';
5105a5eeccaSmarks 		else
5115a5eeccaSmarks 			buf[12] = '-';
5125a5eeccaSmarks 		if (mask & ACE_SYNCHRONIZE)
5135a5eeccaSmarks 			buf[13] = 's';
5145a5eeccaSmarks 		else
5155a5eeccaSmarks 			buf[13] = '-';
516*b249c65cSmarks 		buf[14] = ':';
517*b249c65cSmarks 		buf[15] = '\0';
518*b249c65cSmarks 		error = str_append(dstr, buf);
5195a5eeccaSmarks 	} else {
5205a5eeccaSmarks 		/*
5215a5eeccaSmarks 		 * If ACE is a directory, but inheritance indicates its
5225a5eeccaSmarks 		 * for a file then print permissions for file rather than
5235a5eeccaSmarks 		 * dir.
5245a5eeccaSmarks 		 */
5255a5eeccaSmarks 		if (isdir) {
5265a5eeccaSmarks 			if (mask & ACE_LIST_DIRECTORY) {
5275a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
528*b249c65cSmarks 					error = str_append(dstr,
529*b249c65cSmarks 					    READ_DATA_TXT);
5305a5eeccaSmarks 				} else {
531*b249c65cSmarks 					error =
532*b249c65cSmarks 					    str_append(dstr, READ_DIR_TXT);
5335a5eeccaSmarks 				}
5345a5eeccaSmarks 			}
535*b249c65cSmarks 			if (error == 0 && (mask & ACE_ADD_FILE)) {
5365a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
537*b249c65cSmarks 					error =
538*b249c65cSmarks 					    str_append(dstr, WRITE_DATA_TXT);
5395a5eeccaSmarks 				} else {
540*b249c65cSmarks 					error =
541*b249c65cSmarks 					    str_append(dstr, ADD_FILE_TXT);
5425a5eeccaSmarks 				}
5435a5eeccaSmarks 			}
544*b249c65cSmarks 			if (error == 0 && (mask & ACE_ADD_SUBDIRECTORY)) {
5455a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
546*b249c65cSmarks 					error = str_append(dstr,
547*b249c65cSmarks 					    APPEND_DATA_TXT);
5485a5eeccaSmarks 				} else {
549*b249c65cSmarks 					error = str_append(dstr,
550*b249c65cSmarks 					    ADD_DIR_TXT);
5515a5eeccaSmarks 				}
5525a5eeccaSmarks 			}
5535a5eeccaSmarks 		} else {
5545a5eeccaSmarks 			if (mask & ACE_READ_DATA) {
555*b249c65cSmarks 				error = str_append(dstr, READ_DATA_TXT);
5565a5eeccaSmarks 			}
557*b249c65cSmarks 			if (error == 0 && (mask & ACE_WRITE_DATA)) {
558*b249c65cSmarks 				error = str_append(dstr, WRITE_DATA_TXT);
5595a5eeccaSmarks 			}
560*b249c65cSmarks 			if (error == 0 && (mask & ACE_APPEND_DATA)) {
561*b249c65cSmarks 				error = str_append(dstr, APPEND_DATA_TXT);
5625a5eeccaSmarks 			}
5635a5eeccaSmarks 		}
564*b249c65cSmarks 		if (error == 0 && (mask & ACE_READ_NAMED_ATTRS)) {
565*b249c65cSmarks 			error = str_append(dstr, READ_XATTR_TXT);
5665a5eeccaSmarks 		}
567*b249c65cSmarks 		if (error == 0 && (mask & ACE_WRITE_NAMED_ATTRS)) {
568*b249c65cSmarks 			error = str_append(dstr, WRITE_XATTR_TXT);
5695a5eeccaSmarks 		}
570*b249c65cSmarks 		if (error == 0 && (mask & ACE_EXECUTE)) {
571*b249c65cSmarks 			error = str_append(dstr, EXECUTE_TXT);
5725a5eeccaSmarks 		}
573*b249c65cSmarks 		if (error == 0 && (mask & ACE_DELETE_CHILD)) {
574*b249c65cSmarks 			error = str_append(dstr, DELETE_CHILD_TXT);
5755a5eeccaSmarks 		}
576*b249c65cSmarks 		if (error == 0 && (mask & ACE_READ_ATTRIBUTES)) {
577*b249c65cSmarks 			error = str_append(dstr, READ_ATTRIBUTES_TXT);
5785a5eeccaSmarks 		}
579*b249c65cSmarks 		if (error == 0 && (mask & ACE_WRITE_ATTRIBUTES)) {
580*b249c65cSmarks 			error = str_append(dstr, WRITE_ATTRIBUTES_TXT);
5815a5eeccaSmarks 		}
582*b249c65cSmarks 		if (error == 0 && (mask & ACE_DELETE)) {
583*b249c65cSmarks 			error = str_append(dstr, DELETE_TXT);
5845a5eeccaSmarks 		}
585*b249c65cSmarks 		if (error == 0 && (mask & ACE_READ_ACL)) {
586*b249c65cSmarks 			error = str_append(dstr, READ_ACL_TXT);
5875a5eeccaSmarks 		}
588*b249c65cSmarks 		if (error == 0 && (mask & ACE_WRITE_ACL)) {
589*b249c65cSmarks 			error = str_append(dstr, WRITE_ACL_TXT);
5905a5eeccaSmarks 		}
591*b249c65cSmarks 		if (error == 0 && (mask & ACE_WRITE_OWNER)) {
592*b249c65cSmarks 			error = str_append(dstr, WRITE_OWNER_TXT);
5935a5eeccaSmarks 		}
594*b249c65cSmarks 		if (error == 0 && (mask & ACE_SYNCHRONIZE)) {
595*b249c65cSmarks 			error = str_append(dstr, SYNCHRONIZE_TXT);
596*b249c65cSmarks 		}
597*b249c65cSmarks 		if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') {
598*b249c65cSmarks 			dstr->d_aclexport[--dstr->d_pos] = '\0';
599*b249c65cSmarks 		}
600*b249c65cSmarks 		if (error == 0)
601*b249c65cSmarks 			error = str_append(dstr, ":");
602*b249c65cSmarks 	}
603*b249c65cSmarks 	return (error);
6045a5eeccaSmarks }
6055a5eeccaSmarks 
606*b249c65cSmarks /*
607*b249c65cSmarks  * compute string of access type, such as allow, deny, ...
608*b249c65cSmarks  */
609*b249c65cSmarks static int
610*b249c65cSmarks ace_access_txt(dynaclstr_t *dstr, int type)
6115a5eeccaSmarks {
612*b249c65cSmarks 	int error;
6135a5eeccaSmarks 
614*b249c65cSmarks 	if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
615*b249c65cSmarks 		error = str_append(dstr, ALLOW_TXT);
616*b249c65cSmarks 	else if (type == ACE_ACCESS_DENIED_ACE_TYPE)
617*b249c65cSmarks 		error = str_append(dstr, DENY_TXT);
618*b249c65cSmarks 	else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE)
619*b249c65cSmarks 		error = str_append(dstr, AUDIT_TXT);
620*b249c65cSmarks 	else if (type == ACE_SYSTEM_ALARM_ACE_TYPE)
621*b249c65cSmarks 		error = str_append(dstr, ALARM_TXT);
622*b249c65cSmarks 	else
623*b249c65cSmarks 		error = str_append(dstr, UNKNOWN_TXT);
6245a5eeccaSmarks 
625*b249c65cSmarks 	return (error);
6265a5eeccaSmarks }
6275a5eeccaSmarks 
628*b249c65cSmarks static int
629*b249c65cSmarks ace_inherit_txt(dynaclstr_t *dstr, uint32_t iflags, int flags)
6305a5eeccaSmarks {
631*b249c65cSmarks 	int error = 0;
6325a5eeccaSmarks 
6335a5eeccaSmarks 	if (flags & ACL_COMPACT_FMT) {
634*b249c65cSmarks 		char buf[9];
635*b249c65cSmarks 
6365a5eeccaSmarks 		if (iflags & ACE_FILE_INHERIT_ACE)
6375a5eeccaSmarks 			buf[0] = 'f';
6385a5eeccaSmarks 		else
6395a5eeccaSmarks 			buf[0] = '-';
6405a5eeccaSmarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE)
6415a5eeccaSmarks 			buf[1] = 'd';
6425a5eeccaSmarks 		else
6435a5eeccaSmarks 			buf[1] = '-';
6445a5eeccaSmarks 		if (iflags & ACE_INHERIT_ONLY_ACE)
6455a5eeccaSmarks 			buf[2] = 'i';
6465a5eeccaSmarks 		else
6475a5eeccaSmarks 			buf[2] = '-';
6485a5eeccaSmarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)
6495a5eeccaSmarks 			buf[3] = 'n';
6505a5eeccaSmarks 		else
6515a5eeccaSmarks 			buf[3] = '-';
6525a5eeccaSmarks 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
6535a5eeccaSmarks 			buf[4] = 'S';
6545a5eeccaSmarks 		else
6555a5eeccaSmarks 			buf[4] = '-';
6565a5eeccaSmarks 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG)
6575a5eeccaSmarks 			buf[5] = 'F';
6585a5eeccaSmarks 		else
6595a5eeccaSmarks 			buf[5] = '-';
660da6c28aaSamw 		if (iflags & ACE_INHERITED_ACE)
661da6c28aaSamw 			buf[6] = 'I';
662da6c28aaSamw 		else
663da6c28aaSamw 			buf[6] = '-';
664*b249c65cSmarks 		buf[7] = ':';
665*b249c65cSmarks 		buf[8] = '\0';
666*b249c65cSmarks 		error = str_append(dstr, buf);
6675a5eeccaSmarks 	} else {
6685a5eeccaSmarks 		if (iflags & ACE_FILE_INHERIT_ACE) {
669*b249c65cSmarks 			error = str_append(dstr, FILE_INHERIT_TXT);
6705a5eeccaSmarks 		}
671*b249c65cSmarks 		if (error == 0 && (iflags & ACE_DIRECTORY_INHERIT_ACE)) {
672*b249c65cSmarks 			error = str_append(dstr, DIR_INHERIT_TXT);
6735a5eeccaSmarks 		}
674*b249c65cSmarks 		if (error == 0 && (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) {
675*b249c65cSmarks 			error = str_append(dstr, NO_PROPAGATE_TXT);
6765a5eeccaSmarks 		}
677*b249c65cSmarks 		if (error == 0 && (iflags & ACE_INHERIT_ONLY_ACE)) {
678*b249c65cSmarks 			error = str_append(dstr, INHERIT_ONLY_TXT);
6795a5eeccaSmarks 		}
680*b249c65cSmarks 		if (error == 0 && (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)) {
681*b249c65cSmarks 			error = str_append(dstr, SUCCESSFUL_ACCESS_TXT);
682da6c28aaSamw 		}
683*b249c65cSmarks 		if (error == 0 && (iflags & ACE_FAILED_ACCESS_ACE_FLAG)) {
684*b249c65cSmarks 			error = str_append(dstr, FAILED_ACCESS_TXT);
685da6c28aaSamw 		}
686*b249c65cSmarks 		if (error == 0 && (iflags & ACE_INHERITED_ACE)) {
687*b249c65cSmarks 			error = str_append(dstr, INHERITED_ACE_TXT);
688*b249c65cSmarks 		}
689*b249c65cSmarks 		if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') {
690*b249c65cSmarks 			dstr->d_aclexport[--dstr->d_pos] = '\0';
691*b249c65cSmarks 			error = str_append(dstr, ":");
692*b249c65cSmarks 		}
693da6c28aaSamw 	}
6945a5eeccaSmarks 
695*b249c65cSmarks 	return (error);
696fa9e4066Sahrens }
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate /*
6997c478bd9Sstevel@tonic-gate  * Convert internal acl representation to external representation.
7007c478bd9Sstevel@tonic-gate  *
7017c478bd9Sstevel@tonic-gate  * The length of a non-owning user name or non-owning group name ie entries
7027c478bd9Sstevel@tonic-gate  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
7037c478bd9Sstevel@tonic-gate  * thus check the length of these entries, and if greater than LOGNAME_MAX,
7047c478bd9Sstevel@tonic-gate  * we realloc() via increase_length().
7057c478bd9Sstevel@tonic-gate  *
7067c478bd9Sstevel@tonic-gate  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
7077c478bd9Sstevel@tonic-gate  * adhered to.
7087c478bd9Sstevel@tonic-gate  */
7095a5eeccaSmarks 
7105a5eeccaSmarks /*
7115a5eeccaSmarks  * acltotext() converts each ACL entry to look like this:
7125a5eeccaSmarks  *
7135a5eeccaSmarks  *    entry_type:uid^gid^name:perms[:id]
7145a5eeccaSmarks  *
7155a5eeccaSmarks  * The maximum length of entry_type is 14 ("defaultgroup::" and
7165a5eeccaSmarks  * "defaultother::") hence ENTRYTYPELEN is set to 14.
7175a5eeccaSmarks  *
7185a5eeccaSmarks  * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
7195a5eeccaSmarks  * however the ID could be a number so we therefore use ID_STR_MAX
7205a5eeccaSmarks  *
7215a5eeccaSmarks  * The length of a perms entry is 4 to allow for the comma appended to each
7225a5eeccaSmarks  * to each acl entry.  Hence PERMS is set to 4.
7235a5eeccaSmarks  */
7245a5eeccaSmarks 
7255a5eeccaSmarks #define	ENTRYTYPELEN	14
7265a5eeccaSmarks #define	PERMS		4
7275a5eeccaSmarks #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
7285a5eeccaSmarks 
7297c478bd9Sstevel@tonic-gate char *
7305a5eeccaSmarks aclent_acltotext(aclent_t  *aclp, int aclcnt, int flags)
7317c478bd9Sstevel@tonic-gate {
732*b249c65cSmarks 	dynaclstr_t 	*dstr;
7337c478bd9Sstevel@tonic-gate 	char		*aclexport;
734*b249c65cSmarks 	int		i;
735*b249c65cSmarks 	int 		error = 0;
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	if (aclp == NULL)
7387c478bd9Sstevel@tonic-gate 		return (NULL);
739*b249c65cSmarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
7407c478bd9Sstevel@tonic-gate 		return (NULL);
741*b249c65cSmarks 	dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE;
742*b249c65cSmarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
7437c478bd9Sstevel@tonic-gate 		free(dstr);
7447c478bd9Sstevel@tonic-gate 		return (NULL);
7457c478bd9Sstevel@tonic-gate 	}
746*b249c65cSmarks 	*dstr->d_aclexport = '\0';
747*b249c65cSmarks 	dstr->d_pos = 0;
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	for (i = 0; i < aclcnt; i++, aclp++) {
750*b249c65cSmarks 		if (error = aclent_type_txt(dstr, aclp, flags))
7517c478bd9Sstevel@tonic-gate 			break;
752*b249c65cSmarks 		if (error = aclent_perm_txt(dstr, aclp->a_perm))
7537c478bd9Sstevel@tonic-gate 			break;
7545a5eeccaSmarks 
7555a5eeccaSmarks 		if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) ||
7565a5eeccaSmarks 		    (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) ||
7575a5eeccaSmarks 		    (aclp->a_type == DEF_GROUP))) {
758*b249c65cSmarks 			char id[ID_STR_MAX], *idstr;
759*b249c65cSmarks 
760*b249c65cSmarks 			if (error = str_append(dstr, ":"))
761*b249c65cSmarks 				break;
7625a5eeccaSmarks 			id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */
7635a5eeccaSmarks 			idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]);
764*b249c65cSmarks 			if (error = str_append(dstr, idstr))
765*b249c65cSmarks 				break;
7665a5eeccaSmarks 		}
7677c478bd9Sstevel@tonic-gate 		if (i < aclcnt - 1)
768*b249c65cSmarks 			if (error = str_append(dstr, ","))
769*b249c65cSmarks 				break;
7707c478bd9Sstevel@tonic-gate 	}
771*b249c65cSmarks 	if (error) {
772*b249c65cSmarks 		if (dstr->d_aclexport)
773*b249c65cSmarks 			free(dstr->d_aclexport);
774*b249c65cSmarks 	} else {
775*b249c65cSmarks 		aclexport = dstr->d_aclexport;
776*b249c65cSmarks 	}
7777c478bd9Sstevel@tonic-gate 	free(dstr);
7787c478bd9Sstevel@tonic-gate 	return (aclexport);
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate 
7815a5eeccaSmarks char *
7825a5eeccaSmarks acltotext(aclent_t *aclp, int aclcnt)
7837c478bd9Sstevel@tonic-gate {
7845a5eeccaSmarks 	return (aclent_acltotext(aclp, aclcnt, 0));
785fa9e4066Sahrens }
786fa9e4066Sahrens 
7877c478bd9Sstevel@tonic-gate 
788fa9e4066Sahrens aclent_t *
789fa9e4066Sahrens aclfromtext(char *aclstr, int *aclcnt)
790fa9e4066Sahrens {
791fa9e4066Sahrens 	acl_t *aclp;
792fa9e4066Sahrens 	aclent_t *aclentp;
793fa9e4066Sahrens 	int error;
794fa9e4066Sahrens 
7955a5eeccaSmarks 	error = acl_fromtext(aclstr, &aclp);
796fa9e4066Sahrens 	if (error)
797fa9e4066Sahrens 		return (NULL);
798fa9e4066Sahrens 
799fa9e4066Sahrens 	aclentp = aclp->acl_aclp;
800fa9e4066Sahrens 	aclp->acl_aclp = NULL;
801fa9e4066Sahrens 	*aclcnt = aclp->acl_cnt;
8025a5eeccaSmarks 
8035a5eeccaSmarks 	acl_free(aclp);
804fa9e4066Sahrens 	return (aclentp);
805fa9e4066Sahrens }
806fa9e4066Sahrens 
807fa9e4066Sahrens 
8087c478bd9Sstevel@tonic-gate /*
809*b249c65cSmarks  * returns a character position index of the start of the newly
810*b249c65cSmarks  * appended string.  Returns -1 if operation couldn't be completed.
8117c478bd9Sstevel@tonic-gate  */
8127c478bd9Sstevel@tonic-gate static int
813*b249c65cSmarks str_append(dynaclstr_t *dstr, char *newstr)
8147c478bd9Sstevel@tonic-gate {
815*b249c65cSmarks 	size_t len = strlen(newstr);
8167c478bd9Sstevel@tonic-gate 
817*b249c65cSmarks 	if ((len + dstr->d_pos) >= dstr->d_bufsize) {
818*b249c65cSmarks 		dstr->d_aclexport = realloc(dstr->d_aclexport,
819*b249c65cSmarks 		    dstr->d_bufsize + len + 1);
820*b249c65cSmarks 		if (dstr->d_aclexport == NULL)
8217c478bd9Sstevel@tonic-gate 			return (1);
822*b249c65cSmarks 		dstr->d_bufsize += len;
823*b249c65cSmarks 	}
824*b249c65cSmarks 	(void) strcat(&dstr->d_aclexport[dstr->d_pos], newstr);
825*b249c65cSmarks 	dstr->d_pos += len;
8267c478bd9Sstevel@tonic-gate 	return (0);
8277c478bd9Sstevel@tonic-gate }
828fa9e4066Sahrens 
829*b249c65cSmarks static int
830*b249c65cSmarks aclent_perm_txt(dynaclstr_t *dstr, o_mode_t perm)
831*b249c65cSmarks {
832*b249c65cSmarks 	char buf[4];
833*b249c65cSmarks 
834*b249c65cSmarks 	if (perm & S_IROTH)
835*b249c65cSmarks 		buf[0] = 'r';
836*b249c65cSmarks 	else
837*b249c65cSmarks 		buf[0] = '-';
838*b249c65cSmarks 	if (perm & S_IWOTH)
839*b249c65cSmarks 		buf[1] = 'w';
840*b249c65cSmarks 	else
841*b249c65cSmarks 		buf[1] = '-';
842*b249c65cSmarks 	if (perm & S_IXOTH)
843*b249c65cSmarks 		buf[2] = 'x';
844*b249c65cSmarks 	else
845*b249c65cSmarks 		buf[2] = '-';
846*b249c65cSmarks 	buf[3] = '\0';
847*b249c65cSmarks 	return (str_append(dstr, buf));
848*b249c65cSmarks }
849*b249c65cSmarks 
850fa9e4066Sahrens /*
8515a5eeccaSmarks  * ace_acltotext() convert each ace formatted acl to look like this:
852fa9e4066Sahrens  *
8535a5eeccaSmarks  * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
854fa9e4066Sahrens  *
855fa9e4066Sahrens  * The maximum length of entry_type is 5 ("group")
856fa9e4066Sahrens  *
8575a5eeccaSmarks  * The max length of a uid^gid^name entry (in theory) is 8,
8585a5eeccaSmarks  * however id could be a number so we therefore use ID_STR_MAX
859fa9e4066Sahrens  *
860fa9e4066Sahrens  * The length of a perms entry is 144 i.e read_data/write_data...
861fa9e4066Sahrens  * to each acl entry.
862fa9e4066Sahrens  *
863da6c28aaSamw  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access
864da6c28aaSamw  *         /failed_access
865fa9e4066Sahrens  *
866fa9e4066Sahrens  */
867fa9e4066Sahrens 
868fa9e4066Sahrens #define	ACE_ENTRYTYPLEN		6
869da6c28aaSamw #define	IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \
870da6c28aaSamw 	"successful_access/failed_access/inherited"
871da6c28aaSamw #define	IFLAGS_SIZE		(sizeof (IFLAGS_STR) - 1)
8725a5eeccaSmarks #define	ACCESS_TYPE_SIZE	7	/* if unknown */
873fa9e4066Sahrens #define	COLON_CNT		3
874fa9e4066Sahrens #define	PERMS_LEN		216
8755a5eeccaSmarks #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \
8765a5eeccaSmarks     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
877fa9e4066Sahrens 
878fa9e4066Sahrens static char *
8795a5eeccaSmarks ace_acltotext(acl_t *aceaclp, int flags)
880fa9e4066Sahrens {
881fa9e4066Sahrens 	ace_t		*aclp = aceaclp->acl_aclp;
882fa9e4066Sahrens 	int		aclcnt = aceaclp->acl_cnt;
8835a5eeccaSmarks 	int		i;
884*b249c65cSmarks 	int		error = 0;
885fa9e4066Sahrens 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
886*b249c65cSmarks 	dynaclstr_t 	*dstr;
887*b249c65cSmarks 	char		*aclexport;
888fa9e4066Sahrens 
889fa9e4066Sahrens 	if (aclp == NULL)
890fa9e4066Sahrens 		return (NULL);
891fa9e4066Sahrens 
892*b249c65cSmarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
893*b249c65cSmarks 		return (NULL);
894*b249c65cSmarks 	dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE;
895*b249c65cSmarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
896*b249c65cSmarks 		free(dstr);
897*b249c65cSmarks 		return (NULL);
898*b249c65cSmarks 	}
899*b249c65cSmarks 	*dstr->d_aclexport = '\0';
900*b249c65cSmarks 	dstr->d_pos = 0;
901*b249c65cSmarks 
902fa9e4066Sahrens 	for (i = 0; i < aclcnt; i++, aclp++) {
903fa9e4066Sahrens 
904*b249c65cSmarks 		if (error = ace_type_txt(dstr, aclp, flags))
905*b249c65cSmarks 			break;
906*b249c65cSmarks 		if (error = ace_perm_txt(dstr, aclp->a_access_mask,
907*b249c65cSmarks 		    aclp->a_flags, isdir, flags))
908*b249c65cSmarks 			break;
909*b249c65cSmarks 		if (error = ace_inherit_txt(dstr, aclp->a_flags, flags))
910*b249c65cSmarks 			break;
911*b249c65cSmarks 		if (error = ace_access_txt(dstr, aclp->a_type))
912*b249c65cSmarks 			break;
913fa9e4066Sahrens 
9145a5eeccaSmarks 		if ((flags & ACL_APPEND_ID) &&
9155a5eeccaSmarks 		    (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ||
9165a5eeccaSmarks 		    ((aclp->a_flags & ACE_TYPE_FLAGS) ==
9175a5eeccaSmarks 		    ACE_IDENTIFIER_GROUP))) {
918*b249c65cSmarks 			char id[ID_STR_MAX], *idstr;
919*b249c65cSmarks 
920*b249c65cSmarks 			if (error = str_append(dstr, ":"))
921*b249c65cSmarks 				break;
9225a5eeccaSmarks 			id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */
923*b249c65cSmarks 			idstr = lltostr((aclp->a_who > MAXUID &&
924*b249c65cSmarks 			    !(flags & ACL_NORESOLVE)) ? UID_NOBODY :
925*b249c65cSmarks 			    aclp->a_who, &id[ID_STR_MAX - 1]);
926*b249c65cSmarks 			if (error = str_append(dstr, idstr))
927*b249c65cSmarks 				break;
9285a5eeccaSmarks 		}
9295a5eeccaSmarks 		if (i < aclcnt - 1) {
930*b249c65cSmarks 			if (error = str_append(dstr, ","))
931*b249c65cSmarks 				break;
932fa9e4066Sahrens 		}
933fa9e4066Sahrens 	}
934*b249c65cSmarks 	if (error) {
935*b249c65cSmarks 		if (dstr->d_aclexport)
936*b249c65cSmarks 			free(dstr->d_aclexport);
937*b249c65cSmarks 	} else {
938*b249c65cSmarks 		aclexport = dstr->d_aclexport;
939*b249c65cSmarks 	}
940*b249c65cSmarks 	free(dstr);
941fa9e4066Sahrens 	return (aclexport);
942fa9e4066Sahrens }
943fa9e4066Sahrens 
9445a5eeccaSmarks char *
9455a5eeccaSmarks acl_totext(acl_t *aclp, int flags)
946fa9e4066Sahrens {
9475a5eeccaSmarks 	char *txtp;
948fa9e4066Sahrens 
949fa9e4066Sahrens 	if (aclp == NULL)
950fa9e4066Sahrens 		return (NULL);
951fa9e4066Sahrens 
952fa9e4066Sahrens 	switch (aclp->acl_type) {
953fa9e4066Sahrens 	case ACE_T:
9545a5eeccaSmarks 		txtp = ace_acltotext(aclp, flags);
9555a5eeccaSmarks 		break;
956fa9e4066Sahrens 	case ACLENT_T:
9575a5eeccaSmarks 		txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags);
9585a5eeccaSmarks 		break;
959fa9e4066Sahrens 	}
9605a5eeccaSmarks 
9615a5eeccaSmarks 	return (txtp);
962fa9e4066Sahrens }
963fa9e4066Sahrens 
964fa9e4066Sahrens int
965fa9e4066Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp)
966fa9e4066Sahrens {
9675a5eeccaSmarks 	int error;
9685a5eeccaSmarks 	char *buf;
9695a5eeccaSmarks 
9705a5eeccaSmarks 	buf = malloc(strlen(acltextp) + 2);
9715a5eeccaSmarks 	if (buf == NULL)
9725a5eeccaSmarks 		return (EACL_MEM_ERROR);
9735a5eeccaSmarks 	strcpy(buf, acltextp);
9745a5eeccaSmarks 	strcat(buf, "\n");
9755a5eeccaSmarks 	yybuf = buf;
9765a5eeccaSmarks 	yyreset();
9775a5eeccaSmarks 	error = yyparse();
9785a5eeccaSmarks 	free(buf);
9795a5eeccaSmarks 
9805a5eeccaSmarks 	if (yyacl) {
9815a5eeccaSmarks 		if (error == 0)
9825a5eeccaSmarks 			*ret_aclp = yyacl;
9835a5eeccaSmarks 		else {
9845a5eeccaSmarks 			acl_free(yyacl);
9855a5eeccaSmarks 		}
9865a5eeccaSmarks 		yyacl = NULL;
9875a5eeccaSmarks 	}
9885a5eeccaSmarks 	return (error);
9895a5eeccaSmarks }
9905a5eeccaSmarks 
9915a5eeccaSmarks int
9925a5eeccaSmarks acl_parse(const char *acltextp, acl_t **aclp)
9935a5eeccaSmarks {
994fa9e4066Sahrens 	int error;
995fa9e4066Sahrens 
9965a5eeccaSmarks 	yyinteractive = 1;
9975a5eeccaSmarks 	error = acl_fromtext(acltextp, aclp);
9985a5eeccaSmarks 	yyinteractive = 0;
999fa9e4066Sahrens 	return (error);
1000fa9e4066Sahrens }
10015a5eeccaSmarks 
10025a5eeccaSmarks static void
10035a5eeccaSmarks ace_compact_printacl(acl_t *aclp)
10045a5eeccaSmarks {
10055a5eeccaSmarks 	int cnt;
10065a5eeccaSmarks 	ace_t *acep;
1007*b249c65cSmarks 	dynaclstr_t *dstr;
1008*b249c65cSmarks 	int len;
10095a5eeccaSmarks 
1010*b249c65cSmarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
1011*b249c65cSmarks 		return;
1012*b249c65cSmarks 	dstr->d_bufsize = ACE_ENTRY_SIZE;
1013*b249c65cSmarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
1014*b249c65cSmarks 		free(dstr);
1015*b249c65cSmarks 		return;
1016*b249c65cSmarks 	}
1017*b249c65cSmarks 	*dstr->d_aclexport = '\0';
1018*b249c65cSmarks 
1019*b249c65cSmarks 	dstr->d_pos = 0;
10205a5eeccaSmarks 	for (cnt = 0, acep = aclp->acl_aclp;
10215a5eeccaSmarks 	    cnt != aclp->acl_cnt; cnt++, acep++) {
1022*b249c65cSmarks 		dstr->d_aclexport[0] = '\0';
1023*b249c65cSmarks 		dstr->d_pos = 0;
1024*b249c65cSmarks 
1025*b249c65cSmarks 		if (ace_type_txt(dstr, acep, 0))
1026*b249c65cSmarks 			break;
1027*b249c65cSmarks 		len = strlen(&dstr->d_aclexport[0]);
1028*b249c65cSmarks 		if (ace_perm_txt(dstr, acep->a_access_mask, acep->a_flags,
1029*b249c65cSmarks 		    aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT))
1030*b249c65cSmarks 			break;
1031*b249c65cSmarks 		if (ace_inherit_txt(dstr, acep->a_flags, ACL_COMPACT_FMT))
1032*b249c65cSmarks 			break;
1033*b249c65cSmarks 		if (ace_access_txt(dstr, acep->a_type) == -1)
1034*b249c65cSmarks 			break;
1035*b249c65cSmarks 		(void) printf("    %20.*s%s\n", len, dstr->d_aclexport,
1036*b249c65cSmarks 		    &dstr->d_aclexport[len]);
10375a5eeccaSmarks 	}
1038*b249c65cSmarks 
1039*b249c65cSmarks 	if (dstr->d_aclexport)
1040*b249c65cSmarks 		free(dstr->d_aclexport);
1041*b249c65cSmarks 	free(dstr);
10425a5eeccaSmarks }
10435a5eeccaSmarks 
10445a5eeccaSmarks static void
10455a5eeccaSmarks ace_printacl(acl_t *aclp, int cols, int compact)
10465a5eeccaSmarks {
10475a5eeccaSmarks 	int  slot = 0;
10485a5eeccaSmarks 	char *token;
10495a5eeccaSmarks 	char *acltext;
10505a5eeccaSmarks 
10515a5eeccaSmarks 	if (compact) {
10525a5eeccaSmarks 		ace_compact_printacl(aclp);
10535a5eeccaSmarks 		return;
10545a5eeccaSmarks 	}
10555a5eeccaSmarks 
10565a5eeccaSmarks 	acltext = acl_totext(aclp, 0);
10575a5eeccaSmarks 
10585a5eeccaSmarks 	if (acltext == NULL)
10595a5eeccaSmarks 		return;
10605a5eeccaSmarks 
10615a5eeccaSmarks 	token = strtok(acltext, ",");
10625a5eeccaSmarks 	if (token == NULL) {
10635a5eeccaSmarks 		free(acltext);
10645a5eeccaSmarks 		return;
10655a5eeccaSmarks 	}
10665a5eeccaSmarks 
10675a5eeccaSmarks 	do {
10685a5eeccaSmarks 		(void) printf("     %d:", slot++);
10695a5eeccaSmarks 		split_line(token, cols - 5);
10705a5eeccaSmarks 	} while (token = strtok(NULL, ","));
10715a5eeccaSmarks 	free(acltext);
10725a5eeccaSmarks }
10735a5eeccaSmarks 
10745a5eeccaSmarks /*
10755a5eeccaSmarks  * pretty print an ACL.
10765a5eeccaSmarks  * For aclent_t ACL's the format is
10775a5eeccaSmarks  * similar to the old format used by getfacl,
10785a5eeccaSmarks  * with the addition of adding a "slot" number
10795a5eeccaSmarks  * before each entry.
10805a5eeccaSmarks  *
10815a5eeccaSmarks  * for ace_t ACL's the cols variable will break up
10825a5eeccaSmarks  * the long lines into multiple lines and will also
10835a5eeccaSmarks  * print a "slot" number.
10845a5eeccaSmarks  */
10855a5eeccaSmarks void
10865a5eeccaSmarks acl_printacl(acl_t *aclp, int cols, int compact)
10875a5eeccaSmarks {
10885a5eeccaSmarks 
10895a5eeccaSmarks 	switch (aclp->acl_type) {
10905a5eeccaSmarks 	case ACLENT_T:
10915a5eeccaSmarks 		aclent_printacl(aclp);
10925a5eeccaSmarks 		break;
10935a5eeccaSmarks 	case ACE_T:
10945a5eeccaSmarks 		ace_printacl(aclp, cols, compact);
10955a5eeccaSmarks 		break;
10965a5eeccaSmarks 	}
10975a5eeccaSmarks }
10985a5eeccaSmarks 
10995a5eeccaSmarks typedef struct value_table {
11005a5eeccaSmarks 	char		p_letter; /* perm letter such as 'r' */
11015a5eeccaSmarks 	uint32_t	p_value; /* value for perm when pletter found */
11025a5eeccaSmarks } value_table_t;
11035a5eeccaSmarks 
11045a5eeccaSmarks /*
1105da6c28aaSamw  * The permission tables are laid out in positional order
11065a5eeccaSmarks  * a '-' character will indicate a permission at a given
11075a5eeccaSmarks  * position is not specified.  The '-' is not part of the
11085a5eeccaSmarks  * table, but will be checked for in the permission computation
11095a5eeccaSmarks  * routine.
11105a5eeccaSmarks  */
1111da6c28aaSamw value_table_t ace_perm_table[] = {
11125a5eeccaSmarks 	{ 'r', ACE_READ_DATA},
11135a5eeccaSmarks 	{ 'w', ACE_WRITE_DATA},
11145a5eeccaSmarks 	{ 'x', ACE_EXECUTE},
11155a5eeccaSmarks 	{ 'p', ACE_APPEND_DATA},
11165a5eeccaSmarks 	{ 'd', ACE_DELETE},
11175a5eeccaSmarks 	{ 'D', ACE_DELETE_CHILD},
11185a5eeccaSmarks 	{ 'a', ACE_READ_ATTRIBUTES},
11195a5eeccaSmarks 	{ 'A', ACE_WRITE_ATTRIBUTES},
11205a5eeccaSmarks 	{ 'R', ACE_READ_NAMED_ATTRS},
11215a5eeccaSmarks 	{ 'W', ACE_WRITE_NAMED_ATTRS},
11225a5eeccaSmarks 	{ 'c', ACE_READ_ACL},
11235a5eeccaSmarks 	{ 'C', ACE_WRITE_ACL},
11245a5eeccaSmarks 	{ 'o', ACE_WRITE_OWNER},
11255a5eeccaSmarks 	{ 's', ACE_SYNCHRONIZE}
11265a5eeccaSmarks };
11275a5eeccaSmarks 
1128da6c28aaSamw #define	ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t))
11295a5eeccaSmarks 
1130da6c28aaSamw value_table_t aclent_perm_table[] = {
11315a5eeccaSmarks 	{ 'r', S_IROTH},
11325a5eeccaSmarks 	{ 'w', S_IWOTH},
11335a5eeccaSmarks 	{ 'x', S_IXOTH}
11345a5eeccaSmarks };
11355a5eeccaSmarks 
1136da6c28aaSamw #define	ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t))
1137da6c28aaSamw 
1138da6c28aaSamw value_table_t inherit_table[] = {
11395a5eeccaSmarks 	{'f', ACE_FILE_INHERIT_ACE},
11405a5eeccaSmarks 	{'d', ACE_DIRECTORY_INHERIT_ACE},
11415a5eeccaSmarks 	{'i', ACE_INHERIT_ONLY_ACE},
11425a5eeccaSmarks 	{'n', ACE_NO_PROPAGATE_INHERIT_ACE},
11435a5eeccaSmarks 	{'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
1144da6c28aaSamw 	{'F', ACE_FAILED_ACCESS_ACE_FLAG},
1145da6c28aaSamw 	{'I', ACE_INHERITED_ACE}
11465a5eeccaSmarks };
11475a5eeccaSmarks 
1148da6c28aaSamw #define	IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t))
1149bf8b6031Smarks #define	IFLAG_COUNT_V1 6 /* Older version compatibility */
1150da6c28aaSamw 
11515a5eeccaSmarks /*
11525a5eeccaSmarks  * compute value from a permission table or inheritance table
11535a5eeccaSmarks  * based on string passed in.  If positional is set then
11545a5eeccaSmarks  * string must match order in permtab, otherwise any order
11555a5eeccaSmarks  * is allowed.
11565a5eeccaSmarks  */
11575a5eeccaSmarks int
11585a5eeccaSmarks compute_values(value_table_t *permtab, int count,
11595a5eeccaSmarks     char *permstr, int positional, uint32_t *mask)
11605a5eeccaSmarks {
11615a5eeccaSmarks 	uint32_t perm_val = 0;
11625a5eeccaSmarks 	char *pstr;
11635a5eeccaSmarks 	int i, found;
11645a5eeccaSmarks 
11655a5eeccaSmarks 	if (count < 0)
11665a5eeccaSmarks 		return (1);
11675a5eeccaSmarks 
11685a5eeccaSmarks 	if (positional) {
11695a5eeccaSmarks 		for (i = 0, pstr = permstr; i != count && pstr &&
11705a5eeccaSmarks 		    *pstr; i++, pstr++) {
11715a5eeccaSmarks 			if (*pstr == permtab[i].p_letter) {
11725a5eeccaSmarks 				perm_val |= permtab[i].p_value;
11735a5eeccaSmarks 			} else if (*pstr != '-') {
11745a5eeccaSmarks 				return (1);
11755a5eeccaSmarks 			}
11765a5eeccaSmarks 		}
11775a5eeccaSmarks 	} else {  /* random order single letters with no '-' */
11785a5eeccaSmarks 		for (pstr = permstr; pstr && *pstr; pstr++) {
11795a5eeccaSmarks 			for (found = 0, i = 0; i != count; i++) {
11805a5eeccaSmarks 				if (*pstr == permtab[i].p_letter) {
11815a5eeccaSmarks 					perm_val |= permtab[i].p_value;
11825a5eeccaSmarks 					found = 1;
11835a5eeccaSmarks 					break;
11845a5eeccaSmarks 				}
11855a5eeccaSmarks 			}
11865a5eeccaSmarks 			if (found == 0)
11875a5eeccaSmarks 				return (1);
11885a5eeccaSmarks 		}
11895a5eeccaSmarks 	}
11905a5eeccaSmarks 
11915a5eeccaSmarks 	*mask = perm_val;
11925a5eeccaSmarks 	return (0);
11935a5eeccaSmarks }
11945a5eeccaSmarks 
1195bf8b6031Smarks 
1196bf8b6031Smarks int
1197bf8b6031Smarks ace_inherit_helper(char *str, uint32_t *imask, int table_length)
1198bf8b6031Smarks {
1199bf8b6031Smarks 	int rc = 0;
1200bf8b6031Smarks 
1201bf8b6031Smarks 	if (strlen(str) == table_length) {
1202bf8b6031Smarks 		/*
1203bf8b6031Smarks 		 * If the string == table_length then first check to see it's
1204bf8b6031Smarks 		 * in positional format.  If that fails then see if it's in
1205bf8b6031Smarks 		 * non-positional format.
1206bf8b6031Smarks 		 */
1207bf8b6031Smarks 		if (compute_values(inherit_table, table_length, str,
1208bf8b6031Smarks 		    1, imask) && compute_values(inherit_table,
1209bf8b6031Smarks 		    table_length, str, 0, imask)) {
1210bf8b6031Smarks 			rc = 1;
1211bf8b6031Smarks 		}
1212bf8b6031Smarks 	} else {
1213bf8b6031Smarks 		rc = compute_values(inherit_table, table_length, str, 0, imask);
1214bf8b6031Smarks 	}
1215bf8b6031Smarks 
1216bf8b6031Smarks 	return (rc ? EACL_INHERIT_ERROR : 0);
1217bf8b6031Smarks }
1218bf8b6031Smarks 
12195a5eeccaSmarks /*
12205a5eeccaSmarks  * compute value for inheritance flags.
12215a5eeccaSmarks  */
12225a5eeccaSmarks int
12235a5eeccaSmarks compute_ace_inherit(char *str, uint32_t *imask)
12245a5eeccaSmarks {
1225bf8b6031Smarks 	int rc = 0;
12265a5eeccaSmarks 
1227bf8b6031Smarks 	rc = ace_inherit_helper(str, imask, IFLAG_COUNT);
12285a5eeccaSmarks 
1229bf8b6031Smarks 	if (rc && strlen(str) != IFLAG_COUNT) {
12305a5eeccaSmarks 
1231bf8b6031Smarks 		/* is it an old formatted inherit string? */
1232bf8b6031Smarks 		rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1);
1233bf8b6031Smarks 	}
12345a5eeccaSmarks 
1235bf8b6031Smarks 	return (rc);
12365a5eeccaSmarks }
12375a5eeccaSmarks 
12385a5eeccaSmarks 
12395a5eeccaSmarks /*
12405a5eeccaSmarks  * compute value for ACE permissions.
12415a5eeccaSmarks  */
12425a5eeccaSmarks int
12435a5eeccaSmarks compute_ace_perms(char *str, uint32_t *mask)
12445a5eeccaSmarks {
12455a5eeccaSmarks 	int positional = 0;
12465a5eeccaSmarks 	int error;
12475a5eeccaSmarks 
12485a5eeccaSmarks 	if (strlen(str) == ACE_PERM_COUNT)
12495a5eeccaSmarks 		positional = 1;
12505a5eeccaSmarks 
12515a5eeccaSmarks 	error = compute_values(ace_perm_table, ACE_PERM_COUNT,
12525a5eeccaSmarks 	    str, positional, mask);
12535a5eeccaSmarks 
12545a5eeccaSmarks 	if (error && positional) {
12555a5eeccaSmarks 		/*
12565a5eeccaSmarks 		 * If positional was set, then make sure permissions
12575a5eeccaSmarks 		 * aren't actually valid in non positional case where
12585a5eeccaSmarks 		 * all permissions are specified, just in random order.
12595a5eeccaSmarks 		 */
12605a5eeccaSmarks 		error = compute_values(ace_perm_table,
12615a5eeccaSmarks 		    ACE_PERM_COUNT, str, 0, mask);
12625a5eeccaSmarks 	}
12635a5eeccaSmarks 	if (error)
12645a5eeccaSmarks 		error = EACL_PERM_MASK_ERROR;
12655a5eeccaSmarks 
12665a5eeccaSmarks 	return (error);
12675a5eeccaSmarks }
12685a5eeccaSmarks 
12695a5eeccaSmarks 
12705a5eeccaSmarks 
12715a5eeccaSmarks /*
12725a5eeccaSmarks  * compute values for aclent permissions.
12735a5eeccaSmarks  */
12745a5eeccaSmarks int
12755a5eeccaSmarks compute_aclent_perms(char *str, o_mode_t *mask)
12765a5eeccaSmarks {
12775a5eeccaSmarks 	int error;
12785a5eeccaSmarks 	uint32_t pmask;
12795a5eeccaSmarks 
12805a5eeccaSmarks 	if (strlen(str) != ACLENT_PERM_COUNT)
12815a5eeccaSmarks 		return (EACL_PERM_MASK_ERROR);
12825a5eeccaSmarks 
12835a5eeccaSmarks 	*mask = 0;
12845a5eeccaSmarks 	error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT,
12855a5eeccaSmarks 	    str, 1, &pmask);
12865a5eeccaSmarks 	if (error == 0) {
12875a5eeccaSmarks 		*mask = (o_mode_t)pmask;
12885a5eeccaSmarks 	} else
12895a5eeccaSmarks 		error = EACL_PERM_MASK_ERROR;
12905a5eeccaSmarks 	return (error);
12915a5eeccaSmarks }
12925a5eeccaSmarks 
12935a5eeccaSmarks /*
12945a5eeccaSmarks  * determine ACE permissions.
12955a5eeccaSmarks  */
12965a5eeccaSmarks int
12975a5eeccaSmarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask)
12985a5eeccaSmarks {
12995a5eeccaSmarks 	int error;
13005a5eeccaSmarks 
13015a5eeccaSmarks 	if (aclperm->perm_style == PERM_TYPE_EMPTY) {
13025a5eeccaSmarks 		*mask = 0;
13035a5eeccaSmarks 		return (0);
13045a5eeccaSmarks 	}
13055a5eeccaSmarks 
13065a5eeccaSmarks 	if (aclperm->perm_style == PERM_TYPE_ACE) {
13075a5eeccaSmarks 		*mask = aclperm->perm_val;
13085a5eeccaSmarks 		return (0);
13095a5eeccaSmarks 	}
13105a5eeccaSmarks 
13115a5eeccaSmarks 	error = compute_ace_perms(aclperm->perm_str, mask);
13125a5eeccaSmarks 	if (error) {
13135b233e2dSmarks 		acl_error(dgettext(TEXT_DOMAIN,
13145b233e2dSmarks 		    "Invalid permission(s) '%s' specified\n"),
13155a5eeccaSmarks 		    aclperm->perm_str);
13165a5eeccaSmarks 		return (EACL_PERM_MASK_ERROR);
13175a5eeccaSmarks 	}
13185a5eeccaSmarks 
13195a5eeccaSmarks 	return (0);
13205a5eeccaSmarks }
1321