xref: /titanic_53/usr/src/lib/libsec/common/acltext.c (revision 5a5eeccada4b11bc692e9a5015d5f4a4f188226c)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*5a5eeccaSmarks  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <grp.h>
317c478bd9Sstevel@tonic-gate #include <pwd.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <limits.h>
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
35fa9e4066Sahrens #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <sys/param.h>
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
38*5a5eeccaSmarks #include <sys/stat.h>
397c478bd9Sstevel@tonic-gate #include <sys/acl.h>
40fa9e4066Sahrens #include <aclutils.h>
41fa9e4066Sahrens 
42*5a5eeccaSmarks #define	ID_STR_MAX	20	/* digits in LONG_MAX */
43*5a5eeccaSmarks 
44*5a5eeccaSmarks #define	APPENDED_ID_MAX	ID_STR_MAX + 1		/* id + colon */
45*5a5eeccaSmarks /*
46*5a5eeccaSmarks  * yyinteractive controls whether yyparse should print out
47*5a5eeccaSmarks  * error messages to stderr, and whether or not id's should be
48*5a5eeccaSmarks  * allowed from acl_fromtext().
49*5a5eeccaSmarks  */
50*5a5eeccaSmarks int	yyinteractive;
51*5a5eeccaSmarks acl_t	*yyacl;
52*5a5eeccaSmarks char	*yybuf;
53fa9e4066Sahrens 
54fa9e4066Sahrens extern acl_t *acl_alloc(enum acl_type);
557c478bd9Sstevel@tonic-gate 
5611e32170Shm123892 
577c478bd9Sstevel@tonic-gate struct dynaclstr {
587c478bd9Sstevel@tonic-gate 	size_t bufsize;		/* current size of aclexport */
597c478bd9Sstevel@tonic-gate 	char *aclexport;
607c478bd9Sstevel@tonic-gate };
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate static char *strappend(char *, char *);
637c478bd9Sstevel@tonic-gate static char *convert_perm(char *, o_mode_t);
647c478bd9Sstevel@tonic-gate static int increase_length(struct dynaclstr *, size_t);
657c478bd9Sstevel@tonic-gate 
66*5a5eeccaSmarks static void
67*5a5eeccaSmarks aclent_perms(int perm, char *txt_perms)
68fa9e4066Sahrens {
69*5a5eeccaSmarks 	if (perm & S_IROTH)
70*5a5eeccaSmarks 		txt_perms[0] = 'r';
71*5a5eeccaSmarks 	else
72*5a5eeccaSmarks 		txt_perms[0] = '-';
73*5a5eeccaSmarks 	if (perm & S_IWOTH)
74*5a5eeccaSmarks 		txt_perms[1] = 'w';
75*5a5eeccaSmarks 	else
76*5a5eeccaSmarks 		txt_perms[1] = '-';
77*5a5eeccaSmarks 	if (perm & S_IXOTH)
78*5a5eeccaSmarks 		txt_perms[2] = 'x';
79*5a5eeccaSmarks 	else
80*5a5eeccaSmarks 		txt_perms[2] = '-';
81*5a5eeccaSmarks 	txt_perms[3] = '\0';
82*5a5eeccaSmarks }
83fa9e4066Sahrens 
84*5a5eeccaSmarks static char *
85*5a5eeccaSmarks pruname(uid_t uid, char *uidp)
86*5a5eeccaSmarks {
87*5a5eeccaSmarks 	struct passwd	*passwdp;
88fa9e4066Sahrens 
89*5a5eeccaSmarks 	passwdp = getpwuid(uid);
90*5a5eeccaSmarks 	if (passwdp == (struct passwd *)NULL) {
91*5a5eeccaSmarks 		/* could not get passwd information: display uid instead */
92*5a5eeccaSmarks 		(void) sprintf(uidp, "%ld", (long)uid);
93*5a5eeccaSmarks 		return (uidp);
94*5a5eeccaSmarks 	} else
95*5a5eeccaSmarks 		return (passwdp->pw_name);
96*5a5eeccaSmarks }
97fa9e4066Sahrens 
98*5a5eeccaSmarks static char *
99*5a5eeccaSmarks prgname(gid_t gid, char *gidp)
100*5a5eeccaSmarks {
101*5a5eeccaSmarks 	struct group	*groupp;
102fa9e4066Sahrens 
103*5a5eeccaSmarks 	groupp = getgrgid(gid);
104*5a5eeccaSmarks 	if (groupp == (struct group *)NULL) {
105*5a5eeccaSmarks 		/* could not get group information: display gid instead */
106*5a5eeccaSmarks 		(void) sprintf(gidp, "%ld", (long)gid);
107*5a5eeccaSmarks 		return (gidp);
108*5a5eeccaSmarks 	} else
109*5a5eeccaSmarks 		return (groupp->gr_name);
110*5a5eeccaSmarks }
111*5a5eeccaSmarks static void
112*5a5eeccaSmarks aclent_printacl(acl_t *aclp)
113*5a5eeccaSmarks {
114*5a5eeccaSmarks 	aclent_t *tp;
115*5a5eeccaSmarks 	int aclcnt;
116*5a5eeccaSmarks 	int mask;
117*5a5eeccaSmarks 	int slot = 0;
118*5a5eeccaSmarks 	char perm[4];
119*5a5eeccaSmarks 	char uidp[10];
120*5a5eeccaSmarks 	char gidp[10];
121*5a5eeccaSmarks 
122*5a5eeccaSmarks 	/* display ACL: assume it is sorted. */
123*5a5eeccaSmarks 	aclcnt = aclp->acl_cnt;
124*5a5eeccaSmarks 	for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) {
125*5a5eeccaSmarks 		if (tp->a_type == CLASS_OBJ)
126*5a5eeccaSmarks 			mask = tp->a_perm;
127*5a5eeccaSmarks 	}
128*5a5eeccaSmarks 	aclcnt = aclp->acl_cnt;
129*5a5eeccaSmarks 	for (tp = aclp->acl_aclp; aclcnt--; tp++) {
130*5a5eeccaSmarks 		(void) printf("     %d:", slot++);
131*5a5eeccaSmarks 		switch (tp->a_type) {
132*5a5eeccaSmarks 		case USER:
133*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
134*5a5eeccaSmarks 			(void) printf("user:%s:%s\t\t",
135*5a5eeccaSmarks 			    pruname(tp->a_id, uidp), perm);
136*5a5eeccaSmarks 			aclent_perms((tp->a_perm & mask), perm);
137*5a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
138*5a5eeccaSmarks 			break;
139*5a5eeccaSmarks 		case USER_OBJ:
140*5a5eeccaSmarks 			/* no need to display uid */
141*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
142*5a5eeccaSmarks 			(void) printf("user::%s\n", perm);
143*5a5eeccaSmarks 			break;
144*5a5eeccaSmarks 		case GROUP:
145*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
146*5a5eeccaSmarks 			(void) printf("group:%s:%s\t\t",
147*5a5eeccaSmarks 			    prgname(tp->a_id, gidp), perm);
148*5a5eeccaSmarks 			aclent_perms(tp->a_perm & mask, perm);
149*5a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
150*5a5eeccaSmarks 			break;
151*5a5eeccaSmarks 		case GROUP_OBJ:
152*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
153*5a5eeccaSmarks 			(void) printf("group::%s\t\t", perm);
154*5a5eeccaSmarks 			aclent_perms(tp->a_perm & mask, perm);
155*5a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
156*5a5eeccaSmarks 			break;
157*5a5eeccaSmarks 		case CLASS_OBJ:
158*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
159*5a5eeccaSmarks 			(void) printf("mask:%s\n", perm);
160*5a5eeccaSmarks 			break;
161*5a5eeccaSmarks 		case OTHER_OBJ:
162*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
163*5a5eeccaSmarks 			(void) printf("other:%s\n", perm);
164*5a5eeccaSmarks 			break;
165*5a5eeccaSmarks 		case DEF_USER:
166*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
167*5a5eeccaSmarks 			(void) printf("default:user:%s:%s\n",
168*5a5eeccaSmarks 			    pruname(tp->a_id, uidp), perm);
169*5a5eeccaSmarks 			break;
170*5a5eeccaSmarks 		case DEF_USER_OBJ:
171*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
172*5a5eeccaSmarks 			(void) printf("default:user::%s\n", perm);
173*5a5eeccaSmarks 			break;
174*5a5eeccaSmarks 		case DEF_GROUP:
175*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
176*5a5eeccaSmarks 			(void) printf("default:group:%s:%s\n",
177*5a5eeccaSmarks 			    prgname(tp->a_id, gidp), perm);
178*5a5eeccaSmarks 			break;
179*5a5eeccaSmarks 		case DEF_GROUP_OBJ:
180*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
181*5a5eeccaSmarks 			(void) printf("default:group::%s\n", perm);
182*5a5eeccaSmarks 			break;
183*5a5eeccaSmarks 		case DEF_CLASS_OBJ:
184*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
185*5a5eeccaSmarks 			(void) printf("default:mask:%s\n", perm);
186*5a5eeccaSmarks 			break;
187*5a5eeccaSmarks 		case DEF_OTHER_OBJ:
188*5a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
189*5a5eeccaSmarks 			(void) printf("default:other:%s\n", perm);
190*5a5eeccaSmarks 			break;
191*5a5eeccaSmarks 		default:
192*5a5eeccaSmarks 			(void) fprintf(stderr,
193*5a5eeccaSmarks 			    gettext("unrecognized entry\n"));
194*5a5eeccaSmarks 			break;
195*5a5eeccaSmarks 		}
196*5a5eeccaSmarks 	}
197*5a5eeccaSmarks }
198*5a5eeccaSmarks 
199*5a5eeccaSmarks static void
200*5a5eeccaSmarks split_line(char *str, int cols)
201*5a5eeccaSmarks {
202*5a5eeccaSmarks 	char *ptr;
203*5a5eeccaSmarks 	int len;
204*5a5eeccaSmarks 	int i;
205*5a5eeccaSmarks 	int last_split;
206*5a5eeccaSmarks 	char *pad = "";
207*5a5eeccaSmarks 	int pad_len;
208*5a5eeccaSmarks 
209*5a5eeccaSmarks 	len = strlen(str);
210*5a5eeccaSmarks 	ptr = str;
211*5a5eeccaSmarks 	pad_len = 0;
212*5a5eeccaSmarks 
213*5a5eeccaSmarks 	ptr = str;
214*5a5eeccaSmarks 	last_split = 0;
215*5a5eeccaSmarks 	for (i = 0; i != len; i++) {
216*5a5eeccaSmarks 		if ((i + pad_len + 4) >= cols) {
217*5a5eeccaSmarks 			(void) printf("%s%.*s\n", pad, last_split, ptr);
218*5a5eeccaSmarks 			ptr = &ptr[last_split];
219*5a5eeccaSmarks 			len = strlen(ptr);
220*5a5eeccaSmarks 			i = 0;
221*5a5eeccaSmarks 			pad_len = 4;
222*5a5eeccaSmarks 			pad = "         ";
223*5a5eeccaSmarks 		} else {
224*5a5eeccaSmarks 			if (ptr[i] == '/' || ptr[i] == ':') {
225*5a5eeccaSmarks 				last_split = i;
226*5a5eeccaSmarks 			}
227*5a5eeccaSmarks 		}
228*5a5eeccaSmarks 	}
229*5a5eeccaSmarks 	if (i == len) {
230*5a5eeccaSmarks 		(void) printf("%s%s\n", pad, ptr);
231*5a5eeccaSmarks 	}
232*5a5eeccaSmarks }
233*5a5eeccaSmarks 
234*5a5eeccaSmarks #define	OWNERAT_TXT	"owner@"
235*5a5eeccaSmarks #define	GROUPAT_TXT	"group@"
236*5a5eeccaSmarks #define	EVERYONEAT_TXT	"everyone@"
237*5a5eeccaSmarks #define	GROUP_TXT	"group:"
238*5a5eeccaSmarks #define	USER_TXT	"user:"
239*5a5eeccaSmarks 
240*5a5eeccaSmarks char *
241*5a5eeccaSmarks ace_type_txt(char *buf, char **endp, ace_t *acep)
242*5a5eeccaSmarks {
243*5a5eeccaSmarks 
244*5a5eeccaSmarks 	char idp[10];
245*5a5eeccaSmarks 
246*5a5eeccaSmarks 	if (buf == NULL)
247*5a5eeccaSmarks 		return (NULL);
248*5a5eeccaSmarks 
249*5a5eeccaSmarks 	switch (acep->a_flags & ACE_TYPE_FLAGS) {
250*5a5eeccaSmarks 	case ACE_OWNER:
251*5a5eeccaSmarks 		strcpy(buf, OWNERAT_TXT);
252*5a5eeccaSmarks 		*endp = buf + sizeof (OWNERAT_TXT) - 1;
253*5a5eeccaSmarks 		break;
254*5a5eeccaSmarks 
255*5a5eeccaSmarks 	case ACE_GROUP|ACE_IDENTIFIER_GROUP:
256*5a5eeccaSmarks 		strcpy(buf, GROUPAT_TXT);
257*5a5eeccaSmarks 		*endp = buf + sizeof (GROUPAT_TXT) - 1;
258*5a5eeccaSmarks 		break;
259*5a5eeccaSmarks 
260*5a5eeccaSmarks 	case ACE_IDENTIFIER_GROUP:
261*5a5eeccaSmarks 		strcpy(buf, GROUP_TXT);
262*5a5eeccaSmarks 		strcat(buf, prgname(acep->a_who, idp));
263*5a5eeccaSmarks 		*endp = buf + strlen(buf);
264*5a5eeccaSmarks 		break;
265*5a5eeccaSmarks 
266*5a5eeccaSmarks 	case ACE_EVERYONE:
267*5a5eeccaSmarks 		strcpy(buf, EVERYONEAT_TXT);
268*5a5eeccaSmarks 		*endp = buf + sizeof (EVERYONEAT_TXT) - 1;
269*5a5eeccaSmarks 		break;
270*5a5eeccaSmarks 
271*5a5eeccaSmarks 	case 0:
272*5a5eeccaSmarks 		strcpy(buf, USER_TXT);
273*5a5eeccaSmarks 		strcat(buf, pruname(acep->a_who, idp));
274*5a5eeccaSmarks 		*endp = buf + strlen(buf);
275*5a5eeccaSmarks 		break;
276*5a5eeccaSmarks 	}
277*5a5eeccaSmarks 
278*5a5eeccaSmarks 	return (buf);
279*5a5eeccaSmarks }
280*5a5eeccaSmarks 
281*5a5eeccaSmarks #define	READ_DATA_TXT	"read_data/"
282*5a5eeccaSmarks #define	WRITE_DATA_TXT	"write_data/"
283*5a5eeccaSmarks #define	EXECUTE_TXT	"execute/"
284*5a5eeccaSmarks #define	READ_XATTR_TXT	"read_xattr/"
285*5a5eeccaSmarks #define	WRITE_XATTR_TXT	"write_xattr/"
286*5a5eeccaSmarks #define	READ_ATTRIBUTES_TXT "read_attributes/"
287*5a5eeccaSmarks #define	WRITE_ATTRIBUTES_TXT "write_attributes/"
288*5a5eeccaSmarks #define	DELETE_TXT	"delete/"
289*5a5eeccaSmarks #define	DELETE_CHILD_TXT "delete_child/"
290*5a5eeccaSmarks #define	WRITE_OWNER_TXT "write_owner/"
291*5a5eeccaSmarks #define	READ_ACL_TXT	"read_acl/"
292*5a5eeccaSmarks #define	WRITE_ACL_TXT	"write_acl/"
293*5a5eeccaSmarks #define	APPEND_DATA_TXT "append_data/"
294*5a5eeccaSmarks #define	READ_DIR_TXT	"list_directory/read_data/"
295*5a5eeccaSmarks #define	ADD_DIR_TXT	"add_subdirectory/append_data/"
296*5a5eeccaSmarks #define	ADD_FILE_TXT	"add_file/write_data/"
297*5a5eeccaSmarks #define	SYNCHRONIZE_TXT "synchronize"	/* not slash on this one */
298*5a5eeccaSmarks 
299*5a5eeccaSmarks char *
300*5a5eeccaSmarks ace_perm_txt(char *buf, char **endp, uint32_t mask,
301*5a5eeccaSmarks     uint32_t iflags, int isdir, int flags)
302*5a5eeccaSmarks {
303*5a5eeccaSmarks 	char *lend = buf;		/* local end */
304*5a5eeccaSmarks 
305*5a5eeccaSmarks 	if (buf == NULL)
306*5a5eeccaSmarks 		return (NULL);
307*5a5eeccaSmarks 
308*5a5eeccaSmarks 	if (flags & ACL_COMPACT_FMT) {
309*5a5eeccaSmarks 
310*5a5eeccaSmarks 		if (mask & ACE_READ_DATA)
311*5a5eeccaSmarks 			buf[0] = 'r';
312*5a5eeccaSmarks 		else
313*5a5eeccaSmarks 			buf[0] = '-';
314*5a5eeccaSmarks 		if (mask & ACE_WRITE_DATA)
315*5a5eeccaSmarks 			buf[1] = 'w';
316*5a5eeccaSmarks 		else
317*5a5eeccaSmarks 			buf[1] = '-';
318*5a5eeccaSmarks 		if (mask & ACE_EXECUTE)
319*5a5eeccaSmarks 			buf[2] = 'x';
320*5a5eeccaSmarks 		else
321*5a5eeccaSmarks 			buf[2] = '-';
322*5a5eeccaSmarks 		if (mask & ACE_APPEND_DATA)
323*5a5eeccaSmarks 			buf[3] = 'p';
324*5a5eeccaSmarks 		else
325*5a5eeccaSmarks 			buf[3] = '-';
326*5a5eeccaSmarks 		if (mask & ACE_DELETE)
327*5a5eeccaSmarks 			buf[4] = 'd';
328*5a5eeccaSmarks 		else
329*5a5eeccaSmarks 			buf[4] = '-';
330*5a5eeccaSmarks 		if (mask & ACE_DELETE_CHILD)
331*5a5eeccaSmarks 			buf[5] = 'D';
332*5a5eeccaSmarks 		else
333*5a5eeccaSmarks 			buf[5] = '-';
334*5a5eeccaSmarks 		if (mask & ACE_READ_ATTRIBUTES)
335*5a5eeccaSmarks 			buf[6] = 'a';
336*5a5eeccaSmarks 		else
337*5a5eeccaSmarks 			buf[6] = '-';
338*5a5eeccaSmarks 		if (mask & ACE_WRITE_ATTRIBUTES)
339*5a5eeccaSmarks 			buf[7] = 'A';
340*5a5eeccaSmarks 		else
341*5a5eeccaSmarks 			buf[7] = '-';
342*5a5eeccaSmarks 		if (mask & ACE_READ_NAMED_ATTRS)
343*5a5eeccaSmarks 			buf[8] = 'R';
344*5a5eeccaSmarks 		else
345*5a5eeccaSmarks 			buf[8] = '-';
346*5a5eeccaSmarks 		if (mask & ACE_WRITE_NAMED_ATTRS)
347*5a5eeccaSmarks 			buf[9] = 'W';
348*5a5eeccaSmarks 		else
349*5a5eeccaSmarks 			buf[9] = '-';
350*5a5eeccaSmarks 		if (mask & ACE_READ_ACL)
351*5a5eeccaSmarks 			buf[10] = 'c';
352*5a5eeccaSmarks 		else
353*5a5eeccaSmarks 			buf[10] = '-';
354*5a5eeccaSmarks 		if (mask & ACE_WRITE_ACL)
355*5a5eeccaSmarks 			buf[11] = 'C';
356*5a5eeccaSmarks 		else
357*5a5eeccaSmarks 			buf[11] = '-';
358*5a5eeccaSmarks 		if (mask & ACE_WRITE_OWNER)
359*5a5eeccaSmarks 			buf[12] = 'o';
360*5a5eeccaSmarks 		else
361*5a5eeccaSmarks 			buf[12] = '-';
362*5a5eeccaSmarks 		if (mask & ACE_SYNCHRONIZE)
363*5a5eeccaSmarks 			buf[13] = 's';
364*5a5eeccaSmarks 		else
365*5a5eeccaSmarks 			buf[13] = '-';
366*5a5eeccaSmarks 		buf[14] = '\0';
367*5a5eeccaSmarks 		*endp = buf + 14;
368*5a5eeccaSmarks 		return (buf);
369*5a5eeccaSmarks 	} else {
370*5a5eeccaSmarks 		/*
371*5a5eeccaSmarks 		 * If ACE is a directory, but inheritance indicates its
372*5a5eeccaSmarks 		 * for a file then print permissions for file rather than
373*5a5eeccaSmarks 		 * dir.
374*5a5eeccaSmarks 		 */
375*5a5eeccaSmarks 		if (isdir) {
376*5a5eeccaSmarks 			if (mask & ACE_LIST_DIRECTORY) {
377*5a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
378*5a5eeccaSmarks 					strcpy(lend, READ_DATA_TXT);
379*5a5eeccaSmarks 					lend += sizeof (READ_DATA_TXT) - 1;
380*5a5eeccaSmarks 				} else {
381*5a5eeccaSmarks 					strcpy(lend, READ_DIR_TXT);
382*5a5eeccaSmarks 					lend += sizeof (READ_DIR_TXT) - 1;
383*5a5eeccaSmarks 				}
384*5a5eeccaSmarks 			}
385*5a5eeccaSmarks 			if (mask & ACE_ADD_FILE) {
386*5a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
387*5a5eeccaSmarks 					strcpy(lend, WRITE_DATA_TXT);
388*5a5eeccaSmarks 					lend += sizeof (WRITE_DATA_TXT) - 1;
389*5a5eeccaSmarks 				} else {
390*5a5eeccaSmarks 					strcpy(lend, ADD_FILE_TXT);
391*5a5eeccaSmarks 					lend +=
392*5a5eeccaSmarks 					    sizeof (ADD_FILE_TXT) -1;
393*5a5eeccaSmarks 				}
394*5a5eeccaSmarks 			}
395*5a5eeccaSmarks 			if (mask & ACE_ADD_SUBDIRECTORY) {
396*5a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
397*5a5eeccaSmarks 					strcpy(lend, APPEND_DATA_TXT);
398*5a5eeccaSmarks 					lend += sizeof (APPEND_DATA_TXT) - 1;
399*5a5eeccaSmarks 				} else {
400*5a5eeccaSmarks 					strcpy(lend, ADD_DIR_TXT);
401*5a5eeccaSmarks 					lend += sizeof (ADD_DIR_TXT) - 1;
402*5a5eeccaSmarks 				}
403*5a5eeccaSmarks 			}
404*5a5eeccaSmarks 		} else {
405*5a5eeccaSmarks 			if (mask & ACE_READ_DATA) {
406*5a5eeccaSmarks 				strcpy(lend, READ_DATA_TXT);
407*5a5eeccaSmarks 				lend += sizeof (READ_DATA_TXT) - 1;
408*5a5eeccaSmarks 			}
409*5a5eeccaSmarks 			if (mask & ACE_WRITE_DATA) {
410*5a5eeccaSmarks 				strcpy(lend, WRITE_DATA_TXT);
411*5a5eeccaSmarks 				lend += sizeof (WRITE_DATA_TXT) - 1;
412*5a5eeccaSmarks 			}
413*5a5eeccaSmarks 			if (mask & ACE_APPEND_DATA) {
414*5a5eeccaSmarks 				strcpy(lend, APPEND_DATA_TXT);
415*5a5eeccaSmarks 				lend += sizeof (APPEND_DATA_TXT) - 1;
416*5a5eeccaSmarks 			}
417*5a5eeccaSmarks 		}
418*5a5eeccaSmarks 		if (mask & ACE_READ_NAMED_ATTRS) {
419*5a5eeccaSmarks 			strcpy(lend, READ_XATTR_TXT);
420*5a5eeccaSmarks 			lend += sizeof (READ_XATTR_TXT) - 1;
421*5a5eeccaSmarks 		}
422*5a5eeccaSmarks 		if (mask & ACE_WRITE_NAMED_ATTRS) {
423*5a5eeccaSmarks 			strcpy(lend, WRITE_XATTR_TXT);
424*5a5eeccaSmarks 			lend += sizeof (WRITE_XATTR_TXT) - 1;
425*5a5eeccaSmarks 		}
426*5a5eeccaSmarks 		if (mask & ACE_EXECUTE) {
427*5a5eeccaSmarks 			strcpy(lend, EXECUTE_TXT);
428*5a5eeccaSmarks 			lend += sizeof (EXECUTE_TXT) - 1;
429*5a5eeccaSmarks 		}
430*5a5eeccaSmarks 		if (mask & ACE_DELETE_CHILD) {
431*5a5eeccaSmarks 			strcpy(lend, DELETE_CHILD_TXT);
432*5a5eeccaSmarks 			lend += sizeof (DELETE_CHILD_TXT) - 1;
433*5a5eeccaSmarks 		}
434*5a5eeccaSmarks 		if (mask & ACE_READ_ATTRIBUTES) {
435*5a5eeccaSmarks 			strcpy(lend, READ_ATTRIBUTES_TXT);
436*5a5eeccaSmarks 			lend += sizeof (READ_ATTRIBUTES_TXT) - 1;
437*5a5eeccaSmarks 		}
438*5a5eeccaSmarks 		if (mask & ACE_WRITE_ATTRIBUTES) {
439*5a5eeccaSmarks 			strcpy(lend, WRITE_ATTRIBUTES_TXT);
440*5a5eeccaSmarks 			lend += sizeof (WRITE_ATTRIBUTES_TXT) - 1;
441*5a5eeccaSmarks 		}
442*5a5eeccaSmarks 		if (mask & ACE_DELETE) {
443*5a5eeccaSmarks 			strcpy(lend, DELETE_TXT);
444*5a5eeccaSmarks 			lend += sizeof (DELETE_TXT) - 1;
445*5a5eeccaSmarks 		}
446*5a5eeccaSmarks 		if (mask & ACE_READ_ACL) {
447*5a5eeccaSmarks 			strcpy(lend, READ_ACL_TXT);
448*5a5eeccaSmarks 			lend += sizeof (READ_ACL_TXT) - 1;
449*5a5eeccaSmarks 		}
450*5a5eeccaSmarks 		if (mask & ACE_WRITE_ACL) {
451*5a5eeccaSmarks 			strcpy(lend, WRITE_ACL_TXT);
452*5a5eeccaSmarks 			lend += sizeof (WRITE_ACL_TXT) - 1;
453*5a5eeccaSmarks 		}
454*5a5eeccaSmarks 		if (mask & ACE_WRITE_OWNER) {
455*5a5eeccaSmarks 			strcpy(lend, WRITE_OWNER_TXT);
456*5a5eeccaSmarks 			lend += sizeof (WRITE_OWNER_TXT) - 1;
457*5a5eeccaSmarks 		}
458*5a5eeccaSmarks 		if (mask & ACE_SYNCHRONIZE) {
459*5a5eeccaSmarks 			strcpy(lend, SYNCHRONIZE_TXT);
460*5a5eeccaSmarks 			lend += sizeof (SYNCHRONIZE_TXT) - 1;
461*5a5eeccaSmarks 		}
462*5a5eeccaSmarks 
463*5a5eeccaSmarks 		if (*(lend - 1) == '/')
464*5a5eeccaSmarks 			*--lend = '\0';
465*5a5eeccaSmarks 	}
466*5a5eeccaSmarks 
467*5a5eeccaSmarks 	*endp = lend;
468*5a5eeccaSmarks 	return (buf);
469*5a5eeccaSmarks }
470*5a5eeccaSmarks 
471*5a5eeccaSmarks #define	ALLOW_TXT	"allow"
472*5a5eeccaSmarks #define	DENY_TXT	"deny"
473*5a5eeccaSmarks #define	ALARM_TXT	"alarm"
474*5a5eeccaSmarks #define	AUDIT_TXT	"audit"
475*5a5eeccaSmarks #define	UNKNOWN_TXT	"unknown"
476*5a5eeccaSmarks char *
477*5a5eeccaSmarks ace_access_txt(char *buf, char **endp, int type)
478*5a5eeccaSmarks {
479*5a5eeccaSmarks 
480*5a5eeccaSmarks 	if (buf == NULL)
481*5a5eeccaSmarks 		return (NULL);
482*5a5eeccaSmarks 
483*5a5eeccaSmarks 	if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
484*5a5eeccaSmarks 		strcpy(buf, ALLOW_TXT);
485*5a5eeccaSmarks 		*endp += sizeof (ALLOW_TXT) - 1;
486*5a5eeccaSmarks 	} else if (type == ACE_ACCESS_DENIED_ACE_TYPE) {
487*5a5eeccaSmarks 		strcpy(buf, DENY_TXT);
488*5a5eeccaSmarks 		*endp += sizeof (DENY_TXT) - 1;
489*5a5eeccaSmarks 	} else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) {
490*5a5eeccaSmarks 		strcpy(buf, AUDIT_TXT);
491*5a5eeccaSmarks 		*endp += sizeof (AUDIT_TXT) - 1;
492*5a5eeccaSmarks 	} else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) {
493*5a5eeccaSmarks 		strcpy(buf, ALARM_TXT);
494*5a5eeccaSmarks 		*endp += sizeof (ALARM_TXT) - 1;
495*5a5eeccaSmarks 	} else {
496*5a5eeccaSmarks 		strcpy(buf, UNKNOWN_TXT);
497*5a5eeccaSmarks 		*endp += sizeof (UNKNOWN_TXT) - 1;
498*5a5eeccaSmarks 	}
499*5a5eeccaSmarks 
500*5a5eeccaSmarks 	return (buf);
501*5a5eeccaSmarks }
502*5a5eeccaSmarks 
503*5a5eeccaSmarks static char *
504*5a5eeccaSmarks ace_inherit_txt(char *buf, char **endp, uint32_t iflags, int flags)
505*5a5eeccaSmarks {
506*5a5eeccaSmarks 
507*5a5eeccaSmarks 	char *lend = buf;
508*5a5eeccaSmarks 
509*5a5eeccaSmarks 	if (buf == NULL) {
510*5a5eeccaSmarks 		return (NULL);
511*5a5eeccaSmarks 	}
512*5a5eeccaSmarks 
513*5a5eeccaSmarks 	if (flags & ACL_COMPACT_FMT) {
514*5a5eeccaSmarks 		if (iflags & ACE_FILE_INHERIT_ACE)
515*5a5eeccaSmarks 			buf[0] = 'f';
516*5a5eeccaSmarks 		else
517*5a5eeccaSmarks 			buf[0] = '-';
518*5a5eeccaSmarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE)
519*5a5eeccaSmarks 			buf[1] = 'd';
520*5a5eeccaSmarks 		else
521*5a5eeccaSmarks 			buf[1] = '-';
522*5a5eeccaSmarks 		if (iflags & ACE_INHERIT_ONLY_ACE)
523*5a5eeccaSmarks 			buf[2] = 'i';
524*5a5eeccaSmarks 		else
525*5a5eeccaSmarks 			buf[2] = '-';
526*5a5eeccaSmarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)
527*5a5eeccaSmarks 			buf[3] = 'n';
528*5a5eeccaSmarks 		else
529*5a5eeccaSmarks 			buf[3] = '-';
530*5a5eeccaSmarks 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
531*5a5eeccaSmarks 			buf[4] = 'S';
532*5a5eeccaSmarks 		else
533*5a5eeccaSmarks 			buf[4] = '-';
534*5a5eeccaSmarks 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG)
535*5a5eeccaSmarks 			buf[5] = 'F';
536*5a5eeccaSmarks 		else
537*5a5eeccaSmarks 			buf[5] = '-';
538*5a5eeccaSmarks 		buf[6] = '\0';
539*5a5eeccaSmarks 		*endp = buf + 6;
540*5a5eeccaSmarks 	} else {
541*5a5eeccaSmarks 		if (iflags & ACE_FILE_INHERIT_ACE) {
542*5a5eeccaSmarks 			strcpy(lend, "file_inherit/");
543*5a5eeccaSmarks 			lend += sizeof ("file_inherit/") - 1;
544*5a5eeccaSmarks 		}
545*5a5eeccaSmarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE) {
546*5a5eeccaSmarks 			strcpy(lend, "dir_inherit/");
547*5a5eeccaSmarks 			lend += sizeof ("dir_inherit/") - 1;
548*5a5eeccaSmarks 		}
549*5a5eeccaSmarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) {
550*5a5eeccaSmarks 			strcpy(lend, "no_propagate/");
551*5a5eeccaSmarks 			lend += sizeof ("no_propagate/") - 1;
552*5a5eeccaSmarks 		}
553*5a5eeccaSmarks 		if (iflags & ACE_INHERIT_ONLY_ACE) {
554*5a5eeccaSmarks 			strcpy(lend, "inherit_only/");
555*5a5eeccaSmarks 			lend += sizeof ("inherit_only/") - 1;
556*5a5eeccaSmarks 		}
557*5a5eeccaSmarks 
558*5a5eeccaSmarks 		if (*(lend - 1) == '/')
559*5a5eeccaSmarks 			*--lend = '\0';
560*5a5eeccaSmarks 		*endp = lend;
561*5a5eeccaSmarks 	}
562*5a5eeccaSmarks 
563*5a5eeccaSmarks 	return (buf);
564fa9e4066Sahrens }
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate  * Convert internal acl representation to external representation.
5687c478bd9Sstevel@tonic-gate  *
5697c478bd9Sstevel@tonic-gate  * The length of a non-owning user name or non-owning group name ie entries
5707c478bd9Sstevel@tonic-gate  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
5717c478bd9Sstevel@tonic-gate  * thus check the length of these entries, and if greater than LOGNAME_MAX,
5727c478bd9Sstevel@tonic-gate  * we realloc() via increase_length().
5737c478bd9Sstevel@tonic-gate  *
5747c478bd9Sstevel@tonic-gate  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
5757c478bd9Sstevel@tonic-gate  * adhered to.
5767c478bd9Sstevel@tonic-gate  */
577*5a5eeccaSmarks 
578*5a5eeccaSmarks /*
579*5a5eeccaSmarks  * acltotext() converts each ACL entry to look like this:
580*5a5eeccaSmarks  *
581*5a5eeccaSmarks  *    entry_type:uid^gid^name:perms[:id]
582*5a5eeccaSmarks  *
583*5a5eeccaSmarks  * The maximum length of entry_type is 14 ("defaultgroup::" and
584*5a5eeccaSmarks  * "defaultother::") hence ENTRYTYPELEN is set to 14.
585*5a5eeccaSmarks  *
586*5a5eeccaSmarks  * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
587*5a5eeccaSmarks  * however the ID could be a number so we therefore use ID_STR_MAX
588*5a5eeccaSmarks  *
589*5a5eeccaSmarks  * The length of a perms entry is 4 to allow for the comma appended to each
590*5a5eeccaSmarks  * to each acl entry.  Hence PERMS is set to 4.
591*5a5eeccaSmarks  */
592*5a5eeccaSmarks 
593*5a5eeccaSmarks #define	ENTRYTYPELEN	14
594*5a5eeccaSmarks #define	PERMS		4
595*5a5eeccaSmarks #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
596*5a5eeccaSmarks #define	UPDATE_WHERE	where = dstr->aclexport + strlen(dstr->aclexport)
597*5a5eeccaSmarks 
5987c478bd9Sstevel@tonic-gate char *
599*5a5eeccaSmarks aclent_acltotext(aclent_t  *aclp, int aclcnt, int flags)
6007c478bd9Sstevel@tonic-gate {
6017c478bd9Sstevel@tonic-gate 	char		*aclexport;
6027c478bd9Sstevel@tonic-gate 	char		*where;
6037c478bd9Sstevel@tonic-gate 	struct group	*groupp;
6047c478bd9Sstevel@tonic-gate 	struct passwd	*passwdp;
6057c478bd9Sstevel@tonic-gate 	struct dynaclstr *dstr;
6067c478bd9Sstevel@tonic-gate 	int		i, rtn;
6077c478bd9Sstevel@tonic-gate 	size_t		excess = 0;
608*5a5eeccaSmarks 	char		id[20], *idstr;
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	if (aclp == NULL)
6117c478bd9Sstevel@tonic-gate 		return (NULL);
6127c478bd9Sstevel@tonic-gate 	if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL)
6137c478bd9Sstevel@tonic-gate 		return (NULL);
6147c478bd9Sstevel@tonic-gate 	dstr->bufsize = aclcnt * ACL_ENTRY_SIZE;
6157c478bd9Sstevel@tonic-gate 	if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) {
6167c478bd9Sstevel@tonic-gate 		free(dstr);
6177c478bd9Sstevel@tonic-gate 		return (NULL);
6187c478bd9Sstevel@tonic-gate 	}
6197c478bd9Sstevel@tonic-gate 	*dstr->aclexport = '\0';
6207c478bd9Sstevel@tonic-gate 	where = dstr->aclexport;
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	for (i = 0; i < aclcnt; i++, aclp++) {
6237c478bd9Sstevel@tonic-gate 		switch (aclp->a_type) {
6247c478bd9Sstevel@tonic-gate 		case DEF_USER_OBJ:
6257c478bd9Sstevel@tonic-gate 		case USER_OBJ:
6267c478bd9Sstevel@tonic-gate 			if (aclp->a_type == USER_OBJ)
6277c478bd9Sstevel@tonic-gate 				where = strappend(where, "user::");
6287c478bd9Sstevel@tonic-gate 			else
6297c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultuser::");
6307c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6317c478bd9Sstevel@tonic-gate 			break;
6327c478bd9Sstevel@tonic-gate 		case DEF_USER:
6337c478bd9Sstevel@tonic-gate 		case USER:
6347c478bd9Sstevel@tonic-gate 			if (aclp->a_type == USER)
6357c478bd9Sstevel@tonic-gate 				where = strappend(where, "user:");
6367c478bd9Sstevel@tonic-gate 			else
6377c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultuser:");
6387c478bd9Sstevel@tonic-gate 			passwdp = getpwuid(aclp->a_id);
6397c478bd9Sstevel@tonic-gate 			if (passwdp == (struct passwd *)NULL) {
6407c478bd9Sstevel@tonic-gate 				/* put in uid instead */
6417c478bd9Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
64211e32170Shm123892 				UPDATE_WHERE;
6437c478bd9Sstevel@tonic-gate 			} else {
6447c478bd9Sstevel@tonic-gate 				excess = strlen(passwdp->pw_name) - LOGNAME_MAX;
6457c478bd9Sstevel@tonic-gate 				if (excess > 0) {
6467c478bd9Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
6477c478bd9Sstevel@tonic-gate 					if (rtn == 1) {
64811e32170Shm123892 						UPDATE_WHERE;
6497c478bd9Sstevel@tonic-gate 					} else {
6507c478bd9Sstevel@tonic-gate 						free(dstr->aclexport);
6517c478bd9Sstevel@tonic-gate 						free(dstr);
6527c478bd9Sstevel@tonic-gate 						return (NULL);
6537c478bd9Sstevel@tonic-gate 					}
6547c478bd9Sstevel@tonic-gate 				}
6557c478bd9Sstevel@tonic-gate 				where = strappend(where, passwdp->pw_name);
6567c478bd9Sstevel@tonic-gate 			}
6577c478bd9Sstevel@tonic-gate 			where = strappend(where, ":");
6587c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6597c478bd9Sstevel@tonic-gate 			break;
6607c478bd9Sstevel@tonic-gate 		case DEF_GROUP_OBJ:
6617c478bd9Sstevel@tonic-gate 		case GROUP_OBJ:
6627c478bd9Sstevel@tonic-gate 			if (aclp->a_type == GROUP_OBJ)
6637c478bd9Sstevel@tonic-gate 				where = strappend(where, "group::");
6647c478bd9Sstevel@tonic-gate 			else
6657c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultgroup::");
6667c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6677c478bd9Sstevel@tonic-gate 			break;
6687c478bd9Sstevel@tonic-gate 		case DEF_GROUP:
6697c478bd9Sstevel@tonic-gate 		case GROUP:
6707c478bd9Sstevel@tonic-gate 			if (aclp->a_type == GROUP)
6717c478bd9Sstevel@tonic-gate 				where = strappend(where, "group:");
6727c478bd9Sstevel@tonic-gate 			else
6737c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultgroup:");
6747c478bd9Sstevel@tonic-gate 			groupp = getgrgid(aclp->a_id);
6757c478bd9Sstevel@tonic-gate 			if (groupp == (struct group *)NULL) {
6767c478bd9Sstevel@tonic-gate 				/* put in gid instead */
6777c478bd9Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
67811e32170Shm123892 				UPDATE_WHERE;
6797c478bd9Sstevel@tonic-gate 			} else {
6807c478bd9Sstevel@tonic-gate 				excess = strlen(groupp->gr_name) - LOGNAME_MAX;
6817c478bd9Sstevel@tonic-gate 				if (excess > 0) {
6827c478bd9Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
6837c478bd9Sstevel@tonic-gate 					if (rtn == 1) {
68411e32170Shm123892 						UPDATE_WHERE;
6857c478bd9Sstevel@tonic-gate 					} else {
6867c478bd9Sstevel@tonic-gate 						free(dstr->aclexport);
6877c478bd9Sstevel@tonic-gate 						free(dstr);
6887c478bd9Sstevel@tonic-gate 						return (NULL);
6897c478bd9Sstevel@tonic-gate 					}
6907c478bd9Sstevel@tonic-gate 				}
6917c478bd9Sstevel@tonic-gate 				where = strappend(where, groupp->gr_name);
6927c478bd9Sstevel@tonic-gate 			}
6937c478bd9Sstevel@tonic-gate 			where = strappend(where, ":");
6947c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
6957c478bd9Sstevel@tonic-gate 			break;
6967c478bd9Sstevel@tonic-gate 		case DEF_CLASS_OBJ:
6977c478bd9Sstevel@tonic-gate 		case CLASS_OBJ:
6987c478bd9Sstevel@tonic-gate 			if (aclp->a_type == CLASS_OBJ)
6997c478bd9Sstevel@tonic-gate 				where = strappend(where, "mask:");
7007c478bd9Sstevel@tonic-gate 			else
7017c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultmask:");
7027c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
7037c478bd9Sstevel@tonic-gate 			break;
7047c478bd9Sstevel@tonic-gate 		case DEF_OTHER_OBJ:
7057c478bd9Sstevel@tonic-gate 		case OTHER_OBJ:
7067c478bd9Sstevel@tonic-gate 			if (aclp->a_type == OTHER_OBJ)
7077c478bd9Sstevel@tonic-gate 				where = strappend(where, "other:");
7087c478bd9Sstevel@tonic-gate 			else
7097c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultother:");
7107c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
7117c478bd9Sstevel@tonic-gate 			break;
7127c478bd9Sstevel@tonic-gate 		default:
7137c478bd9Sstevel@tonic-gate 			free(dstr->aclexport);
7147c478bd9Sstevel@tonic-gate 			free(dstr);
7157c478bd9Sstevel@tonic-gate 			return (NULL);
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 		}
718*5a5eeccaSmarks 
719*5a5eeccaSmarks 		if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) ||
720*5a5eeccaSmarks 		    (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) ||
721*5a5eeccaSmarks 		    (aclp->a_type == DEF_GROUP))) {
722*5a5eeccaSmarks 			where = strappend(where, ":");
723*5a5eeccaSmarks 			id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */
724*5a5eeccaSmarks 			idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]);
725*5a5eeccaSmarks 			where = strappend(where, idstr);
726*5a5eeccaSmarks 		}
7277c478bd9Sstevel@tonic-gate 		if (i < aclcnt - 1)
7287c478bd9Sstevel@tonic-gate 			where = strappend(where, ",");
7297c478bd9Sstevel@tonic-gate 	}
7307c478bd9Sstevel@tonic-gate 	aclexport = dstr->aclexport;
7317c478bd9Sstevel@tonic-gate 	free(dstr);
7327c478bd9Sstevel@tonic-gate 	return (aclexport);
733*5a5eeccaSmarks 
734*5a5eeccaSmarks 
735*5a5eeccaSmarks 
736*5a5eeccaSmarks 
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate 
739*5a5eeccaSmarks char *
740*5a5eeccaSmarks acltotext(aclent_t *aclp, int aclcnt)
7417c478bd9Sstevel@tonic-gate {
742*5a5eeccaSmarks 	return (aclent_acltotext(aclp, aclcnt, 0));
743fa9e4066Sahrens }
744fa9e4066Sahrens 
7457c478bd9Sstevel@tonic-gate 
746fa9e4066Sahrens aclent_t *
747fa9e4066Sahrens aclfromtext(char *aclstr, int *aclcnt)
748fa9e4066Sahrens {
749fa9e4066Sahrens 	acl_t *aclp;
750fa9e4066Sahrens 	aclent_t *aclentp;
751fa9e4066Sahrens 	int error;
752fa9e4066Sahrens 
753*5a5eeccaSmarks 	error = acl_fromtext(aclstr, &aclp);
754fa9e4066Sahrens 	if (error)
755fa9e4066Sahrens 		return (NULL);
756fa9e4066Sahrens 
757fa9e4066Sahrens 	aclentp = aclp->acl_aclp;
758fa9e4066Sahrens 	aclp->acl_aclp = NULL;
759fa9e4066Sahrens 	*aclcnt = aclp->acl_cnt;
760*5a5eeccaSmarks 
761*5a5eeccaSmarks 	acl_free(aclp);
762fa9e4066Sahrens 	return (aclentp);
763fa9e4066Sahrens }
764fa9e4066Sahrens 
765fa9e4066Sahrens 
7667c478bd9Sstevel@tonic-gate static char *
7677c478bd9Sstevel@tonic-gate strappend(char *where, char *newstr)
7687c478bd9Sstevel@tonic-gate {
7697c478bd9Sstevel@tonic-gate 	(void) strcat(where, newstr);
7707c478bd9Sstevel@tonic-gate 	return (where + strlen(newstr));
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate static char *
7747c478bd9Sstevel@tonic-gate convert_perm(char *where, o_mode_t perm)
7757c478bd9Sstevel@tonic-gate {
776*5a5eeccaSmarks 	if (perm & S_IROTH)
7777c478bd9Sstevel@tonic-gate 		where = strappend(where, "r");
7787c478bd9Sstevel@tonic-gate 	else
7797c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
780*5a5eeccaSmarks 	if (perm & S_IWOTH)
7817c478bd9Sstevel@tonic-gate 		where = strappend(where, "w");
7827c478bd9Sstevel@tonic-gate 	else
7837c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
784*5a5eeccaSmarks 	if (perm & S_IXOTH)
7857c478bd9Sstevel@tonic-gate 		where = strappend(where, "x");
7867c478bd9Sstevel@tonic-gate 	else
7877c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
7887c478bd9Sstevel@tonic-gate 	/* perm is the last field */
7897c478bd9Sstevel@tonic-gate 	return (where);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate /*
7937c478bd9Sstevel@tonic-gate  * Callers should check the return code as this routine may change the string
7947c478bd9Sstevel@tonic-gate  * pointer in dynaclstr.
7957c478bd9Sstevel@tonic-gate  */
7967c478bd9Sstevel@tonic-gate static int
7977c478bd9Sstevel@tonic-gate increase_length(struct dynaclstr *dacl, size_t increase)
7987c478bd9Sstevel@tonic-gate {
7997c478bd9Sstevel@tonic-gate 	char *tptr;
8007c478bd9Sstevel@tonic-gate 	size_t newsize;
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 	newsize = dacl->bufsize + increase;
8037c478bd9Sstevel@tonic-gate 	tptr = realloc(dacl->aclexport, newsize);
8047c478bd9Sstevel@tonic-gate 	if (tptr != NULL) {
8057c478bd9Sstevel@tonic-gate 		dacl->aclexport = tptr;
8067c478bd9Sstevel@tonic-gate 		dacl->bufsize = newsize;
8077c478bd9Sstevel@tonic-gate 		return (1);
8087c478bd9Sstevel@tonic-gate 	} else
8097c478bd9Sstevel@tonic-gate 		return (0);
8107c478bd9Sstevel@tonic-gate }
811fa9e4066Sahrens 
812fa9e4066Sahrens /*
813*5a5eeccaSmarks  * ace_acltotext() convert each ace formatted acl to look like this:
814fa9e4066Sahrens  *
815*5a5eeccaSmarks  * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
816fa9e4066Sahrens  *
817fa9e4066Sahrens  * The maximum length of entry_type is 5 ("group")
818fa9e4066Sahrens  *
819*5a5eeccaSmarks  * The max length of a uid^gid^name entry (in theory) is 8,
820*5a5eeccaSmarks  * however id could be a number so we therefore use ID_STR_MAX
821fa9e4066Sahrens  *
822fa9e4066Sahrens  * The length of a perms entry is 144 i.e read_data/write_data...
823fa9e4066Sahrens  * to each acl entry.
824fa9e4066Sahrens  *
825fa9e4066Sahrens  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate
826fa9e4066Sahrens  *
827fa9e4066Sahrens  */
828fa9e4066Sahrens 
829fa9e4066Sahrens #define	ACE_ENTRYTYPLEN		6
830fa9e4066Sahrens #define	IFLAGS_SIZE		51
831*5a5eeccaSmarks #define	ACCESS_TYPE_SIZE	7	/* if unknown */
832fa9e4066Sahrens #define	COLON_CNT		3
833fa9e4066Sahrens #define	PERMS_LEN		216
834*5a5eeccaSmarks #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN +\
835*5a5eeccaSmarks     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
836fa9e4066Sahrens 
837fa9e4066Sahrens static char *
838*5a5eeccaSmarks ace_acltotext(acl_t *aceaclp, int flags)
839fa9e4066Sahrens {
840fa9e4066Sahrens 	ace_t		*aclp = aceaclp->acl_aclp;
841fa9e4066Sahrens 	int		aclcnt = aceaclp->acl_cnt;
842fa9e4066Sahrens 	char		*aclexport;
843*5a5eeccaSmarks 	char		*endp;
844*5a5eeccaSmarks 	int		i;
845*5a5eeccaSmarks 	char		id[ID_STR_MAX], *idstr;
846fa9e4066Sahrens 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
847fa9e4066Sahrens 
848fa9e4066Sahrens 	if (aclp == NULL)
849fa9e4066Sahrens 		return (NULL);
850*5a5eeccaSmarks 	if ((aclexport = malloc(aclcnt * ACE_ENTRY_SIZE)) == NULL)
851fa9e4066Sahrens 		return (NULL);
852fa9e4066Sahrens 
853*5a5eeccaSmarks 	aclexport[0] = '\0';
854*5a5eeccaSmarks 	endp = aclexport;
855fa9e4066Sahrens 	for (i = 0; i < aclcnt; i++, aclp++) {
856fa9e4066Sahrens 
857*5a5eeccaSmarks 		(void) ace_type_txt(endp, &endp, aclp);
858*5a5eeccaSmarks 		*endp++ = ':';
859*5a5eeccaSmarks 		*endp = '\0';
860*5a5eeccaSmarks 		(void) ace_perm_txt(endp, &endp, aclp->a_access_mask,
861*5a5eeccaSmarks 		    aclp->a_flags, isdir, flags);
862*5a5eeccaSmarks 		*endp++ = ':';
863*5a5eeccaSmarks 		*endp = '\0';
864*5a5eeccaSmarks 		(void) ace_inherit_txt(endp, &endp, aclp->a_flags, flags);
865*5a5eeccaSmarks 		if (flags & ACL_COMPACT_FMT || aclp->a_flags &
866*5a5eeccaSmarks 		    (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE |
867*5a5eeccaSmarks 		    (ACE_INHERIT_ONLY_ACE | ACE_NO_PROPAGATE_INHERIT_ACE))) {
868*5a5eeccaSmarks 			*endp++ = ':';
869*5a5eeccaSmarks 			*endp = '\0';
870fa9e4066Sahrens 		}
871*5a5eeccaSmarks 		(void) ace_access_txt(endp, &endp, aclp->a_type);
872fa9e4066Sahrens 
873*5a5eeccaSmarks 		if ((flags & ACL_APPEND_ID) &&
874*5a5eeccaSmarks 		    (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ||
875*5a5eeccaSmarks 		    ((aclp->a_flags & ACE_TYPE_FLAGS) ==
876*5a5eeccaSmarks 		    ACE_IDENTIFIER_GROUP))) {
877*5a5eeccaSmarks 			*endp++ = ':';
878*5a5eeccaSmarks 			*endp = '\0';
879*5a5eeccaSmarks 			id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */
880*5a5eeccaSmarks 			idstr = lltostr(aclp->a_who, &id[ID_STR_MAX - 1]);
881*5a5eeccaSmarks 			strcpy(endp, idstr);
882*5a5eeccaSmarks 			endp += strlen(idstr);
883*5a5eeccaSmarks 		}
884*5a5eeccaSmarks 		if (i < aclcnt - 1) {
885*5a5eeccaSmarks 			*endp++ = ',';
886*5a5eeccaSmarks 			*(endp + 1) = '\0';
887fa9e4066Sahrens 		}
888fa9e4066Sahrens 	}
889fa9e4066Sahrens 	return (aclexport);
890fa9e4066Sahrens }
891fa9e4066Sahrens 
892*5a5eeccaSmarks char *
893*5a5eeccaSmarks acl_totext(acl_t *aclp, int flags)
894fa9e4066Sahrens {
895fa9e4066Sahrens 
896*5a5eeccaSmarks 	char *txtp;
897fa9e4066Sahrens 
898fa9e4066Sahrens 	if (aclp == NULL)
899fa9e4066Sahrens 		return (NULL);
900fa9e4066Sahrens 
901fa9e4066Sahrens 	switch (aclp->acl_type) {
902fa9e4066Sahrens 	case ACE_T:
903*5a5eeccaSmarks 		txtp = ace_acltotext(aclp, flags);
904*5a5eeccaSmarks 		break;
905fa9e4066Sahrens 	case ACLENT_T:
906*5a5eeccaSmarks 		txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags);
907*5a5eeccaSmarks 		break;
908fa9e4066Sahrens 	}
909*5a5eeccaSmarks 
910*5a5eeccaSmarks 	return (txtp);
911fa9e4066Sahrens }
912fa9e4066Sahrens 
913fa9e4066Sahrens int
914fa9e4066Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp)
915fa9e4066Sahrens {
916*5a5eeccaSmarks 	int error;
917*5a5eeccaSmarks 	char *buf;
918*5a5eeccaSmarks 
919*5a5eeccaSmarks 	buf = malloc(strlen(acltextp) + 2);
920*5a5eeccaSmarks 	if (buf == NULL)
921*5a5eeccaSmarks 		return (EACL_MEM_ERROR);
922*5a5eeccaSmarks 	strcpy(buf, acltextp);
923*5a5eeccaSmarks 	strcat(buf, "\n");
924*5a5eeccaSmarks 	yybuf = buf;
925*5a5eeccaSmarks 	yyreset();
926*5a5eeccaSmarks 	error = yyparse();
927*5a5eeccaSmarks 	free(buf);
928*5a5eeccaSmarks 
929*5a5eeccaSmarks 	if (yyacl) {
930*5a5eeccaSmarks 		if (error == 0)
931*5a5eeccaSmarks 			*ret_aclp = yyacl;
932*5a5eeccaSmarks 		else {
933*5a5eeccaSmarks 			acl_free(yyacl);
934*5a5eeccaSmarks 		}
935*5a5eeccaSmarks 		yyacl = NULL;
936*5a5eeccaSmarks 	}
937*5a5eeccaSmarks 	return (error);
938*5a5eeccaSmarks }
939*5a5eeccaSmarks 
940*5a5eeccaSmarks int
941*5a5eeccaSmarks acl_parse(const char *acltextp, acl_t **aclp)
942*5a5eeccaSmarks {
943fa9e4066Sahrens 	int error;
944fa9e4066Sahrens 
945*5a5eeccaSmarks 	yyinteractive = 1;
946*5a5eeccaSmarks 	error = acl_fromtext(acltextp, aclp);
947*5a5eeccaSmarks 	yyinteractive = 0;
948fa9e4066Sahrens 	return (error);
949fa9e4066Sahrens }
950*5a5eeccaSmarks 
951*5a5eeccaSmarks static void
952*5a5eeccaSmarks ace_compact_printacl(acl_t *aclp)
953*5a5eeccaSmarks {
954*5a5eeccaSmarks 	int cnt;
955*5a5eeccaSmarks 	ace_t *acep;
956*5a5eeccaSmarks 	char *endp;
957*5a5eeccaSmarks 	char buf[ACE_ENTRY_SIZE];
958*5a5eeccaSmarks 
959*5a5eeccaSmarks 	for (cnt = 0, acep = aclp->acl_aclp;
960*5a5eeccaSmarks 	    cnt != aclp->acl_cnt; cnt++, acep++) {
961*5a5eeccaSmarks 		buf[0] = '\0';
962*5a5eeccaSmarks 		(void) printf("    %14s:", ace_type_txt(buf, &endp, acep));
963*5a5eeccaSmarks 		(void) printf("%s:", ace_perm_txt(endp, &endp,
964*5a5eeccaSmarks 		    acep->a_access_mask, acep->a_flags,
965*5a5eeccaSmarks 		    aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT));
966*5a5eeccaSmarks 		(void) printf("%s:",
967*5a5eeccaSmarks 		    ace_inherit_txt(endp, &endp, acep->a_flags,
968*5a5eeccaSmarks 			ACL_COMPACT_FMT));
969*5a5eeccaSmarks 		(void) printf("%s\n", ace_access_txt(endp, &endp,
970*5a5eeccaSmarks 		    acep->a_type));
971*5a5eeccaSmarks 	}
972*5a5eeccaSmarks }
973*5a5eeccaSmarks 
974*5a5eeccaSmarks static void
975*5a5eeccaSmarks ace_printacl(acl_t *aclp, int cols, int compact)
976*5a5eeccaSmarks {
977*5a5eeccaSmarks 	int  slot = 0;
978*5a5eeccaSmarks 	char *token;
979*5a5eeccaSmarks 	char *acltext;
980*5a5eeccaSmarks 
981*5a5eeccaSmarks 	if (compact) {
982*5a5eeccaSmarks 		ace_compact_printacl(aclp);
983*5a5eeccaSmarks 		return;
984*5a5eeccaSmarks 	}
985*5a5eeccaSmarks 
986*5a5eeccaSmarks 	acltext = acl_totext(aclp, 0);
987*5a5eeccaSmarks 
988*5a5eeccaSmarks 	if (acltext == NULL)
989*5a5eeccaSmarks 		return;
990*5a5eeccaSmarks 
991*5a5eeccaSmarks 	token = strtok(acltext, ",");
992*5a5eeccaSmarks 	if (token == NULL) {
993*5a5eeccaSmarks 		free(acltext);
994*5a5eeccaSmarks 		return;
995*5a5eeccaSmarks 	}
996*5a5eeccaSmarks 
997*5a5eeccaSmarks 	do {
998*5a5eeccaSmarks 		(void) printf("     %d:", slot++);
999*5a5eeccaSmarks 		split_line(token, cols - 5);
1000*5a5eeccaSmarks 	} while (token = strtok(NULL, ","));
1001*5a5eeccaSmarks 	free(acltext);
1002*5a5eeccaSmarks }
1003*5a5eeccaSmarks 
1004*5a5eeccaSmarks /*
1005*5a5eeccaSmarks  * pretty print an ACL.
1006*5a5eeccaSmarks  * For aclent_t ACL's the format is
1007*5a5eeccaSmarks  * similar to the old format used by getfacl,
1008*5a5eeccaSmarks  * with the addition of adding a "slot" number
1009*5a5eeccaSmarks  * before each entry.
1010*5a5eeccaSmarks  *
1011*5a5eeccaSmarks  * for ace_t ACL's the cols variable will break up
1012*5a5eeccaSmarks  * the long lines into multiple lines and will also
1013*5a5eeccaSmarks  * print a "slot" number.
1014*5a5eeccaSmarks  */
1015*5a5eeccaSmarks void
1016*5a5eeccaSmarks acl_printacl(acl_t *aclp, int cols, int compact)
1017*5a5eeccaSmarks {
1018*5a5eeccaSmarks 
1019*5a5eeccaSmarks 	switch (aclp->acl_type) {
1020*5a5eeccaSmarks 	case ACLENT_T:
1021*5a5eeccaSmarks 		aclent_printacl(aclp);
1022*5a5eeccaSmarks 		break;
1023*5a5eeccaSmarks 	case ACE_T:
1024*5a5eeccaSmarks 		ace_printacl(aclp, cols, compact);
1025*5a5eeccaSmarks 		break;
1026*5a5eeccaSmarks 	}
1027*5a5eeccaSmarks }
1028*5a5eeccaSmarks 
1029*5a5eeccaSmarks typedef struct value_table {
1030*5a5eeccaSmarks 	char		p_letter; /* perm letter such as 'r' */
1031*5a5eeccaSmarks 	uint32_t	p_value; /* value for perm when pletter found */
1032*5a5eeccaSmarks } value_table_t;
1033*5a5eeccaSmarks 
1034*5a5eeccaSmarks #define	ACE_PERM_COUNT 14
1035*5a5eeccaSmarks 
1036*5a5eeccaSmarks /*
1037*5a5eeccaSmarks  * The permission tables are layed out in positional order
1038*5a5eeccaSmarks  * a '-' character will indicate a permission at a given
1039*5a5eeccaSmarks  * position is not specified.  The '-' is not part of the
1040*5a5eeccaSmarks  * table, but will be checked for in the permission computation
1041*5a5eeccaSmarks  * routine.
1042*5a5eeccaSmarks  */
1043*5a5eeccaSmarks value_table_t ace_perm_table[ACE_PERM_COUNT] = {
1044*5a5eeccaSmarks 	{ 'r', ACE_READ_DATA},
1045*5a5eeccaSmarks 	{ 'w', ACE_WRITE_DATA},
1046*5a5eeccaSmarks 	{ 'x', ACE_EXECUTE},
1047*5a5eeccaSmarks 	{ 'p', ACE_APPEND_DATA},
1048*5a5eeccaSmarks 	{ 'd', ACE_DELETE},
1049*5a5eeccaSmarks 	{ 'D', ACE_DELETE_CHILD},
1050*5a5eeccaSmarks 	{ 'a', ACE_READ_ATTRIBUTES},
1051*5a5eeccaSmarks 	{ 'A', ACE_WRITE_ATTRIBUTES},
1052*5a5eeccaSmarks 	{ 'R', ACE_READ_NAMED_ATTRS},
1053*5a5eeccaSmarks 	{ 'W', ACE_WRITE_NAMED_ATTRS},
1054*5a5eeccaSmarks 	{ 'c', ACE_READ_ACL},
1055*5a5eeccaSmarks 	{ 'C', ACE_WRITE_ACL},
1056*5a5eeccaSmarks 	{ 'o', ACE_WRITE_OWNER},
1057*5a5eeccaSmarks 	{ 's', ACE_SYNCHRONIZE}
1058*5a5eeccaSmarks };
1059*5a5eeccaSmarks 
1060*5a5eeccaSmarks #define	ACLENT_PERM_COUNT 3
1061*5a5eeccaSmarks 
1062*5a5eeccaSmarks value_table_t aclent_perm_table[ACLENT_PERM_COUNT] = {
1063*5a5eeccaSmarks 	{ 'r', S_IROTH},
1064*5a5eeccaSmarks 	{ 'w', S_IWOTH},
1065*5a5eeccaSmarks 	{ 'x', S_IXOTH}
1066*5a5eeccaSmarks };
1067*5a5eeccaSmarks 
1068*5a5eeccaSmarks #define	IFLAG_COUNT	6
1069*5a5eeccaSmarks value_table_t inherit_table[IFLAG_COUNT] = {
1070*5a5eeccaSmarks 	{'f', ACE_FILE_INHERIT_ACE},
1071*5a5eeccaSmarks 	{'d', ACE_DIRECTORY_INHERIT_ACE},
1072*5a5eeccaSmarks 	{'i', ACE_INHERIT_ONLY_ACE},
1073*5a5eeccaSmarks 	{'n', ACE_NO_PROPAGATE_INHERIT_ACE},
1074*5a5eeccaSmarks 	{'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
1075*5a5eeccaSmarks 	{'F', ACE_FAILED_ACCESS_ACE_FLAG}
1076*5a5eeccaSmarks };
1077*5a5eeccaSmarks 
1078*5a5eeccaSmarks /*
1079*5a5eeccaSmarks  * compute value from a permission table or inheritance table
1080*5a5eeccaSmarks  * based on string passed in.  If positional is set then
1081*5a5eeccaSmarks  * string must match order in permtab, otherwise any order
1082*5a5eeccaSmarks  * is allowed.
1083*5a5eeccaSmarks  */
1084*5a5eeccaSmarks int
1085*5a5eeccaSmarks compute_values(value_table_t *permtab, int count,
1086*5a5eeccaSmarks     char *permstr, int positional, uint32_t *mask)
1087*5a5eeccaSmarks {
1088*5a5eeccaSmarks 	uint32_t perm_val = 0;
1089*5a5eeccaSmarks 	char *pstr;
1090*5a5eeccaSmarks 	int i, found;
1091*5a5eeccaSmarks 
1092*5a5eeccaSmarks 	if (count < 0)
1093*5a5eeccaSmarks 		return (1);
1094*5a5eeccaSmarks 
1095*5a5eeccaSmarks 	if (positional) {
1096*5a5eeccaSmarks 		for (i = 0, pstr = permstr; i != count && pstr &&
1097*5a5eeccaSmarks 		    *pstr; i++, pstr++) {
1098*5a5eeccaSmarks 			if (*pstr == permtab[i].p_letter) {
1099*5a5eeccaSmarks 				perm_val |= permtab[i].p_value;
1100*5a5eeccaSmarks 			} else if (*pstr != '-') {
1101*5a5eeccaSmarks 				return (1);
1102*5a5eeccaSmarks 			}
1103*5a5eeccaSmarks 		}
1104*5a5eeccaSmarks 	} else {  /* random order single letters with no '-' */
1105*5a5eeccaSmarks 		for (pstr = permstr; pstr && *pstr; pstr++) {
1106*5a5eeccaSmarks 			for (found = 0, i = 0; i != count; i++) {
1107*5a5eeccaSmarks 				if (*pstr == permtab[i].p_letter) {
1108*5a5eeccaSmarks 					perm_val |= permtab[i].p_value;
1109*5a5eeccaSmarks 					found = 1;
1110*5a5eeccaSmarks 					break;
1111*5a5eeccaSmarks 				}
1112*5a5eeccaSmarks 			}
1113*5a5eeccaSmarks 			if (found == 0)
1114*5a5eeccaSmarks 				return (1);
1115*5a5eeccaSmarks 		}
1116*5a5eeccaSmarks 	}
1117*5a5eeccaSmarks 
1118*5a5eeccaSmarks 	*mask = perm_val;
1119*5a5eeccaSmarks 	return (0);
1120*5a5eeccaSmarks }
1121*5a5eeccaSmarks 
1122*5a5eeccaSmarks /*
1123*5a5eeccaSmarks  * compute value for inheritance flags.
1124*5a5eeccaSmarks  */
1125*5a5eeccaSmarks int
1126*5a5eeccaSmarks compute_ace_inherit(char *str, uint32_t *imask)
1127*5a5eeccaSmarks {
1128*5a5eeccaSmarks 	int error;
1129*5a5eeccaSmarks 	int positional = 0;
1130*5a5eeccaSmarks 
1131*5a5eeccaSmarks 	if (strlen(str) == IFLAG_COUNT)
1132*5a5eeccaSmarks 		positional = 1;
1133*5a5eeccaSmarks 
1134*5a5eeccaSmarks 	error = compute_values(inherit_table, IFLAG_COUNT,
1135*5a5eeccaSmarks 	    str, positional, imask);
1136*5a5eeccaSmarks 
1137*5a5eeccaSmarks 	if (error)
1138*5a5eeccaSmarks 		return (EACL_INHERIT_ERROR);
1139*5a5eeccaSmarks 
1140*5a5eeccaSmarks 	return (error);
1141*5a5eeccaSmarks }
1142*5a5eeccaSmarks 
1143*5a5eeccaSmarks 
1144*5a5eeccaSmarks /*
1145*5a5eeccaSmarks  * compute value for ACE permissions.
1146*5a5eeccaSmarks  */
1147*5a5eeccaSmarks int
1148*5a5eeccaSmarks compute_ace_perms(char *str, uint32_t *mask)
1149*5a5eeccaSmarks {
1150*5a5eeccaSmarks 	int positional = 0;
1151*5a5eeccaSmarks 	int error;
1152*5a5eeccaSmarks 
1153*5a5eeccaSmarks 	if (strlen(str) == ACE_PERM_COUNT)
1154*5a5eeccaSmarks 		positional = 1;
1155*5a5eeccaSmarks 
1156*5a5eeccaSmarks 	error = compute_values(ace_perm_table, ACE_PERM_COUNT,
1157*5a5eeccaSmarks 	    str, positional, mask);
1158*5a5eeccaSmarks 
1159*5a5eeccaSmarks 	if (error && positional) {
1160*5a5eeccaSmarks 		/*
1161*5a5eeccaSmarks 		 * If positional was set, then make sure permissions
1162*5a5eeccaSmarks 		 * aren't actually valid in non positional case where
1163*5a5eeccaSmarks 		 * all permissions are specified, just in random order.
1164*5a5eeccaSmarks 		 */
1165*5a5eeccaSmarks 		error = compute_values(ace_perm_table,
1166*5a5eeccaSmarks 		    ACE_PERM_COUNT, str, 0, mask);
1167*5a5eeccaSmarks 	}
1168*5a5eeccaSmarks 	if (error)
1169*5a5eeccaSmarks 		error = EACL_PERM_MASK_ERROR;
1170*5a5eeccaSmarks 
1171*5a5eeccaSmarks 	return (error);
1172*5a5eeccaSmarks }
1173*5a5eeccaSmarks 
1174*5a5eeccaSmarks 
1175*5a5eeccaSmarks 
1176*5a5eeccaSmarks /*
1177*5a5eeccaSmarks  * compute values for aclent permissions.
1178*5a5eeccaSmarks  */
1179*5a5eeccaSmarks int
1180*5a5eeccaSmarks compute_aclent_perms(char *str, o_mode_t *mask)
1181*5a5eeccaSmarks {
1182*5a5eeccaSmarks 	int error;
1183*5a5eeccaSmarks 	uint32_t pmask;
1184*5a5eeccaSmarks 
1185*5a5eeccaSmarks 	if (strlen(str) != ACLENT_PERM_COUNT)
1186*5a5eeccaSmarks 		return (EACL_PERM_MASK_ERROR);
1187*5a5eeccaSmarks 
1188*5a5eeccaSmarks 	*mask = 0;
1189*5a5eeccaSmarks 	error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT,
1190*5a5eeccaSmarks 	    str, 1, &pmask);
1191*5a5eeccaSmarks 	if (error == 0) {
1192*5a5eeccaSmarks 		*mask = (o_mode_t)pmask;
1193*5a5eeccaSmarks 	} else
1194*5a5eeccaSmarks 		error = EACL_PERM_MASK_ERROR;
1195*5a5eeccaSmarks 	return (error);
1196*5a5eeccaSmarks }
1197*5a5eeccaSmarks 
1198*5a5eeccaSmarks /*
1199*5a5eeccaSmarks  * determine ACE permissions.
1200*5a5eeccaSmarks  */
1201*5a5eeccaSmarks int
1202*5a5eeccaSmarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask)
1203*5a5eeccaSmarks {
1204*5a5eeccaSmarks 	int error;
1205*5a5eeccaSmarks 
1206*5a5eeccaSmarks 	if (aclperm->perm_style == PERM_TYPE_EMPTY) {
1207*5a5eeccaSmarks 		*mask = 0;
1208*5a5eeccaSmarks 		return (0);
1209*5a5eeccaSmarks 	}
1210*5a5eeccaSmarks 
1211*5a5eeccaSmarks 	if (aclperm->perm_style == PERM_TYPE_ACE) {
1212*5a5eeccaSmarks 		*mask = aclperm->perm_val;
1213*5a5eeccaSmarks 		return (0);
1214*5a5eeccaSmarks 	}
1215*5a5eeccaSmarks 
1216*5a5eeccaSmarks 	error = compute_ace_perms(aclperm->perm_str, mask);
1217*5a5eeccaSmarks 	if (error) {
1218*5a5eeccaSmarks 		acl_error(gettext("Invalid permission(s) '%s' specified\n"),
1219*5a5eeccaSmarks 		    aclperm->perm_str);
1220*5a5eeccaSmarks 		return (EACL_PERM_MASK_ERROR);
1221*5a5eeccaSmarks 	}
1222*5a5eeccaSmarks 
1223*5a5eeccaSmarks 	return (0);
1224*5a5eeccaSmarks }
1225