xref: /illumos-gate/usr/src/lib/libsec/common/acltext.c (revision fab57d1b)
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 /*
221fdeec65Sjoyce mcintosh  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
23*fab57d1bSGordon Ross  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <grp.h>
297c478bd9Sstevel@tonic-gate #include <pwd.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <limits.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
33fa9e4066Sahrens #include <errno.h>
347c478bd9Sstevel@tonic-gate #include <sys/param.h>
357c478bd9Sstevel@tonic-gate #include <sys/types.h>
365a5eeccaSmarks #include <sys/stat.h>
377c478bd9Sstevel@tonic-gate #include <sys/acl.h>
38fa9e4066Sahrens #include <aclutils.h>
39b249c65cSmarks #include <idmap.h>
409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <synch.h>
41fa9e4066Sahrens 
425a5eeccaSmarks #define	ID_STR_MAX	20	/* digits in LONG_MAX */
43fa9e4066Sahrens 
445a5eeccaSmarks #define	APPENDED_ID_MAX	ID_STR_MAX + 1		/* id + colon */
457c478bd9Sstevel@tonic-gate /*
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().
497c478bd9Sstevel@tonic-gate  */
505a5eeccaSmarks int	yyinteractive;
515a5eeccaSmarks acl_t	*yyacl;
525a5eeccaSmarks char	*yybuf;
539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_t	yymutex;
547c478bd9Sstevel@tonic-gate 
555a5eeccaSmarks extern acl_t *acl_alloc(enum acl_type);
567c478bd9Sstevel@tonic-gate 
57b249c65cSmarks /*
58b249c65cSmarks  * dynamic string that will increase in size on an
59b249c65cSmarks  * as needed basis.
60b249c65cSmarks  */
61b249c65cSmarks typedef struct dynaclstr {
62b249c65cSmarks 	size_t d_bufsize;		/* current size of aclexport */
63b249c65cSmarks 	char *d_aclexport;
64b249c65cSmarks 	int d_pos;
65b249c65cSmarks } dynaclstr_t;
6611e32170Shm 
67b249c65cSmarks static int str_append(dynaclstr_t *, char *);
68b249c65cSmarks static int aclent_perm_txt(dynaclstr_t *, o_mode_t);
697c478bd9Sstevel@tonic-gate 
705a5eeccaSmarks static void
aclent_perms(int perm,char * txt_perms)715a5eeccaSmarks aclent_perms(int perm, char *txt_perms)
72fa9e4066Sahrens {
735a5eeccaSmarks 	if (perm & S_IROTH)
745a5eeccaSmarks 		txt_perms[0] = 'r';
755a5eeccaSmarks 	else
765a5eeccaSmarks 		txt_perms[0] = '-';
775a5eeccaSmarks 	if (perm & S_IWOTH)
785a5eeccaSmarks 		txt_perms[1] = 'w';
795a5eeccaSmarks 	else
805a5eeccaSmarks 		txt_perms[1] = '-';
815a5eeccaSmarks 	if (perm & S_IXOTH)
825a5eeccaSmarks 		txt_perms[2] = 'x';
835a5eeccaSmarks 	else
845a5eeccaSmarks 		txt_perms[2] = '-';
855a5eeccaSmarks 	txt_perms[3] = '\0';
865a5eeccaSmarks }
87fa9e4066Sahrens 
885a5eeccaSmarks static char *
pruname(uid_t uid,char * uidp,size_t buflen,int noresolve)89afe1f701Smarks pruname(uid_t uid, char *uidp, size_t buflen, int noresolve)
905a5eeccaSmarks {
9145a17f45Sgjelinek 	struct passwd	*passwdp = NULL;
92fa9e4066Sahrens 
9345a17f45Sgjelinek 	if (noresolve == 0)
9445a17f45Sgjelinek 		passwdp = getpwuid(uid);
955a5eeccaSmarks 	if (passwdp == (struct passwd *)NULL) {
965a5eeccaSmarks 		/* could not get passwd information: display uid instead */
97f48205beScasper 		(void) snprintf(uidp, buflen, "%u", uid);
98afe1f701Smarks 	} else {
99afe1f701Smarks 		(void) strlcpy(uidp, passwdp->pw_name, buflen);
100afe1f701Smarks 	}
101afe1f701Smarks 	return (uidp);
1025a5eeccaSmarks }
103fa9e4066Sahrens 
1045a5eeccaSmarks static char *
prgname(gid_t gid,char * gidp,size_t buflen,int noresolve)105afe1f701Smarks prgname(gid_t gid, char *gidp, size_t buflen, int noresolve)
1065a5eeccaSmarks {
10745a17f45Sgjelinek 	struct group	*groupp = NULL;
108fa9e4066Sahrens 
10945a17f45Sgjelinek 	if (noresolve == 0)
11045a17f45Sgjelinek 		groupp = getgrgid(gid);
1115a5eeccaSmarks 	if (groupp == (struct group *)NULL) {
1125a5eeccaSmarks 		/* could not get group information: display gid instead */
113f48205beScasper 		(void) snprintf(gidp, buflen, "%u", gid);
114afe1f701Smarks 	} else {
115afe1f701Smarks 		(void) strlcpy(gidp, groupp->gr_name, buflen);
116afe1f701Smarks 	}
117afe1f701Smarks 	return (gidp);
1185a5eeccaSmarks }
119b249c65cSmarks 
120909c9a9fSMark Shellenbaum static int
getsidname(uid_t who,boolean_t user,char ** sidp,boolean_t noresolve)121909c9a9fSMark Shellenbaum getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve)
122b249c65cSmarks {
123b249c65cSmarks 	idmap_get_handle_t *get_hdl = NULL;
124b249c65cSmarks 	idmap_stat status;
125b249c65cSmarks 	idmap_rid_t rid;
126909c9a9fSMark Shellenbaum 	int error = IDMAP_ERR_NORESULT;
127b249c65cSmarks 	int len;
1289a2c8b2bSGowtham Thommandra 	char *domain = NULL;
129b249c65cSmarks 
130909c9a9fSMark Shellenbaum 	*sidp = NULL;
131b249c65cSmarks 
132b249c65cSmarks 	/*
133b249c65cSmarks 	 * First try and get windows name
134b249c65cSmarks 	 */
135b249c65cSmarks 
136909c9a9fSMark Shellenbaum 	if (!noresolve) {
137909c9a9fSMark Shellenbaum 		if (user)
138909c9a9fSMark Shellenbaum 			error = idmap_getwinnamebyuid(who,
1398ce3a038SMarcel Telka 			    IDMAP_REQ_FLG_USE_CACHE, sidp, NULL);
140909c9a9fSMark Shellenbaum 		else
141909c9a9fSMark Shellenbaum 			error = idmap_getwinnamebygid(who,
1428ce3a038SMarcel Telka 			    IDMAP_REQ_FLG_USE_CACHE, sidp, NULL);
143909c9a9fSMark Shellenbaum 	}
144909c9a9fSMark Shellenbaum 	if (error != IDMAP_SUCCESS) {
1451fdeec65Sjoyce mcintosh 		if (idmap_get_create(&get_hdl) == IDMAP_SUCCESS) {
146b249c65cSmarks 			if (user)
147b249c65cSmarks 				error = idmap_get_sidbyuid(get_hdl, who,
1483ee87bcaSJulian Pullen 				    IDMAP_REQ_FLG_USE_CACHE, &domain, &rid,
1493ee87bcaSJulian Pullen 				    &status);
150b249c65cSmarks 			else
151b249c65cSmarks 				error = idmap_get_sidbygid(get_hdl, who,
1523ee87bcaSJulian Pullen 				    IDMAP_REQ_FLG_USE_CACHE, &domain, &rid,
1533ee87bcaSJulian Pullen 				    &status);
154909c9a9fSMark Shellenbaum 			if (error == IDMAP_SUCCESS &&
155909c9a9fSMark Shellenbaum 			    idmap_get_mappings(get_hdl) == 0) {
156909c9a9fSMark Shellenbaum 				if (status == IDMAP_SUCCESS) {
157909c9a9fSMark Shellenbaum 					len = snprintf(NULL, 0,
158909c9a9fSMark Shellenbaum 					    "%s-%d", domain, rid);
159909c9a9fSMark Shellenbaum 					if (*sidp = malloc(len + 1)) {
160909c9a9fSMark Shellenbaum 						(void) snprintf(*sidp, len + 1,
161909c9a9fSMark Shellenbaum 						    "%s-%d", domain, rid);
162909c9a9fSMark Shellenbaum 					}
163909c9a9fSMark Shellenbaum 				}
164909c9a9fSMark Shellenbaum 			}
165b249c65cSmarks 		}
166b249c65cSmarks 		if (get_hdl)
167b249c65cSmarks 			idmap_get_destroy(get_hdl);
1689a2c8b2bSGowtham Thommandra 	}
1699a2c8b2bSGowtham Thommandra 
1708ce3a038SMarcel Telka 	free(domain);
1718ce3a038SMarcel Telka 
172909c9a9fSMark Shellenbaum 	return (*sidp ? 0 : 1);
173b249c65cSmarks }
174b249c65cSmarks 
175*fab57d1bSGordon Ross /*
176*fab57d1bSGordon Ross  * sid_string_by_id() is an exposed interface via -lsec
177*fab57d1bSGordon Ross  */
178*fab57d1bSGordon Ross int
sid_string_by_id(uid_t who,boolean_t user,char ** sidp,boolean_t noresolve)179*fab57d1bSGordon Ross sid_string_by_id(uid_t who, boolean_t user, char **sidp, boolean_t noresolve)
180*fab57d1bSGordon Ross {
181*fab57d1bSGordon Ross 	return (getsidname(who, user, sidp, noresolve));
182*fab57d1bSGordon Ross }
183*fab57d1bSGordon Ross 
1845a5eeccaSmarks static void
aclent_printacl(acl_t * aclp)1855a5eeccaSmarks aclent_printacl(acl_t *aclp)
1865a5eeccaSmarks {
1875a5eeccaSmarks 	aclent_t *tp;
1885a5eeccaSmarks 	int aclcnt;
1895a5eeccaSmarks 	int mask;
1905a5eeccaSmarks 	int slot = 0;
1915a5eeccaSmarks 	char perm[4];
192afe1f701Smarks 	char uidp[ID_STR_MAX];
193afe1f701Smarks 	char gidp[ID_STR_MAX];
1945a5eeccaSmarks 
1955a5eeccaSmarks 	/* display ACL: assume it is sorted. */
1965a5eeccaSmarks 	aclcnt = aclp->acl_cnt;
1975a5eeccaSmarks 	for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) {
1985a5eeccaSmarks 		if (tp->a_type == CLASS_OBJ)
1995a5eeccaSmarks 			mask = tp->a_perm;
2005a5eeccaSmarks 	}
2015a5eeccaSmarks 	aclcnt = aclp->acl_cnt;
2025a5eeccaSmarks 	for (tp = aclp->acl_aclp; aclcnt--; tp++) {
2035a5eeccaSmarks 		(void) printf("     %d:", slot++);
2045a5eeccaSmarks 		switch (tp->a_type) {
2055a5eeccaSmarks 		case USER:
2065a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2075a5eeccaSmarks 			(void) printf("user:%s:%s\t\t",
208afe1f701Smarks 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
2095a5eeccaSmarks 			aclent_perms((tp->a_perm & mask), perm);
2105a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
2115a5eeccaSmarks 			break;
2125a5eeccaSmarks 		case USER_OBJ:
2135a5eeccaSmarks 			/* no need to display uid */
2145a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2155a5eeccaSmarks 			(void) printf("user::%s\n", perm);
2165a5eeccaSmarks 			break;
2175a5eeccaSmarks 		case GROUP:
2185a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2195a5eeccaSmarks 			(void) printf("group:%s:%s\t\t",
220afe1f701Smarks 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
2215a5eeccaSmarks 			aclent_perms(tp->a_perm & mask, perm);
2225a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
2235a5eeccaSmarks 			break;
2245a5eeccaSmarks 		case GROUP_OBJ:
2255a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2265a5eeccaSmarks 			(void) printf("group::%s\t\t", perm);
2275a5eeccaSmarks 			aclent_perms(tp->a_perm & mask, perm);
2285a5eeccaSmarks 			(void) printf("#effective:%s\n", perm);
2295a5eeccaSmarks 			break;
2305a5eeccaSmarks 		case CLASS_OBJ:
2315a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2325a5eeccaSmarks 			(void) printf("mask:%s\n", perm);
2335a5eeccaSmarks 			break;
2345a5eeccaSmarks 		case OTHER_OBJ:
2355a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2365a5eeccaSmarks 			(void) printf("other:%s\n", perm);
2375a5eeccaSmarks 			break;
2385a5eeccaSmarks 		case DEF_USER:
2395a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2405a5eeccaSmarks 			(void) printf("default:user:%s:%s\n",
241afe1f701Smarks 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
2425a5eeccaSmarks 			break;
2435a5eeccaSmarks 		case DEF_USER_OBJ:
2445a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2455a5eeccaSmarks 			(void) printf("default:user::%s\n", perm);
2465a5eeccaSmarks 			break;
2475a5eeccaSmarks 		case DEF_GROUP:
2485a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2495a5eeccaSmarks 			(void) printf("default:group:%s:%s\n",
250afe1f701Smarks 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
2515a5eeccaSmarks 			break;
2525a5eeccaSmarks 		case DEF_GROUP_OBJ:
2535a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2545a5eeccaSmarks 			(void) printf("default:group::%s\n", perm);
2555a5eeccaSmarks 			break;
2565a5eeccaSmarks 		case DEF_CLASS_OBJ:
2575a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2585a5eeccaSmarks 			(void) printf("default:mask:%s\n", perm);
2595a5eeccaSmarks 			break;
2605a5eeccaSmarks 		case DEF_OTHER_OBJ:
2615a5eeccaSmarks 			aclent_perms(tp->a_perm, perm);
2625a5eeccaSmarks 			(void) printf("default:other:%s\n", perm);
2635a5eeccaSmarks 			break;
2645a5eeccaSmarks 		default:
2655a5eeccaSmarks 			(void) fprintf(stderr,
2665b233e2dSmarks 			    dgettext(TEXT_DOMAIN, "unrecognized entry\n"));
2675a5eeccaSmarks 			break;
2685a5eeccaSmarks 		}
2695a5eeccaSmarks 	}
2705a5eeccaSmarks }
2715a5eeccaSmarks 
2725a5eeccaSmarks static void
split_line(char * str,int cols)2735a5eeccaSmarks split_line(char *str, int cols)
2745a5eeccaSmarks {
2755a5eeccaSmarks 	char *ptr;
2765a5eeccaSmarks 	int len;
2775a5eeccaSmarks 	int i;
2785a5eeccaSmarks 	int last_split;
2795a5eeccaSmarks 	char *pad = "";
2805a5eeccaSmarks 	int pad_len;
2815a5eeccaSmarks 
2825a5eeccaSmarks 	len = strlen(str);
2835a5eeccaSmarks 	ptr = str;
2845a5eeccaSmarks 	pad_len = 0;
2855a5eeccaSmarks 
2865a5eeccaSmarks 	ptr = str;
2875a5eeccaSmarks 	last_split = 0;
2885a5eeccaSmarks 	for (i = 0; i != len; i++) {
2895a5eeccaSmarks 		if ((i + pad_len + 4) >= cols) {
2905a5eeccaSmarks 			(void) printf("%s%.*s\n", pad, last_split, ptr);
2915a5eeccaSmarks 			ptr = &ptr[last_split];
2925a5eeccaSmarks 			len = strlen(ptr);
2935a5eeccaSmarks 			i = 0;
2945a5eeccaSmarks 			pad_len = 4;
2955a5eeccaSmarks 			pad = "         ";
2965a5eeccaSmarks 		} else {
2975a5eeccaSmarks 			if (ptr[i] == '/' || ptr[i] == ':') {
2985a5eeccaSmarks 				last_split = i;
2995a5eeccaSmarks 			}
3005a5eeccaSmarks 		}
3015a5eeccaSmarks 	}
3025a5eeccaSmarks 	if (i == len) {
3035a5eeccaSmarks 		(void) printf("%s%s\n", pad, ptr);
3045a5eeccaSmarks 	}
3055a5eeccaSmarks }
3065a5eeccaSmarks 
307b249c65cSmarks /*
308b249c65cSmarks  * compute entry type string, such as user:joe, group:staff,...
309b249c65cSmarks  */
310b249c65cSmarks static int
aclent_type_txt(dynaclstr_t * dstr,aclent_t * aclp,int flags)311b249c65cSmarks aclent_type_txt(dynaclstr_t *dstr, aclent_t *aclp, int flags)
3125a5eeccaSmarks {
313afe1f701Smarks 	char idp[ID_STR_MAX];
314b249c65cSmarks 	int error;
3155a5eeccaSmarks 
316b249c65cSmarks 	switch (aclp->a_type) {
317b249c65cSmarks 	case DEF_USER_OBJ:
318b249c65cSmarks 	case USER_OBJ:
319b249c65cSmarks 		if (aclp->a_type == USER_OBJ)
320b249c65cSmarks 			error = str_append(dstr, "user::");
321b249c65cSmarks 		else
322b249c65cSmarks 			error = str_append(dstr, "defaultuser::");
323b249c65cSmarks 		break;
324b249c65cSmarks 
325b249c65cSmarks 	case DEF_USER:
326b249c65cSmarks 	case USER:
327b249c65cSmarks 		if (aclp->a_type == USER)
328b249c65cSmarks 			error = str_append(dstr, "user:");
329b249c65cSmarks 		else
330b249c65cSmarks 			error = str_append(dstr, "defaultuser:");
331b249c65cSmarks 		if (error)
332b249c65cSmarks 			break;
333b249c65cSmarks 		error = str_append(dstr, pruname(aclp->a_id, idp,
334b249c65cSmarks 		    sizeof (idp), flags & ACL_NORESOLVE));
335b249c65cSmarks 		if (error == 0)
336b249c65cSmarks 			error = str_append(dstr, ":");
337b249c65cSmarks 		break;
338b249c65cSmarks 
339b249c65cSmarks 	case DEF_GROUP_OBJ:
340b249c65cSmarks 	case GROUP_OBJ:
341b249c65cSmarks 		if (aclp->a_type == GROUP_OBJ)
342b249c65cSmarks 			error = str_append(dstr, "group::");
343b249c65cSmarks 		else
344b249c65cSmarks 			error = str_append(dstr, "defaultgroup::");
345b249c65cSmarks 		break;
346b249c65cSmarks 
347b249c65cSmarks 	case DEF_GROUP:
348b249c65cSmarks 	case GROUP:
349b249c65cSmarks 		if (aclp->a_type == GROUP)
350b249c65cSmarks 			error = str_append(dstr, "group:");
351b249c65cSmarks 		else
352b249c65cSmarks 			error = str_append(dstr, "defaultgroup:");
353b249c65cSmarks 		if (error)
354b249c65cSmarks 			break;
355b249c65cSmarks 		error = str_append(dstr, prgname(aclp->a_id, idp,
356b249c65cSmarks 		    sizeof (idp), flags & ACL_NORESOLVE));
357b249c65cSmarks 		if (error == 0)
358b249c65cSmarks 			error = str_append(dstr, ":");
359b249c65cSmarks 		break;
360b249c65cSmarks 
361b249c65cSmarks 	case DEF_CLASS_OBJ:
362b249c65cSmarks 	case CLASS_OBJ:
363b249c65cSmarks 		if (aclp->a_type == CLASS_OBJ)
364b249c65cSmarks 			error = str_append(dstr, "mask:");
365b249c65cSmarks 		else
366b249c65cSmarks 			error = str_append(dstr, "defaultmask:");
367b249c65cSmarks 		break;
368b249c65cSmarks 
369b249c65cSmarks 	case DEF_OTHER_OBJ:
370b249c65cSmarks 	case OTHER_OBJ:
371b249c65cSmarks 		if (aclp->a_type == OTHER_OBJ)
372b249c65cSmarks 			error = str_append(dstr, "other:");
373b249c65cSmarks 		else
374b249c65cSmarks 			error = str_append(dstr, "defaultother:");
375b249c65cSmarks 		break;
376b249c65cSmarks 
377b249c65cSmarks 	default:
378b249c65cSmarks 		error = 1;
379b249c65cSmarks 		break;
380b249c65cSmarks 	}
381b249c65cSmarks 
382b249c65cSmarks 	return (error);
383b249c65cSmarks }
384b249c65cSmarks 
385b249c65cSmarks /*
386b249c65cSmarks  * compute entry type string such as, owner@:, user:joe, group:staff,...
387b249c65cSmarks  */
388b249c65cSmarks static int
ace_type_txt(dynaclstr_t * dynstr,ace_t * acep,int flags)389b249c65cSmarks ace_type_txt(dynaclstr_t *dynstr, ace_t *acep, int flags)
390b249c65cSmarks {
391b249c65cSmarks 	char idp[ID_STR_MAX];
392b249c65cSmarks 	int error;
393b249c65cSmarks 	char *sidp = NULL;
3945a5eeccaSmarks 
3955a5eeccaSmarks 	switch (acep->a_flags & ACE_TYPE_FLAGS) {
3965a5eeccaSmarks 	case ACE_OWNER:
397b249c65cSmarks 		error = str_append(dynstr, OWNERAT_TXT);
3985a5eeccaSmarks 		break;
3995a5eeccaSmarks 
4005a5eeccaSmarks 	case ACE_GROUP|ACE_IDENTIFIER_GROUP:
401b249c65cSmarks 		error = str_append(dynstr, GROUPAT_TXT);
4025a5eeccaSmarks 		break;
4035a5eeccaSmarks 
4045a5eeccaSmarks 	case ACE_IDENTIFIER_GROUP:
405b249c65cSmarks 		if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) {
406b249c65cSmarks 			if (error = str_append(dynstr,
407b249c65cSmarks 			    GROUPSID_TXT))
408b249c65cSmarks 				break;
409909c9a9fSMark Shellenbaum 			if (error = getsidname(acep->a_who, B_FALSE,
410909c9a9fSMark Shellenbaum 			    &sidp, flags & ACL_NORESOLVE))
411909c9a9fSMark Shellenbaum 				break;
412909c9a9fSMark Shellenbaum 			error = str_append(dynstr, sidp);
413b249c65cSmarks 		} else {
414b249c65cSmarks 			if (error = str_append(dynstr, GROUP_TXT))
415b249c65cSmarks 				break;
416b249c65cSmarks 			error = str_append(dynstr, prgname(acep->a_who, idp,
417b249c65cSmarks 			    sizeof (idp), flags & ACL_NORESOLVE));
418b249c65cSmarks 		}
419b249c65cSmarks 		if (error == 0)
420b249c65cSmarks 			error = str_append(dynstr, ":");
4215a5eeccaSmarks 		break;
4225a5eeccaSmarks 
4235a5eeccaSmarks 	case ACE_EVERYONE:
424b249c65cSmarks 		error = str_append(dynstr, EVERYONEAT_TXT);
4255a5eeccaSmarks 		break;
4265a5eeccaSmarks 
4275a5eeccaSmarks 	case 0:
428b249c65cSmarks 		if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) {
429b249c65cSmarks 			if (error = str_append(dynstr, USERSID_TXT))
430b249c65cSmarks 				break;
431909c9a9fSMark Shellenbaum 			if (error = getsidname(acep->a_who, B_TRUE,
432909c9a9fSMark Shellenbaum 			    &sidp, flags & ACL_NORESOLVE))
433909c9a9fSMark Shellenbaum 				break;
434909c9a9fSMark Shellenbaum 			error = str_append(dynstr, sidp);
435b249c65cSmarks 		} else {
436b249c65cSmarks 			if (error = str_append(dynstr, USER_TXT))
437b249c65cSmarks 				break;
438b249c65cSmarks 			error = str_append(dynstr, pruname(acep->a_who, idp,
439b249c65cSmarks 			    sizeof (idp), flags & ACL_NORESOLVE));
440b249c65cSmarks 		}
441b249c65cSmarks 		if (error == 0)
442b249c65cSmarks 			error = str_append(dynstr, ":");
443b249c65cSmarks 		break;
444b249c65cSmarks 	default:
445b249c65cSmarks 		error = 0;
4465a5eeccaSmarks 		break;
4475a5eeccaSmarks 	}
4485a5eeccaSmarks 
449b249c65cSmarks 	if (sidp)
450b249c65cSmarks 		free(sidp);
451b249c65cSmarks 	return (error);
4525a5eeccaSmarks }
4535a5eeccaSmarks 
454b249c65cSmarks /*
455b249c65cSmarks  * compute string of permissions, such as read_data/write_data or
456b249c65cSmarks  * rwxp,...
457b249c65cSmarks  * The format depends on the flags field which indicates whether the compact
458b249c65cSmarks  * or verbose format should be used.
459b249c65cSmarks  */
460b249c65cSmarks static int
ace_perm_txt(dynaclstr_t * dstr,uint32_t mask,uint32_t iflags,int isdir,int flags)461b249c65cSmarks ace_perm_txt(dynaclstr_t *dstr, uint32_t mask,
4625a5eeccaSmarks     uint32_t iflags, int isdir, int flags)
4635a5eeccaSmarks {
464b249c65cSmarks 	int error = 0;
4655a5eeccaSmarks 
4665a5eeccaSmarks 	if (flags & ACL_COMPACT_FMT) {
467b249c65cSmarks 		char buf[16];
4685a5eeccaSmarks 
4695a5eeccaSmarks 		if (mask & ACE_READ_DATA)
4705a5eeccaSmarks 			buf[0] = 'r';
4715a5eeccaSmarks 		else
4725a5eeccaSmarks 			buf[0] = '-';
4735a5eeccaSmarks 		if (mask & ACE_WRITE_DATA)
4745a5eeccaSmarks 			buf[1] = 'w';
4755a5eeccaSmarks 		else
4765a5eeccaSmarks 			buf[1] = '-';
4775a5eeccaSmarks 		if (mask & ACE_EXECUTE)
4785a5eeccaSmarks 			buf[2] = 'x';
4795a5eeccaSmarks 		else
4805a5eeccaSmarks 			buf[2] = '-';
4815a5eeccaSmarks 		if (mask & ACE_APPEND_DATA)
4825a5eeccaSmarks 			buf[3] = 'p';
4835a5eeccaSmarks 		else
4845a5eeccaSmarks 			buf[3] = '-';
4855a5eeccaSmarks 		if (mask & ACE_DELETE)
4865a5eeccaSmarks 			buf[4] = 'd';
4875a5eeccaSmarks 		else
4885a5eeccaSmarks 			buf[4] = '-';
4895a5eeccaSmarks 		if (mask & ACE_DELETE_CHILD)
4905a5eeccaSmarks 			buf[5] = 'D';
4915a5eeccaSmarks 		else
4925a5eeccaSmarks 			buf[5] = '-';
4935a5eeccaSmarks 		if (mask & ACE_READ_ATTRIBUTES)
4945a5eeccaSmarks 			buf[6] = 'a';
4955a5eeccaSmarks 		else
4965a5eeccaSmarks 			buf[6] = '-';
4975a5eeccaSmarks 		if (mask & ACE_WRITE_ATTRIBUTES)
4985a5eeccaSmarks 			buf[7] = 'A';
4995a5eeccaSmarks 		else
5005a5eeccaSmarks 			buf[7] = '-';
5015a5eeccaSmarks 		if (mask & ACE_READ_NAMED_ATTRS)
5025a5eeccaSmarks 			buf[8] = 'R';
5035a5eeccaSmarks 		else
5045a5eeccaSmarks 			buf[8] = '-';
5055a5eeccaSmarks 		if (mask & ACE_WRITE_NAMED_ATTRS)
5065a5eeccaSmarks 			buf[9] = 'W';
5075a5eeccaSmarks 		else
5085a5eeccaSmarks 			buf[9] = '-';
5095a5eeccaSmarks 		if (mask & ACE_READ_ACL)
5105a5eeccaSmarks 			buf[10] = 'c';
5115a5eeccaSmarks 		else
5125a5eeccaSmarks 			buf[10] = '-';
5135a5eeccaSmarks 		if (mask & ACE_WRITE_ACL)
5145a5eeccaSmarks 			buf[11] = 'C';
5155a5eeccaSmarks 		else
5165a5eeccaSmarks 			buf[11] = '-';
5175a5eeccaSmarks 		if (mask & ACE_WRITE_OWNER)
5185a5eeccaSmarks 			buf[12] = 'o';
5195a5eeccaSmarks 		else
5205a5eeccaSmarks 			buf[12] = '-';
5215a5eeccaSmarks 		if (mask & ACE_SYNCHRONIZE)
5225a5eeccaSmarks 			buf[13] = 's';
5235a5eeccaSmarks 		else
5245a5eeccaSmarks 			buf[13] = '-';
525b249c65cSmarks 		buf[14] = ':';
526b249c65cSmarks 		buf[15] = '\0';
527b249c65cSmarks 		error = str_append(dstr, buf);
5285a5eeccaSmarks 	} else {
5295a5eeccaSmarks 		/*
5305a5eeccaSmarks 		 * If ACE is a directory, but inheritance indicates its
5315a5eeccaSmarks 		 * for a file then print permissions for file rather than
5325a5eeccaSmarks 		 * dir.
5335a5eeccaSmarks 		 */
5345a5eeccaSmarks 		if (isdir) {
5355a5eeccaSmarks 			if (mask & ACE_LIST_DIRECTORY) {
5365a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
537b249c65cSmarks 					error = str_append(dstr,
538b249c65cSmarks 					    READ_DATA_TXT);
5395a5eeccaSmarks 				} else {
540b249c65cSmarks 					error =
541b249c65cSmarks 					    str_append(dstr, READ_DIR_TXT);
5425a5eeccaSmarks 				}
5435a5eeccaSmarks 			}
544b249c65cSmarks 			if (error == 0 && (mask & ACE_ADD_FILE)) {
5455a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
546b249c65cSmarks 					error =
547b249c65cSmarks 					    str_append(dstr, WRITE_DATA_TXT);
5485a5eeccaSmarks 				} else {
549b249c65cSmarks 					error =
550b249c65cSmarks 					    str_append(dstr, ADD_FILE_TXT);
5515a5eeccaSmarks 				}
5525a5eeccaSmarks 			}
553b249c65cSmarks 			if (error == 0 && (mask & ACE_ADD_SUBDIRECTORY)) {
5545a5eeccaSmarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
555b249c65cSmarks 					error = str_append(dstr,
556b249c65cSmarks 					    APPEND_DATA_TXT);
5575a5eeccaSmarks 				} else {
558b249c65cSmarks 					error = str_append(dstr,
559b249c65cSmarks 					    ADD_DIR_TXT);
5605a5eeccaSmarks 				}
5615a5eeccaSmarks 			}
5625a5eeccaSmarks 		} else {
5635a5eeccaSmarks 			if (mask & ACE_READ_DATA) {
564b249c65cSmarks 				error = str_append(dstr, READ_DATA_TXT);
5655a5eeccaSmarks 			}
566b249c65cSmarks 			if (error == 0 && (mask & ACE_WRITE_DATA)) {
567b249c65cSmarks 				error = str_append(dstr, WRITE_DATA_TXT);
5685a5eeccaSmarks 			}
569b249c65cSmarks 			if (error == 0 && (mask & ACE_APPEND_DATA)) {
570b249c65cSmarks 				error = str_append(dstr, APPEND_DATA_TXT);
5715a5eeccaSmarks 			}
5725a5eeccaSmarks 		}
573b249c65cSmarks 		if (error == 0 && (mask & ACE_READ_NAMED_ATTRS)) {
574b249c65cSmarks 			error = str_append(dstr, READ_XATTR_TXT);
5755a5eeccaSmarks 		}
576b249c65cSmarks 		if (error == 0 && (mask & ACE_WRITE_NAMED_ATTRS)) {
577b249c65cSmarks 			error = str_append(dstr, WRITE_XATTR_TXT);
5785a5eeccaSmarks 		}
579b249c65cSmarks 		if (error == 0 && (mask & ACE_EXECUTE)) {
580b249c65cSmarks 			error = str_append(dstr, EXECUTE_TXT);
5815a5eeccaSmarks 		}
582b249c65cSmarks 		if (error == 0 && (mask & ACE_DELETE_CHILD)) {
583b249c65cSmarks 			error = str_append(dstr, DELETE_CHILD_TXT);
5845a5eeccaSmarks 		}
585b249c65cSmarks 		if (error == 0 && (mask & ACE_READ_ATTRIBUTES)) {
586b249c65cSmarks 			error = str_append(dstr, READ_ATTRIBUTES_TXT);
5875a5eeccaSmarks 		}
588b249c65cSmarks 		if (error == 0 && (mask & ACE_WRITE_ATTRIBUTES)) {
589b249c65cSmarks 			error = str_append(dstr, WRITE_ATTRIBUTES_TXT);
5905a5eeccaSmarks 		}
591b249c65cSmarks 		if (error == 0 && (mask & ACE_DELETE)) {
592b249c65cSmarks 			error = str_append(dstr, DELETE_TXT);
5935a5eeccaSmarks 		}
594b249c65cSmarks 		if (error == 0 && (mask & ACE_READ_ACL)) {
595b249c65cSmarks 			error = str_append(dstr, READ_ACL_TXT);
5965a5eeccaSmarks 		}
597b249c65cSmarks 		if (error == 0 && (mask & ACE_WRITE_ACL)) {
598b249c65cSmarks 			error = str_append(dstr, WRITE_ACL_TXT);
5995a5eeccaSmarks 		}
600b249c65cSmarks 		if (error == 0 && (mask & ACE_WRITE_OWNER)) {
601b249c65cSmarks 			error = str_append(dstr, WRITE_OWNER_TXT);
6025a5eeccaSmarks 		}
603b249c65cSmarks 		if (error == 0 && (mask & ACE_SYNCHRONIZE)) {
604b249c65cSmarks 			error = str_append(dstr, SYNCHRONIZE_TXT);
6055a5eeccaSmarks 		}
606b249c65cSmarks 		if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') {
607b249c65cSmarks 			dstr->d_aclexport[--dstr->d_pos] = '\0';
608b249c65cSmarks 		}
609b249c65cSmarks 		if (error == 0)
610b249c65cSmarks 			error = str_append(dstr, ":");
6115a5eeccaSmarks 	}
612b249c65cSmarks 	return (error);
6135a5eeccaSmarks }
6145a5eeccaSmarks 
615b249c65cSmarks /*
616b249c65cSmarks  * compute string of access type, such as allow, deny, ...
617b249c65cSmarks  */
618b249c65cSmarks static int
ace_access_txt(dynaclstr_t * dstr,int type)619b249c65cSmarks ace_access_txt(dynaclstr_t *dstr, int type)
6205a5eeccaSmarks {
621b249c65cSmarks 	int error;
6225a5eeccaSmarks 
623b249c65cSmarks 	if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
624b249c65cSmarks 		error = str_append(dstr, ALLOW_TXT);
625b249c65cSmarks 	else if (type == ACE_ACCESS_DENIED_ACE_TYPE)
626b249c65cSmarks 		error = str_append(dstr, DENY_TXT);
627b249c65cSmarks 	else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE)
628b249c65cSmarks 		error = str_append(dstr, AUDIT_TXT);
629b249c65cSmarks 	else if (type == ACE_SYSTEM_ALARM_ACE_TYPE)
630b249c65cSmarks 		error = str_append(dstr, ALARM_TXT);
631b249c65cSmarks 	else
632b249c65cSmarks 		error = str_append(dstr, UNKNOWN_TXT);
6335a5eeccaSmarks 
634b249c65cSmarks 	return (error);
6355a5eeccaSmarks }
6365a5eeccaSmarks 
637b249c65cSmarks static int
ace_inherit_txt(dynaclstr_t * dstr,uint32_t iflags,int flags)638b249c65cSmarks ace_inherit_txt(dynaclstr_t *dstr, uint32_t iflags, int flags)
6395a5eeccaSmarks {
640b249c65cSmarks 	int error = 0;
6415a5eeccaSmarks 
6425a5eeccaSmarks 	if (flags & ACL_COMPACT_FMT) {
643b249c65cSmarks 		char buf[9];
644b249c65cSmarks 
6455a5eeccaSmarks 		if (iflags & ACE_FILE_INHERIT_ACE)
6465a5eeccaSmarks 			buf[0] = 'f';
6475a5eeccaSmarks 		else
6485a5eeccaSmarks 			buf[0] = '-';
6495a5eeccaSmarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE)
6505a5eeccaSmarks 			buf[1] = 'd';
6515a5eeccaSmarks 		else
6525a5eeccaSmarks 			buf[1] = '-';
6535a5eeccaSmarks 		if (iflags & ACE_INHERIT_ONLY_ACE)
6545a5eeccaSmarks 			buf[2] = 'i';
6555a5eeccaSmarks 		else
6565a5eeccaSmarks 			buf[2] = '-';
6575a5eeccaSmarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)
6585a5eeccaSmarks 			buf[3] = 'n';
6595a5eeccaSmarks 		else
6605a5eeccaSmarks 			buf[3] = '-';
6615a5eeccaSmarks 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
6625a5eeccaSmarks 			buf[4] = 'S';
6635a5eeccaSmarks 		else
6645a5eeccaSmarks 			buf[4] = '-';
6655a5eeccaSmarks 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG)
6665a5eeccaSmarks 			buf[5] = 'F';
6675a5eeccaSmarks 		else
6685a5eeccaSmarks 			buf[5] = '-';
669da6c28aaSamw 		if (iflags & ACE_INHERITED_ACE)
670da6c28aaSamw 			buf[6] = 'I';
671da6c28aaSamw 		else
672da6c28aaSamw 			buf[6] = '-';
673b249c65cSmarks 		buf[7] = ':';
674b249c65cSmarks 		buf[8] = '\0';
675b249c65cSmarks 		error = str_append(dstr, buf);
6765a5eeccaSmarks 	} else {
6775a5eeccaSmarks 		if (iflags & ACE_FILE_INHERIT_ACE) {
678b249c65cSmarks 			error = str_append(dstr, FILE_INHERIT_TXT);
6795a5eeccaSmarks 		}
680b249c65cSmarks 		if (error == 0 && (iflags & ACE_DIRECTORY_INHERIT_ACE)) {
681b249c65cSmarks 			error = str_append(dstr, DIR_INHERIT_TXT);
6825a5eeccaSmarks 		}
683b249c65cSmarks 		if (error == 0 && (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) {
684b249c65cSmarks 			error = str_append(dstr, NO_PROPAGATE_TXT);
6855a5eeccaSmarks 		}
686b249c65cSmarks 		if (error == 0 && (iflags & ACE_INHERIT_ONLY_ACE)) {
687b249c65cSmarks 			error = str_append(dstr, INHERIT_ONLY_TXT);
6885a5eeccaSmarks 		}
689b249c65cSmarks 		if (error == 0 && (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)) {
690b249c65cSmarks 			error = str_append(dstr, SUCCESSFUL_ACCESS_TXT);
691da6c28aaSamw 		}
692b249c65cSmarks 		if (error == 0 && (iflags & ACE_FAILED_ACCESS_ACE_FLAG)) {
693b249c65cSmarks 			error = str_append(dstr, FAILED_ACCESS_TXT);
694da6c28aaSamw 		}
695b249c65cSmarks 		if (error == 0 && (iflags & ACE_INHERITED_ACE)) {
696b249c65cSmarks 			error = str_append(dstr, INHERITED_ACE_TXT);
697b249c65cSmarks 		}
698b249c65cSmarks 		if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') {
699b249c65cSmarks 			dstr->d_aclexport[--dstr->d_pos] = '\0';
700b249c65cSmarks 			error = str_append(dstr, ":");
701da6c28aaSamw 		}
7025a5eeccaSmarks 	}
7035a5eeccaSmarks 
704b249c65cSmarks 	return (error);
705fa9e4066Sahrens }
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate /*
7087c478bd9Sstevel@tonic-gate  * Convert internal acl representation to external representation.
7097c478bd9Sstevel@tonic-gate  *
7107c478bd9Sstevel@tonic-gate  * The length of a non-owning user name or non-owning group name ie entries
7117c478bd9Sstevel@tonic-gate  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
7127c478bd9Sstevel@tonic-gate  * thus check the length of these entries, and if greater than LOGNAME_MAX,
7137c478bd9Sstevel@tonic-gate  * we realloc() via increase_length().
7147c478bd9Sstevel@tonic-gate  *
7157c478bd9Sstevel@tonic-gate  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
7167c478bd9Sstevel@tonic-gate  * adhered to.
7177c478bd9Sstevel@tonic-gate  */
7185a5eeccaSmarks 
7195a5eeccaSmarks /*
7205a5eeccaSmarks  * acltotext() converts each ACL entry to look like this:
7215a5eeccaSmarks  *
7225a5eeccaSmarks  *    entry_type:uid^gid^name:perms[:id]
7235a5eeccaSmarks  *
7245a5eeccaSmarks  * The maximum length of entry_type is 14 ("defaultgroup::" and
7255a5eeccaSmarks  * "defaultother::") hence ENTRYTYPELEN is set to 14.
7265a5eeccaSmarks  *
7275a5eeccaSmarks  * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
7285a5eeccaSmarks  * however the ID could be a number so we therefore use ID_STR_MAX
7295a5eeccaSmarks  *
7305a5eeccaSmarks  * The length of a perms entry is 4 to allow for the comma appended to each
7315a5eeccaSmarks  * to each acl entry.  Hence PERMS is set to 4.
7325a5eeccaSmarks  */
7335a5eeccaSmarks 
7345a5eeccaSmarks #define	ENTRYTYPELEN	14
7355a5eeccaSmarks #define	PERMS		4
7365a5eeccaSmarks #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
7375a5eeccaSmarks 
7387c478bd9Sstevel@tonic-gate char *
aclent_acltotext(aclent_t * aclp,int aclcnt,int flags)7395a5eeccaSmarks aclent_acltotext(aclent_t  *aclp, int aclcnt, int flags)
7407c478bd9Sstevel@tonic-gate {
741*fab57d1bSGordon Ross 	dynaclstr_t	*dstr;
742909c9a9fSMark Shellenbaum 	char		*aclexport = NULL;
743b249c65cSmarks 	int		i;
744*fab57d1bSGordon Ross 	int		error = 0;
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	if (aclp == NULL)
7477c478bd9Sstevel@tonic-gate 		return (NULL);
748b249c65cSmarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
7497c478bd9Sstevel@tonic-gate 		return (NULL);
750b249c65cSmarks 	dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE;
751b249c65cSmarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
7527c478bd9Sstevel@tonic-gate 		free(dstr);
7537c478bd9Sstevel@tonic-gate 		return (NULL);
7547c478bd9Sstevel@tonic-gate 	}
755b249c65cSmarks 	*dstr->d_aclexport = '\0';
756b249c65cSmarks 	dstr->d_pos = 0;
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	for (i = 0; i < aclcnt; i++, aclp++) {
759b249c65cSmarks 		if (error = aclent_type_txt(dstr, aclp, flags))
7607c478bd9Sstevel@tonic-gate 			break;
761b249c65cSmarks 		if (error = aclent_perm_txt(dstr, aclp->a_perm))
7627c478bd9Sstevel@tonic-gate 			break;
7635a5eeccaSmarks 
7645a5eeccaSmarks 		if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) ||
7655a5eeccaSmarks 		    (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) ||
7665a5eeccaSmarks 		    (aclp->a_type == DEF_GROUP))) {
767b249c65cSmarks 			char id[ID_STR_MAX], *idstr;
768b249c65cSmarks 
769b249c65cSmarks 			if (error = str_append(dstr, ":"))
770b249c65cSmarks 				break;
7715a5eeccaSmarks 			id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */
7725a5eeccaSmarks 			idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]);
773b249c65cSmarks 			if (error = str_append(dstr, idstr))
774b249c65cSmarks 				break;
7755a5eeccaSmarks 		}
7767c478bd9Sstevel@tonic-gate 		if (i < aclcnt - 1)
777b249c65cSmarks 			if (error = str_append(dstr, ","))
778b249c65cSmarks 				break;
779b249c65cSmarks 	}
780b249c65cSmarks 	if (error) {
781b249c65cSmarks 		if (dstr->d_aclexport)
782b249c65cSmarks 			free(dstr->d_aclexport);
783b249c65cSmarks 	} else {
784b249c65cSmarks 		aclexport = dstr->d_aclexport;
7857c478bd9Sstevel@tonic-gate 	}
7867c478bd9Sstevel@tonic-gate 	free(dstr);
7877c478bd9Sstevel@tonic-gate 	return (aclexport);
7885a5eeccaSmarks }
7897c478bd9Sstevel@tonic-gate 
7905a5eeccaSmarks char *
acltotext(aclent_t * aclp,int aclcnt)7915a5eeccaSmarks acltotext(aclent_t *aclp, int aclcnt)
7925a5eeccaSmarks {
7935a5eeccaSmarks 	return (aclent_acltotext(aclp, aclcnt, 0));
794fa9e4066Sahrens }
795fa9e4066Sahrens 
7965a5eeccaSmarks 
797fa9e4066Sahrens aclent_t *
aclfromtext(char * aclstr,int * aclcnt)798fa9e4066Sahrens aclfromtext(char *aclstr, int *aclcnt)
799fa9e4066Sahrens {
800fa9e4066Sahrens 	acl_t *aclp;
801fa9e4066Sahrens 	aclent_t *aclentp;
802fa9e4066Sahrens 	int error;
803fa9e4066Sahrens 
8045a5eeccaSmarks 	error = acl_fromtext(aclstr, &aclp);
805fa9e4066Sahrens 	if (error)
806fa9e4066Sahrens 		return (NULL);
807fa9e4066Sahrens 
808fa9e4066Sahrens 	aclentp = aclp->acl_aclp;
809fa9e4066Sahrens 	aclp->acl_aclp = NULL;
810fa9e4066Sahrens 	*aclcnt = aclp->acl_cnt;
8115a5eeccaSmarks 
8125a5eeccaSmarks 	acl_free(aclp);
813fa9e4066Sahrens 	return (aclentp);
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate 
816fa9e4066Sahrens 
817b249c65cSmarks /*
818909c9a9fSMark Shellenbaum  * Append string onto dynaclstr_t.
819909c9a9fSMark Shellenbaum  *
820909c9a9fSMark Shellenbaum  * Return 0 on success, 1 for failure.
821b249c65cSmarks  */
822b249c65cSmarks static int
str_append(dynaclstr_t * dstr,char * newstr)823b249c65cSmarks str_append(dynaclstr_t *dstr, char *newstr)
8247c478bd9Sstevel@tonic-gate {
825b249c65cSmarks 	size_t len = strlen(newstr);
826b249c65cSmarks 
827b249c65cSmarks 	if ((len + dstr->d_pos) >= dstr->d_bufsize) {
828b249c65cSmarks 		dstr->d_aclexport = realloc(dstr->d_aclexport,
829b249c65cSmarks 		    dstr->d_bufsize + len + 1);
830b249c65cSmarks 		if (dstr->d_aclexport == NULL)
831b249c65cSmarks 			return (1);
832b249c65cSmarks 		dstr->d_bufsize += len;
833b249c65cSmarks 	}
834b249c65cSmarks 	(void) strcat(&dstr->d_aclexport[dstr->d_pos], newstr);
835b249c65cSmarks 	dstr->d_pos += len;
836b249c65cSmarks 	return (0);
8377c478bd9Sstevel@tonic-gate }
8387c478bd9Sstevel@tonic-gate 
839b249c65cSmarks static int
aclent_perm_txt(dynaclstr_t * dstr,o_mode_t perm)840b249c65cSmarks aclent_perm_txt(dynaclstr_t *dstr, o_mode_t perm)
8417c478bd9Sstevel@tonic-gate {
842b249c65cSmarks 	char buf[4];
843b249c65cSmarks 
8445a5eeccaSmarks 	if (perm & S_IROTH)
845b249c65cSmarks 		buf[0] = 'r';
8467c478bd9Sstevel@tonic-gate 	else
847b249c65cSmarks 		buf[0] = '-';
8485a5eeccaSmarks 	if (perm & S_IWOTH)
849b249c65cSmarks 		buf[1] = 'w';
8507c478bd9Sstevel@tonic-gate 	else
851b249c65cSmarks 		buf[1] = '-';
8525a5eeccaSmarks 	if (perm & S_IXOTH)
853b249c65cSmarks 		buf[2] = 'x';
8547c478bd9Sstevel@tonic-gate 	else
855b249c65cSmarks 		buf[2] = '-';
856b249c65cSmarks 	buf[3] = '\0';
857b249c65cSmarks 	return (str_append(dstr, buf));
8587c478bd9Sstevel@tonic-gate }
859fa9e4066Sahrens 
860fa9e4066Sahrens /*
8615a5eeccaSmarks  * ace_acltotext() convert each ace formatted acl to look like this:
862fa9e4066Sahrens  *
8635a5eeccaSmarks  * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
864fa9e4066Sahrens  *
865fa9e4066Sahrens  * The maximum length of entry_type is 5 ("group")
866fa9e4066Sahrens  *
8675a5eeccaSmarks  * The max length of a uid^gid^name entry (in theory) is 8,
8685a5eeccaSmarks  * however id could be a number so we therefore use ID_STR_MAX
869fa9e4066Sahrens  *
870fa9e4066Sahrens  * The length of a perms entry is 144 i.e read_data/write_data...
871fa9e4066Sahrens  * to each acl entry.
872fa9e4066Sahrens  *
873da6c28aaSamw  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access
874da6c28aaSamw  *         /failed_access
875fa9e4066Sahrens  *
876fa9e4066Sahrens  */
877fa9e4066Sahrens 
878fa9e4066Sahrens #define	ACE_ENTRYTYPLEN		6
879da6c28aaSamw #define	IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \
880da6c28aaSamw 	"successful_access/failed_access/inherited"
881da6c28aaSamw #define	IFLAGS_SIZE		(sizeof (IFLAGS_STR) - 1)
8825a5eeccaSmarks #define	ACCESS_TYPE_SIZE	7	/* if unknown */
883fa9e4066Sahrens #define	COLON_CNT		3
884fa9e4066Sahrens #define	PERMS_LEN		216
885da6c28aaSamw #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \
8865a5eeccaSmarks     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
887fa9e4066Sahrens 
888fa9e4066Sahrens static char *
ace_acltotext(acl_t * aceaclp,int flags)8895a5eeccaSmarks ace_acltotext(acl_t *aceaclp, int flags)
890fa9e4066Sahrens {
891fa9e4066Sahrens 	ace_t		*aclp = aceaclp->acl_aclp;
892fa9e4066Sahrens 	int		aclcnt = aceaclp->acl_cnt;
8935a5eeccaSmarks 	int		i;
894b249c65cSmarks 	int		error = 0;
895fa9e4066Sahrens 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
896*fab57d1bSGordon Ross 	dynaclstr_t	*dstr;
897909c9a9fSMark Shellenbaum 	char		*aclexport = NULL;
8989a2c8b2bSGowtham Thommandra 	char		*rawsidp = NULL;
899fa9e4066Sahrens 
900fa9e4066Sahrens 	if (aclp == NULL)
901fa9e4066Sahrens 		return (NULL);
902b249c65cSmarks 
903b249c65cSmarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
904b249c65cSmarks 		return (NULL);
905b249c65cSmarks 	dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE;
906b249c65cSmarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
907b249c65cSmarks 		free(dstr);
908fa9e4066Sahrens 		return (NULL);
909b249c65cSmarks 	}
910b249c65cSmarks 	*dstr->d_aclexport = '\0';
911b249c65cSmarks 	dstr->d_pos = 0;
912fa9e4066Sahrens 
913fa9e4066Sahrens 	for (i = 0; i < aclcnt; i++, aclp++) {
914fa9e4066Sahrens 
915b249c65cSmarks 		if (error = ace_type_txt(dstr, aclp, flags))
916b249c65cSmarks 			break;
917b249c65cSmarks 		if (error = ace_perm_txt(dstr, aclp->a_access_mask,
918b249c65cSmarks 		    aclp->a_flags, isdir, flags))
919b249c65cSmarks 			break;
920b249c65cSmarks 		if (error = ace_inherit_txt(dstr, aclp->a_flags, flags))
921b249c65cSmarks 			break;
922b249c65cSmarks 		if (error = ace_access_txt(dstr, aclp->a_type))
923b249c65cSmarks 			break;
9245a5eeccaSmarks 
9255a5eeccaSmarks 		if ((flags & ACL_APPEND_ID) &&
9265a5eeccaSmarks 		    (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ||
9275a5eeccaSmarks 		    ((aclp->a_flags & ACE_TYPE_FLAGS) ==
9285a5eeccaSmarks 		    ACE_IDENTIFIER_GROUP))) {
929b249c65cSmarks 			char id[ID_STR_MAX], *idstr;
930b249c65cSmarks 
931b249c65cSmarks 			if (error = str_append(dstr, ":"))
932b249c65cSmarks 				break;
9335f41bf46SMark Shellenbaum 
9345f41bf46SMark Shellenbaum 			rawsidp = NULL;
9355f41bf46SMark Shellenbaum 			id[ID_STR_MAX -1] = '\0'; /* null terminate */
9365f41bf46SMark Shellenbaum 			if (aclp->a_who > MAXUID && (flags & ACL_SID_FMT)) {
9375f41bf46SMark Shellenbaum 
9385f41bf46SMark Shellenbaum 				error = getsidname(aclp->a_who,
9395f41bf46SMark Shellenbaum 				    ((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ?
9405f41bf46SMark Shellenbaum 				    B_TRUE : B_FALSE, &idstr, 1);
9419a2c8b2bSGowtham Thommandra 				rawsidp = idstr;
9425f41bf46SMark Shellenbaum 				if (error)
9435f41bf46SMark Shellenbaum 					break;
9445f41bf46SMark Shellenbaum 			} else if (aclp->a_who > MAXUID &&
9455f41bf46SMark Shellenbaum 			    !(flags & ACL_NORESOLVE)) {
9465f41bf46SMark Shellenbaum 				idstr = lltostr(UID_NOBODY,
9475f41bf46SMark Shellenbaum 				    &id[ID_STR_MAX - 1]);
9485f41bf46SMark Shellenbaum 			} else {
9495f41bf46SMark Shellenbaum 				idstr = lltostr(aclp->a_who,
9505f41bf46SMark Shellenbaum 				    &id[ID_STR_MAX - 1]);
9515f41bf46SMark Shellenbaum 			}
952b249c65cSmarks 			if (error = str_append(dstr, idstr))
953b249c65cSmarks 				break;
9549a2c8b2bSGowtham Thommandra 			if (rawsidp) {
9555f41bf46SMark Shellenbaum 				free(rawsidp);
9569a2c8b2bSGowtham Thommandra 				rawsidp = NULL;
9579a2c8b2bSGowtham Thommandra 			}
9585a5eeccaSmarks 		}
9595a5eeccaSmarks 		if (i < aclcnt - 1) {
960b249c65cSmarks 			if (error = str_append(dstr, ","))
961b249c65cSmarks 				break;
962fa9e4066Sahrens 		}
963fa9e4066Sahrens 	}
9649a2c8b2bSGowtham Thommandra 
9659a2c8b2bSGowtham Thommandra 	if (rawsidp)
9669a2c8b2bSGowtham Thommandra 		free(rawsidp);
967b249c65cSmarks 	if (error) {
968b249c65cSmarks 		if (dstr->d_aclexport)
969b249c65cSmarks 			free(dstr->d_aclexport);
970b249c65cSmarks 	} else {
971b249c65cSmarks 		aclexport = dstr->d_aclexport;
972b249c65cSmarks 	}
973b249c65cSmarks 	free(dstr);
974fa9e4066Sahrens 	return (aclexport);
975fa9e4066Sahrens }
976fa9e4066Sahrens 
9775a5eeccaSmarks char *
acl_totext(acl_t * aclp,int flags)9785a5eeccaSmarks acl_totext(acl_t *aclp, int flags)
979fa9e4066Sahrens {
9805a5eeccaSmarks 	char *txtp;
981fa9e4066Sahrens 
9825a5eeccaSmarks 	if (aclp == NULL)
9835a5eeccaSmarks 		return (NULL);
984fa9e4066Sahrens 
9855a5eeccaSmarks 	switch (aclp->acl_type) {
9865a5eeccaSmarks 	case ACE_T:
9875a5eeccaSmarks 		txtp = ace_acltotext(aclp, flags);
9885a5eeccaSmarks 		break;
9895a5eeccaSmarks 	case ACLENT_T:
9905a5eeccaSmarks 		txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags);
9915a5eeccaSmarks 		break;
9925a5eeccaSmarks 	}
993fa9e4066Sahrens 
9945a5eeccaSmarks 	return (txtp);
995fa9e4066Sahrens }
996fa9e4066Sahrens 
9975a5eeccaSmarks int
acl_fromtext(const char * acltextp,acl_t ** ret_aclp)9985a5eeccaSmarks acl_fromtext(const char *acltextp, acl_t **ret_aclp)
9995a5eeccaSmarks {
10005a5eeccaSmarks 	int error;
10015a5eeccaSmarks 	char *buf;
10025a5eeccaSmarks 
10035a5eeccaSmarks 	buf = malloc(strlen(acltextp) + 2);
10045a5eeccaSmarks 	if (buf == NULL)
10055a5eeccaSmarks 		return (EACL_MEM_ERROR);
10065a5eeccaSmarks 	strcpy(buf, acltextp);
10075a5eeccaSmarks 	strcat(buf, "\n");
10089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) mutex_lock(&yymutex);
10105a5eeccaSmarks 	yybuf = buf;
10115a5eeccaSmarks 	yyreset();
10125a5eeccaSmarks 	error = yyparse();
10135a5eeccaSmarks 	free(buf);
10145a5eeccaSmarks 
10155a5eeccaSmarks 	if (yyacl) {
10165a5eeccaSmarks 		if (error == 0)
10175a5eeccaSmarks 			*ret_aclp = yyacl;
10185a5eeccaSmarks 		else {
10195a5eeccaSmarks 			acl_free(yyacl);
10205a5eeccaSmarks 		}
10215a5eeccaSmarks 		yyacl = NULL;
10225a5eeccaSmarks 	}
10239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) mutex_unlock(&yymutex);
10249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10255a5eeccaSmarks 	return (error);
10265a5eeccaSmarks }
1027fa9e4066Sahrens 
1028fa9e4066Sahrens int
acl_parse(const char * acltextp,acl_t ** aclp)10295a5eeccaSmarks acl_parse(const char *acltextp, acl_t **aclp)
1030fa9e4066Sahrens {
10315a5eeccaSmarks 	int error;
1032fa9e4066Sahrens 
10335a5eeccaSmarks 	yyinteractive = 1;
10345a5eeccaSmarks 	error = acl_fromtext(acltextp, aclp);
10355a5eeccaSmarks 	yyinteractive = 0;
10365a5eeccaSmarks 	return (error);
10375a5eeccaSmarks }
1038fa9e4066Sahrens 
10395a5eeccaSmarks static void
ace_compact_printacl(acl_t * aclp,int flgs)1040*fab57d1bSGordon Ross ace_compact_printacl(acl_t *aclp, int flgs)
10415a5eeccaSmarks {
10425a5eeccaSmarks 	int cnt;
10435a5eeccaSmarks 	ace_t *acep;
1044b249c65cSmarks 	dynaclstr_t *dstr;
1045b249c65cSmarks 	int len;
10465a5eeccaSmarks 
1047b249c65cSmarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
1048b249c65cSmarks 		return;
1049b249c65cSmarks 	dstr->d_bufsize = ACE_ENTRY_SIZE;
1050b249c65cSmarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
1051b249c65cSmarks 		free(dstr);
1052b249c65cSmarks 		return;
1053b249c65cSmarks 	}
1054b249c65cSmarks 	*dstr->d_aclexport = '\0';
1055b249c65cSmarks 
1056b249c65cSmarks 	dstr->d_pos = 0;
10575a5eeccaSmarks 	for (cnt = 0, acep = aclp->acl_aclp;
10585a5eeccaSmarks 	    cnt != aclp->acl_cnt; cnt++, acep++) {
1059b249c65cSmarks 		dstr->d_aclexport[0] = '\0';
1060b249c65cSmarks 		dstr->d_pos = 0;
1061b249c65cSmarks 
1062*fab57d1bSGordon Ross 		if (ace_type_txt(dstr, acep, flgs))
1063b249c65cSmarks 			break;
1064b249c65cSmarks 		len = strlen(&dstr->d_aclexport[0]);
1065b249c65cSmarks 		if (ace_perm_txt(dstr, acep->a_access_mask, acep->a_flags,
1066b249c65cSmarks 		    aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT))
1067b249c65cSmarks 			break;
1068b249c65cSmarks 		if (ace_inherit_txt(dstr, acep->a_flags, ACL_COMPACT_FMT))
1069b249c65cSmarks 			break;
1070b249c65cSmarks 		if (ace_access_txt(dstr, acep->a_type) == -1)
1071b249c65cSmarks 			break;
1072b249c65cSmarks 		(void) printf("    %20.*s%s\n", len, dstr->d_aclexport,
1073b249c65cSmarks 		    &dstr->d_aclexport[len]);
10745a5eeccaSmarks 	}
1075b249c65cSmarks 
1076b249c65cSmarks 	if (dstr->d_aclexport)
1077b249c65cSmarks 		free(dstr->d_aclexport);
1078b249c65cSmarks 	free(dstr);
10795a5eeccaSmarks }
1080fa9e4066Sahrens 
10815a5eeccaSmarks static void
ace_printacl(acl_t * aclp,int cols,int flgs)1082*fab57d1bSGordon Ross ace_printacl(acl_t *aclp, int cols, int flgs)
10835a5eeccaSmarks {
10845a5eeccaSmarks 	int  slot = 0;
10855a5eeccaSmarks 	char *token;
10865a5eeccaSmarks 	char *acltext;
10875a5eeccaSmarks 
1088*fab57d1bSGordon Ross 	if (flgs & ACL_COMPACT_FMT) {
1089*fab57d1bSGordon Ross 		ace_compact_printacl(aclp, flgs);
10905a5eeccaSmarks 		return;
1091fa9e4066Sahrens 	}
1092fa9e4066Sahrens 
1093*fab57d1bSGordon Ross 	acltext = acl_totext(aclp, flgs);
1094fa9e4066Sahrens 
10955a5eeccaSmarks 	if (acltext == NULL)
10965a5eeccaSmarks 		return;
10975a5eeccaSmarks 
10985a5eeccaSmarks 	token = strtok(acltext, ",");
10995a5eeccaSmarks 	if (token == NULL) {
11005a5eeccaSmarks 		free(acltext);
11015a5eeccaSmarks 		return;
1102fa9e4066Sahrens 	}
1103fa9e4066Sahrens 
11045a5eeccaSmarks 	do {
11055a5eeccaSmarks 		(void) printf("     %d:", slot++);
11065a5eeccaSmarks 		split_line(token, cols - 5);
11075a5eeccaSmarks 	} while (token = strtok(NULL, ","));
11085a5eeccaSmarks 	free(acltext);
11095a5eeccaSmarks }
1110fa9e4066Sahrens 
11115a5eeccaSmarks /*
11125a5eeccaSmarks  * pretty print an ACL.
11135a5eeccaSmarks  * For aclent_t ACL's the format is
11145a5eeccaSmarks  * similar to the old format used by getfacl,
11155a5eeccaSmarks  * with the addition of adding a "slot" number
11165a5eeccaSmarks  * before each entry.
11175a5eeccaSmarks  *
11185a5eeccaSmarks  * for ace_t ACL's the cols variable will break up
11195a5eeccaSmarks  * the long lines into multiple lines and will also
11205a5eeccaSmarks  * print a "slot" number.
11215a5eeccaSmarks  */
11225a5eeccaSmarks void
acl_printacl2(acl_t * aclp,int cols,int flgs)1123*fab57d1bSGordon Ross acl_printacl2(acl_t *aclp, int cols, int flgs)
1124*fab57d1bSGordon Ross {
1125*fab57d1bSGordon Ross 
1126*fab57d1bSGordon Ross 	switch (aclp->acl_type) {
1127*fab57d1bSGordon Ross 	case ACLENT_T:
1128*fab57d1bSGordon Ross 		aclent_printacl(aclp);
1129*fab57d1bSGordon Ross 		break;
1130*fab57d1bSGordon Ross 	case ACE_T:
1131*fab57d1bSGordon Ross 		ace_printacl(aclp, cols, flgs);
1132*fab57d1bSGordon Ross 		break;
1133*fab57d1bSGordon Ross 	}
1134*fab57d1bSGordon Ross }
1135*fab57d1bSGordon Ross 
1136*fab57d1bSGordon Ross /*
1137*fab57d1bSGordon Ross  * Historical, compatibility version of the above.
1138*fab57d1bSGordon Ross  */
1139*fab57d1bSGordon Ross void
acl_printacl(acl_t * aclp,int cols,int compact)11405a5eeccaSmarks acl_printacl(acl_t *aclp, int cols, int compact)
11415a5eeccaSmarks {
1142*fab57d1bSGordon Ross 	int flgs = compact ? ACL_COMPACT_FMT : 0;
1143fa9e4066Sahrens 
11445a5eeccaSmarks 	switch (aclp->acl_type) {
11455a5eeccaSmarks 	case ACLENT_T:
11465a5eeccaSmarks 		aclent_printacl(aclp);
11475a5eeccaSmarks 		break;
11485a5eeccaSmarks 	case ACE_T:
1149*fab57d1bSGordon Ross 		ace_printacl(aclp, cols, flgs);
11505a5eeccaSmarks 		break;
11515a5eeccaSmarks 	}
11525a5eeccaSmarks }
1153fa9e4066Sahrens 
11545a5eeccaSmarks typedef struct value_table {
11555a5eeccaSmarks 	char		p_letter; /* perm letter such as 'r' */
11565a5eeccaSmarks 	uint32_t	p_value; /* value for perm when pletter found */
11575a5eeccaSmarks } value_table_t;
1158fa9e4066Sahrens 
11595a5eeccaSmarks /*
1160da6c28aaSamw  * The permission tables are laid out in positional order
11615a5eeccaSmarks  * a '-' character will indicate a permission at a given
11625a5eeccaSmarks  * position is not specified.  The '-' is not part of the
11635a5eeccaSmarks  * table, but will be checked for in the permission computation
11645a5eeccaSmarks  * routine.
11655a5eeccaSmarks  */
1166da6c28aaSamw value_table_t ace_perm_table[] = {
11675a5eeccaSmarks 	{ 'r', ACE_READ_DATA},
11685a5eeccaSmarks 	{ 'w', ACE_WRITE_DATA},
11695a5eeccaSmarks 	{ 'x', ACE_EXECUTE},
11705a5eeccaSmarks 	{ 'p', ACE_APPEND_DATA},
11715a5eeccaSmarks 	{ 'd', ACE_DELETE},
11725a5eeccaSmarks 	{ 'D', ACE_DELETE_CHILD},
11735a5eeccaSmarks 	{ 'a', ACE_READ_ATTRIBUTES},
11745a5eeccaSmarks 	{ 'A', ACE_WRITE_ATTRIBUTES},
11755a5eeccaSmarks 	{ 'R', ACE_READ_NAMED_ATTRS},
11765a5eeccaSmarks 	{ 'W', ACE_WRITE_NAMED_ATTRS},
11775a5eeccaSmarks 	{ 'c', ACE_READ_ACL},
11785a5eeccaSmarks 	{ 'C', ACE_WRITE_ACL},
11795a5eeccaSmarks 	{ 'o', ACE_WRITE_OWNER},
11805a5eeccaSmarks 	{ 's', ACE_SYNCHRONIZE}
11815a5eeccaSmarks };
1182fa9e4066Sahrens 
1183da6c28aaSamw #define	ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t))
1184fa9e4066Sahrens 
1185da6c28aaSamw value_table_t aclent_perm_table[] = {
11865a5eeccaSmarks 	{ 'r', S_IROTH},
11875a5eeccaSmarks 	{ 'w', S_IWOTH},
11885a5eeccaSmarks 	{ 'x', S_IXOTH}
11895a5eeccaSmarks };
1190fa9e4066Sahrens 
1191da6c28aaSamw #define	ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t))
1192da6c28aaSamw 
1193da6c28aaSamw value_table_t inherit_table[] = {
11945a5eeccaSmarks 	{'f', ACE_FILE_INHERIT_ACE},
11955a5eeccaSmarks 	{'d', ACE_DIRECTORY_INHERIT_ACE},
11965a5eeccaSmarks 	{'i', ACE_INHERIT_ONLY_ACE},
11975a5eeccaSmarks 	{'n', ACE_NO_PROPAGATE_INHERIT_ACE},
11985a5eeccaSmarks 	{'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
1199da6c28aaSamw 	{'F', ACE_FAILED_ACCESS_ACE_FLAG},
1200da6c28aaSamw 	{'I', ACE_INHERITED_ACE}
12015a5eeccaSmarks };
1202fa9e4066Sahrens 
1203da6c28aaSamw #define	IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t))
1204bf8b6031Smarks #define	IFLAG_COUNT_V1 6 /* Older version compatibility */
1205da6c28aaSamw 
12065a5eeccaSmarks /*
12075a5eeccaSmarks  * compute value from a permission table or inheritance table
12085a5eeccaSmarks  * based on string passed in.  If positional is set then
12095a5eeccaSmarks  * string must match order in permtab, otherwise any order
12105a5eeccaSmarks  * is allowed.
12115a5eeccaSmarks  */
12125a5eeccaSmarks int
compute_values(value_table_t * permtab,int count,char * permstr,int positional,uint32_t * mask)12135a5eeccaSmarks compute_values(value_table_t *permtab, int count,
12145a5eeccaSmarks     char *permstr, int positional, uint32_t *mask)
12155a5eeccaSmarks {
12165a5eeccaSmarks 	uint32_t perm_val = 0;
12175a5eeccaSmarks 	char *pstr;
12185a5eeccaSmarks 	int i, found;
1219fa9e4066Sahrens 
12205a5eeccaSmarks 	if (count < 0)
12215a5eeccaSmarks 		return (1);
1222fa9e4066Sahrens 
12235a5eeccaSmarks 	if (positional) {
12245a5eeccaSmarks 		for (i = 0, pstr = permstr; i != count && pstr &&
12255a5eeccaSmarks 		    *pstr; i++, pstr++) {
12265a5eeccaSmarks 			if (*pstr == permtab[i].p_letter) {
12275a5eeccaSmarks 				perm_val |= permtab[i].p_value;
12285a5eeccaSmarks 			} else if (*pstr != '-') {
12295a5eeccaSmarks 				return (1);
12305a5eeccaSmarks 			}
1231fa9e4066Sahrens 		}
12325a5eeccaSmarks 	} else {  /* random order single letters with no '-' */
12335a5eeccaSmarks 		for (pstr = permstr; pstr && *pstr; pstr++) {
12345a5eeccaSmarks 			for (found = 0, i = 0; i != count; i++) {
12355a5eeccaSmarks 				if (*pstr == permtab[i].p_letter) {
12365a5eeccaSmarks 					perm_val |= permtab[i].p_value;
12375a5eeccaSmarks 					found = 1;
12385a5eeccaSmarks 					break;
1239fa9e4066Sahrens 				}
1240fa9e4066Sahrens 			}
12415a5eeccaSmarks 			if (found == 0)
12425a5eeccaSmarks 				return (1);
1243fa9e4066Sahrens 		}
1244fa9e4066Sahrens 	}
12455a5eeccaSmarks 
12465a5eeccaSmarks 	*mask = perm_val;
1247fa9e4066Sahrens 	return (0);
1248fa9e4066Sahrens }
1249fa9e4066Sahrens 
1250bf8b6031Smarks 
1251bf8b6031Smarks int
ace_inherit_helper(char * str,uint32_t * imask,int table_length)1252bf8b6031Smarks ace_inherit_helper(char *str, uint32_t *imask, int table_length)
1253bf8b6031Smarks {
1254bf8b6031Smarks 	int rc = 0;
1255bf8b6031Smarks 
1256bf8b6031Smarks 	if (strlen(str) == table_length) {
1257bf8b6031Smarks 		/*
1258bf8b6031Smarks 		 * If the string == table_length then first check to see it's
1259bf8b6031Smarks 		 * in positional format.  If that fails then see if it's in
1260bf8b6031Smarks 		 * non-positional format.
1261bf8b6031Smarks 		 */
1262bf8b6031Smarks 		if (compute_values(inherit_table, table_length, str,
1263bf8b6031Smarks 		    1, imask) && compute_values(inherit_table,
1264bf8b6031Smarks 		    table_length, str, 0, imask)) {
1265bf8b6031Smarks 			rc = 1;
1266bf8b6031Smarks 		}
1267bf8b6031Smarks 	} else {
1268bf8b6031Smarks 		rc = compute_values(inherit_table, table_length, str, 0, imask);
1269bf8b6031Smarks 	}
1270bf8b6031Smarks 
1271bf8b6031Smarks 	return (rc ? EACL_INHERIT_ERROR : 0);
1272bf8b6031Smarks }
1273bf8b6031Smarks 
12745a5eeccaSmarks /*
12755a5eeccaSmarks  * compute value for inheritance flags.
12765a5eeccaSmarks  */
12775a5eeccaSmarks int
compute_ace_inherit(char * str,uint32_t * imask)12785a5eeccaSmarks compute_ace_inherit(char *str, uint32_t *imask)
1279fa9e4066Sahrens {
1280bf8b6031Smarks 	int rc = 0;
1281fa9e4066Sahrens 
1282bf8b6031Smarks 	rc = ace_inherit_helper(str, imask, IFLAG_COUNT);
12835a5eeccaSmarks 
1284bf8b6031Smarks 	if (rc && strlen(str) != IFLAG_COUNT) {
12855a5eeccaSmarks 
1286bf8b6031Smarks 		/* is it an old formatted inherit string? */
1287bf8b6031Smarks 		rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1);
1288bf8b6031Smarks 	}
12895a5eeccaSmarks 
1290bf8b6031Smarks 	return (rc);
1291fa9e4066Sahrens }
1292fa9e4066Sahrens 
12935a5eeccaSmarks 
12945a5eeccaSmarks /*
12955a5eeccaSmarks  * compute value for ACE permissions.
12965a5eeccaSmarks  */
1297fa9e4066Sahrens int
compute_ace_perms(char * str,uint32_t * mask)12985a5eeccaSmarks compute_ace_perms(char *str, uint32_t *mask)
1299fa9e4066Sahrens {
13005a5eeccaSmarks 	int positional = 0;
1301fa9e4066Sahrens 	int error;
1302fa9e4066Sahrens 
13035a5eeccaSmarks 	if (strlen(str) == ACE_PERM_COUNT)
13045a5eeccaSmarks 		positional = 1;
1305fa9e4066Sahrens 
13065a5eeccaSmarks 	error = compute_values(ace_perm_table, ACE_PERM_COUNT,
13075a5eeccaSmarks 	    str, positional, mask);
1308fa9e4066Sahrens 
13095a5eeccaSmarks 	if (error && positional) {
13105a5eeccaSmarks 		/*
13115a5eeccaSmarks 		 * If positional was set, then make sure permissions
13125a5eeccaSmarks 		 * aren't actually valid in non positional case where
13135a5eeccaSmarks 		 * all permissions are specified, just in random order.
13145a5eeccaSmarks 		 */
13155a5eeccaSmarks 		error = compute_values(ace_perm_table,
13165a5eeccaSmarks 		    ACE_PERM_COUNT, str, 0, mask);
1317fa9e4066Sahrens 	}
13185a5eeccaSmarks 	if (error)
13195a5eeccaSmarks 		error = EACL_PERM_MASK_ERROR;
1320fa9e4066Sahrens 
13215a5eeccaSmarks 	return (error);
13225a5eeccaSmarks }
1323fa9e4066Sahrens 
1324fa9e4066Sahrens 
1325fa9e4066Sahrens 
13265a5eeccaSmarks /*
13275a5eeccaSmarks  * compute values for aclent permissions.
13285a5eeccaSmarks  */
13295a5eeccaSmarks int
compute_aclent_perms(char * str,o_mode_t * mask)13305a5eeccaSmarks compute_aclent_perms(char *str, o_mode_t *mask)
13315a5eeccaSmarks {
13325a5eeccaSmarks 	int error;
13335a5eeccaSmarks 	uint32_t pmask;
13345a5eeccaSmarks 
13355a5eeccaSmarks 	if (strlen(str) != ACLENT_PERM_COUNT)
13365a5eeccaSmarks 		return (EACL_PERM_MASK_ERROR);
13375a5eeccaSmarks 
13385a5eeccaSmarks 	*mask = 0;
13395a5eeccaSmarks 	error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT,
13405a5eeccaSmarks 	    str, 1, &pmask);
13415a5eeccaSmarks 	if (error == 0) {
13425a5eeccaSmarks 		*mask = (o_mode_t)pmask;
13435a5eeccaSmarks 	} else
13445a5eeccaSmarks 		error = EACL_PERM_MASK_ERROR;
1345fa9e4066Sahrens 	return (error);
1346fa9e4066Sahrens }
13475a5eeccaSmarks 
13485a5eeccaSmarks /*
13495a5eeccaSmarks  * determine ACE permissions.
13505a5eeccaSmarks  */
13515a5eeccaSmarks int
ace_perm_mask(struct acl_perm_type * aclperm,uint32_t * mask)13525a5eeccaSmarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask)
13535a5eeccaSmarks {
13545a5eeccaSmarks 	int error;
13555a5eeccaSmarks 
13565a5eeccaSmarks 	if (aclperm->perm_style == PERM_TYPE_EMPTY) {
13575a5eeccaSmarks 		*mask = 0;
13585a5eeccaSmarks 		return (0);
13595a5eeccaSmarks 	}
13605a5eeccaSmarks 
13615a5eeccaSmarks 	if (aclperm->perm_style == PERM_TYPE_ACE) {
13625a5eeccaSmarks 		*mask = aclperm->perm_val;
13635a5eeccaSmarks 		return (0);
13645a5eeccaSmarks 	}
13655a5eeccaSmarks 
13665a5eeccaSmarks 	error = compute_ace_perms(aclperm->perm_str, mask);
13675a5eeccaSmarks 	if (error) {
13685b233e2dSmarks 		acl_error(dgettext(TEXT_DOMAIN,
13695b233e2dSmarks 		    "Invalid permission(s) '%s' specified\n"),
13705a5eeccaSmarks 		    aclperm->perm_str);
13715a5eeccaSmarks 		return (EACL_PERM_MASK_ERROR);
13725a5eeccaSmarks 	}
13735a5eeccaSmarks 
13745a5eeccaSmarks 	return (0);
13755a5eeccaSmarks }
1376