10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51507Sgjelinek  * Common Development and Distribution License (the "License").
61507Sgjelinek  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
2211605SGowtham.Thommandra@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*LINTLIBRARY*/
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <grp.h>
290Sstevel@tonic-gate #include <pwd.h>
300Sstevel@tonic-gate #include <string.h>
310Sstevel@tonic-gate #include <limits.h>
320Sstevel@tonic-gate #include <stdlib.h>
33789Sahrens #include <errno.h>
340Sstevel@tonic-gate #include <sys/param.h>
350Sstevel@tonic-gate #include <sys/types.h>
361420Smarks #include <sys/stat.h>
370Sstevel@tonic-gate #include <sys/acl.h>
38789Sahrens #include <aclutils.h>
397057Smarks #include <idmap.h>
40*11963SAfshin.Ardakani@Sun.COM #include <synch.h>
411420Smarks 
421420Smarks #define	ID_STR_MAX	20	/* digits in LONG_MAX */
43789Sahrens 
441420Smarks #define	APPENDED_ID_MAX	ID_STR_MAX + 1		/* id + colon */
451420Smarks /*
461420Smarks  * yyinteractive controls whether yyparse should print out
471420Smarks  * error messages to stderr, and whether or not id's should be
481420Smarks  * allowed from acl_fromtext().
491420Smarks  */
501420Smarks int	yyinteractive;
511420Smarks acl_t	*yyacl;
521420Smarks char	*yybuf;
53*11963SAfshin.Ardakani@Sun.COM mutex_t	yymutex;
54789Sahrens 
55789Sahrens extern acl_t *acl_alloc(enum acl_type);
560Sstevel@tonic-gate 
577057Smarks /*
587057Smarks  * dynamic string that will increase in size on an
597057Smarks  * as needed basis.
607057Smarks  */
617057Smarks typedef struct dynaclstr {
627057Smarks 	size_t d_bufsize;		/* current size of aclexport */
637057Smarks 	char *d_aclexport;
647057Smarks 	int d_pos;
657057Smarks } dynaclstr_t;
66922Shm123892 
677057Smarks static int str_append(dynaclstr_t *, char *);
687057Smarks static int aclent_perm_txt(dynaclstr_t *, o_mode_t);
690Sstevel@tonic-gate 
701420Smarks static void
711420Smarks aclent_perms(int perm, char *txt_perms)
721420Smarks {
731420Smarks 	if (perm & S_IROTH)
741420Smarks 		txt_perms[0] = 'r';
751420Smarks 	else
761420Smarks 		txt_perms[0] = '-';
771420Smarks 	if (perm & S_IWOTH)
781420Smarks 		txt_perms[1] = 'w';
791420Smarks 	else
801420Smarks 		txt_perms[1] = '-';
811420Smarks 	if (perm & S_IXOTH)
821420Smarks 		txt_perms[2] = 'x';
831420Smarks 	else
841420Smarks 		txt_perms[2] = '-';
851420Smarks 	txt_perms[3] = '\0';
861420Smarks }
871420Smarks 
881420Smarks static char *
891535Smarks pruname(uid_t uid, char *uidp, size_t buflen, int noresolve)
901420Smarks {
911515Sgjelinek 	struct passwd	*passwdp = NULL;
921420Smarks 
931515Sgjelinek 	if (noresolve == 0)
941515Sgjelinek 		passwdp = getpwuid(uid);
951420Smarks 	if (passwdp == (struct passwd *)NULL) {
961420Smarks 		/* could not get passwd information: display uid instead */
974321Scasper 		(void) snprintf(uidp, buflen, "%u", uid);
981535Smarks 	} else {
991535Smarks 		(void) strlcpy(uidp, passwdp->pw_name, buflen);
1001535Smarks 	}
1011535Smarks 	return (uidp);
1021420Smarks }
1031420Smarks 
1041420Smarks static char *
1051535Smarks prgname(gid_t gid, char *gidp, size_t buflen, int noresolve)
1061420Smarks {
1071515Sgjelinek 	struct group	*groupp = NULL;
1081420Smarks 
1091515Sgjelinek 	if (noresolve == 0)
1101515Sgjelinek 		groupp = getgrgid(gid);
1111420Smarks 	if (groupp == (struct group *)NULL) {
1121420Smarks 		/* could not get group information: display gid instead */
1134321Scasper 		(void) snprintf(gidp, buflen, "%u", gid);
1141535Smarks 	} else {
1151535Smarks 		(void) strlcpy(gidp, groupp->gr_name, buflen);
1161535Smarks 	}
1171535Smarks 	return (gidp);
1181420Smarks }
1197057Smarks 
1207680SMark.Shellenbaum@Sun.COM static int
1217680SMark.Shellenbaum@Sun.COM getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve)
1227057Smarks {
1237057Smarks 	idmap_handle_t *idmap_hdl = NULL;
1247057Smarks 	idmap_get_handle_t *get_hdl = NULL;
1257057Smarks 	idmap_stat status;
1267057Smarks 	idmap_rid_t rid;
1277680SMark.Shellenbaum@Sun.COM 	int error = IDMAP_ERR_NORESULT;
1287057Smarks 	int len;
12911605SGowtham.Thommandra@Sun.COM 	char *domain = NULL;
13011605SGowtham.Thommandra@Sun.COM 	char *name = NULL;
1317057Smarks 
1327680SMark.Shellenbaum@Sun.COM 	*sidp = NULL;
1337057Smarks 
1347057Smarks 	/*
1357057Smarks 	 * First try and get windows name
1367057Smarks 	 */
1377057Smarks 
1387680SMark.Shellenbaum@Sun.COM 	if (!noresolve) {
1397680SMark.Shellenbaum@Sun.COM 		if (user)
1407680SMark.Shellenbaum@Sun.COM 			error = idmap_getwinnamebyuid(who,
1417680SMark.Shellenbaum@Sun.COM 			    IDMAP_REQ_FLG_USE_CACHE, &name, &domain);
1427680SMark.Shellenbaum@Sun.COM 		else
1437680SMark.Shellenbaum@Sun.COM 			error = idmap_getwinnamebygid(who,
1447680SMark.Shellenbaum@Sun.COM 			    IDMAP_REQ_FLG_USE_CACHE, &name, &domain);
1457680SMark.Shellenbaum@Sun.COM 	}
1467680SMark.Shellenbaum@Sun.COM 	if (error != IDMAP_SUCCESS) {
1477680SMark.Shellenbaum@Sun.COM 		if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS &&
1487680SMark.Shellenbaum@Sun.COM 		    idmap_get_create(idmap_hdl, &get_hdl) == IDMAP_SUCCESS) {
1497057Smarks 			if (user)
1507057Smarks 				error = idmap_get_sidbyuid(get_hdl, who,
1517369SJulian.Pullen@Sun.COM 				    IDMAP_REQ_FLG_USE_CACHE, &domain, &rid,
1527369SJulian.Pullen@Sun.COM 				    &status);
1537057Smarks 			else
1547057Smarks 				error = idmap_get_sidbygid(get_hdl, who,
1557369SJulian.Pullen@Sun.COM 				    IDMAP_REQ_FLG_USE_CACHE, &domain, &rid,
1567369SJulian.Pullen@Sun.COM 				    &status);
1577680SMark.Shellenbaum@Sun.COM 			if (error == IDMAP_SUCCESS &&
1587680SMark.Shellenbaum@Sun.COM 			    idmap_get_mappings(get_hdl) == 0) {
1597680SMark.Shellenbaum@Sun.COM 				if (status == IDMAP_SUCCESS) {
1607680SMark.Shellenbaum@Sun.COM 					len = snprintf(NULL, 0,
1617680SMark.Shellenbaum@Sun.COM 					    "%s-%d", domain, rid);
1627680SMark.Shellenbaum@Sun.COM 					if (*sidp = malloc(len + 1)) {
1637680SMark.Shellenbaum@Sun.COM 						(void) snprintf(*sidp, len + 1,
1647680SMark.Shellenbaum@Sun.COM 						    "%s-%d", domain, rid);
1657680SMark.Shellenbaum@Sun.COM 					}
1667680SMark.Shellenbaum@Sun.COM 				}
1677680SMark.Shellenbaum@Sun.COM 			}
1687057Smarks 		}
1697057Smarks 		if (get_hdl)
1707057Smarks 			idmap_get_destroy(get_hdl);
1717057Smarks 		if (idmap_hdl)
1727057Smarks 			(void) idmap_fini(idmap_hdl);
1737057Smarks 	} else {
1747057Smarks 		int len;
1757680SMark.Shellenbaum@Sun.COM 
1768268SMark.Shellenbaum@Sun.COM 		len = snprintf(NULL, 0, "%s@%s", name, domain);
1777680SMark.Shellenbaum@Sun.COM 		if (*sidp = malloc(len + 1))
1787680SMark.Shellenbaum@Sun.COM 			(void) snprintf(*sidp, len + 1, "%s@%s", name, domain);
17911605SGowtham.Thommandra@Sun.COM 	}
18011605SGowtham.Thommandra@Sun.COM 
18111605SGowtham.Thommandra@Sun.COM 	if (name)
1828268SMark.Shellenbaum@Sun.COM 		free(name);
18311605SGowtham.Thommandra@Sun.COM 	if (domain)
1848268SMark.Shellenbaum@Sun.COM 		free(domain);
1857680SMark.Shellenbaum@Sun.COM 	return (*sidp ? 0 : 1);
1867057Smarks }
1877057Smarks 
1881420Smarks static void
1891420Smarks aclent_printacl(acl_t *aclp)
190789Sahrens {
1911420Smarks 	aclent_t *tp;
1921420Smarks 	int aclcnt;
1931420Smarks 	int mask;
1941420Smarks 	int slot = 0;
1951420Smarks 	char perm[4];
1961535Smarks 	char uidp[ID_STR_MAX];
1971535Smarks 	char gidp[ID_STR_MAX];
1981420Smarks 
1991420Smarks 	/* display ACL: assume it is sorted. */
2001420Smarks 	aclcnt = aclp->acl_cnt;
2011420Smarks 	for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) {
2021420Smarks 		if (tp->a_type == CLASS_OBJ)
2031420Smarks 			mask = tp->a_perm;
2041420Smarks 	}
2051420Smarks 	aclcnt = aclp->acl_cnt;
2061420Smarks 	for (tp = aclp->acl_aclp; aclcnt--; tp++) {
2071420Smarks 		(void) printf("     %d:", slot++);
2081420Smarks 		switch (tp->a_type) {
2091420Smarks 		case USER:
2101420Smarks 			aclent_perms(tp->a_perm, perm);
2111420Smarks 			(void) printf("user:%s:%s\t\t",
2121535Smarks 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
2131420Smarks 			aclent_perms((tp->a_perm & mask), perm);
2141420Smarks 			(void) printf("#effective:%s\n", perm);
2151420Smarks 			break;
2161420Smarks 		case USER_OBJ:
2171420Smarks 			/* no need to display uid */
2181420Smarks 			aclent_perms(tp->a_perm, perm);
2191420Smarks 			(void) printf("user::%s\n", perm);
2201420Smarks 			break;
2211420Smarks 		case GROUP:
2221420Smarks 			aclent_perms(tp->a_perm, perm);
2231420Smarks 			(void) printf("group:%s:%s\t\t",
2241535Smarks 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
2251420Smarks 			aclent_perms(tp->a_perm & mask, perm);
2261420Smarks 			(void) printf("#effective:%s\n", perm);
2271420Smarks 			break;
2281420Smarks 		case GROUP_OBJ:
2291420Smarks 			aclent_perms(tp->a_perm, perm);
2301420Smarks 			(void) printf("group::%s\t\t", perm);
2311420Smarks 			aclent_perms(tp->a_perm & mask, perm);
2321420Smarks 			(void) printf("#effective:%s\n", perm);
2331420Smarks 			break;
2341420Smarks 		case CLASS_OBJ:
2351420Smarks 			aclent_perms(tp->a_perm, perm);
2361420Smarks 			(void) printf("mask:%s\n", perm);
2371420Smarks 			break;
2381420Smarks 		case OTHER_OBJ:
2391420Smarks 			aclent_perms(tp->a_perm, perm);
2401420Smarks 			(void) printf("other:%s\n", perm);
2411420Smarks 			break;
2421420Smarks 		case DEF_USER:
2431420Smarks 			aclent_perms(tp->a_perm, perm);
2441420Smarks 			(void) printf("default:user:%s:%s\n",
2451535Smarks 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
2461420Smarks 			break;
2471420Smarks 		case DEF_USER_OBJ:
2481420Smarks 			aclent_perms(tp->a_perm, perm);
2491420Smarks 			(void) printf("default:user::%s\n", perm);
2501420Smarks 			break;
2511420Smarks 		case DEF_GROUP:
2521420Smarks 			aclent_perms(tp->a_perm, perm);
2531420Smarks 			(void) printf("default:group:%s:%s\n",
2541535Smarks 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
2551420Smarks 			break;
2561420Smarks 		case DEF_GROUP_OBJ:
2571420Smarks 			aclent_perms(tp->a_perm, perm);
2581420Smarks 			(void) printf("default:group::%s\n", perm);
2591420Smarks 			break;
2601420Smarks 		case DEF_CLASS_OBJ:
2611420Smarks 			aclent_perms(tp->a_perm, perm);
2621420Smarks 			(void) printf("default:mask:%s\n", perm);
2631420Smarks 			break;
2641420Smarks 		case DEF_OTHER_OBJ:
2651420Smarks 			aclent_perms(tp->a_perm, perm);
2661420Smarks 			(void) printf("default:other:%s\n", perm);
2671420Smarks 			break;
2681420Smarks 		default:
2691420Smarks 			(void) fprintf(stderr,
2701567Smarks 			    dgettext(TEXT_DOMAIN, "unrecognized entry\n"));
2711420Smarks 			break;
2721420Smarks 		}
2731420Smarks 	}
2741420Smarks }
2751420Smarks 
2761420Smarks static void
2771420Smarks split_line(char *str, int cols)
2781420Smarks {
2791420Smarks 	char *ptr;
2801420Smarks 	int len;
2811420Smarks 	int i;
2821420Smarks 	int last_split;
2831420Smarks 	char *pad = "";
2841420Smarks 	int pad_len;
2851420Smarks 
2861420Smarks 	len = strlen(str);
2871420Smarks 	ptr = str;
2881420Smarks 	pad_len = 0;
2891420Smarks 
2901420Smarks 	ptr = str;
2911420Smarks 	last_split = 0;
2921420Smarks 	for (i = 0; i != len; i++) {
2931420Smarks 		if ((i + pad_len + 4) >= cols) {
2941420Smarks 			(void) printf("%s%.*s\n", pad, last_split, ptr);
2951420Smarks 			ptr = &ptr[last_split];
2961420Smarks 			len = strlen(ptr);
2971420Smarks 			i = 0;
2981420Smarks 			pad_len = 4;
2991420Smarks 			pad = "         ";
3001420Smarks 		} else {
3011420Smarks 			if (ptr[i] == '/' || ptr[i] == ':') {
3021420Smarks 				last_split = i;
3031420Smarks 			}
3041420Smarks 		}
3051420Smarks 	}
3061420Smarks 	if (i == len) {
3071420Smarks 		(void) printf("%s%s\n", pad, ptr);
3081420Smarks 	}
3091420Smarks }
3101420Smarks 
3117057Smarks /*
3127057Smarks  * compute entry type string, such as user:joe, group:staff,...
3137057Smarks  */
3147057Smarks static int
3157057Smarks aclent_type_txt(dynaclstr_t *dstr, aclent_t *aclp, int flags)
3161420Smarks {
3177057Smarks 	char idp[ID_STR_MAX];
3187057Smarks 	int error;
3197057Smarks 
3207057Smarks 	switch (aclp->a_type) {
3217057Smarks 	case DEF_USER_OBJ:
3227057Smarks 	case USER_OBJ:
3237057Smarks 		if (aclp->a_type == USER_OBJ)
3247057Smarks 			error = str_append(dstr, "user::");
3257057Smarks 		else
3267057Smarks 			error = str_append(dstr, "defaultuser::");
3277057Smarks 		break;
3287057Smarks 
3297057Smarks 	case DEF_USER:
3307057Smarks 	case USER:
3317057Smarks 		if (aclp->a_type == USER)
3327057Smarks 			error = str_append(dstr, "user:");
3337057Smarks 		else
3347057Smarks 			error = str_append(dstr, "defaultuser:");
3357057Smarks 		if (error)
3367057Smarks 			break;
3377057Smarks 		error = str_append(dstr, pruname(aclp->a_id, idp,
3387057Smarks 		    sizeof (idp), flags & ACL_NORESOLVE));
3397057Smarks 		if (error == 0)
3407057Smarks 			error = str_append(dstr, ":");
3417057Smarks 		break;
3427057Smarks 
3437057Smarks 	case DEF_GROUP_OBJ:
3447057Smarks 	case GROUP_OBJ:
3457057Smarks 		if (aclp->a_type == GROUP_OBJ)
3467057Smarks 			error = str_append(dstr, "group::");
3477057Smarks 		else
3487057Smarks 			error = str_append(dstr, "defaultgroup::");
3497057Smarks 		break;
3501420Smarks 
3517057Smarks 	case DEF_GROUP:
3527057Smarks 	case GROUP:
3537057Smarks 		if (aclp->a_type == GROUP)
3547057Smarks 			error = str_append(dstr, "group:");
3557057Smarks 		else
3567057Smarks 			error = str_append(dstr, "defaultgroup:");
3577057Smarks 		if (error)
3587057Smarks 			break;
3597057Smarks 		error = str_append(dstr, prgname(aclp->a_id, idp,
3607057Smarks 		    sizeof (idp), flags & ACL_NORESOLVE));
3617057Smarks 		if (error == 0)
3627057Smarks 			error = str_append(dstr, ":");
3637057Smarks 		break;
3647057Smarks 
3657057Smarks 	case DEF_CLASS_OBJ:
3667057Smarks 	case CLASS_OBJ:
3677057Smarks 		if (aclp->a_type == CLASS_OBJ)
3687057Smarks 			error = str_append(dstr, "mask:");
3697057Smarks 		else
3707057Smarks 			error = str_append(dstr, "defaultmask:");
3717057Smarks 		break;
3721420Smarks 
3737057Smarks 	case DEF_OTHER_OBJ:
3747057Smarks 	case OTHER_OBJ:
3757057Smarks 		if (aclp->a_type == OTHER_OBJ)
3767057Smarks 			error = str_append(dstr, "other:");
3777057Smarks 		else
3787057Smarks 			error = str_append(dstr, "defaultother:");
3797057Smarks 		break;
3807057Smarks 
3817057Smarks 	default:
3827057Smarks 		error = 1;
3837057Smarks 		break;
3847057Smarks 	}
3857057Smarks 
3867057Smarks 	return (error);
3877057Smarks }
3887057Smarks 
3897057Smarks /*
3907057Smarks  * compute entry type string such as, owner@:, user:joe, group:staff,...
3917057Smarks  */
3927057Smarks static int
3937057Smarks ace_type_txt(dynaclstr_t *dynstr, ace_t *acep, int flags)
3947057Smarks {
3957057Smarks 	char idp[ID_STR_MAX];
3967057Smarks 	int error;
3977057Smarks 	char *sidp = NULL;
3981420Smarks 
3991420Smarks 	switch (acep->a_flags & ACE_TYPE_FLAGS) {
4001420Smarks 	case ACE_OWNER:
4017057Smarks 		error = str_append(dynstr, OWNERAT_TXT);
4021420Smarks 		break;
4031420Smarks 
4041420Smarks 	case ACE_GROUP|ACE_IDENTIFIER_GROUP:
4057057Smarks 		error = str_append(dynstr, GROUPAT_TXT);
4061420Smarks 		break;
4071420Smarks 
4081420Smarks 	case ACE_IDENTIFIER_GROUP:
4097057Smarks 		if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) {
4107057Smarks 			if (error = str_append(dynstr,
4117057Smarks 			    GROUPSID_TXT))
4127057Smarks 				break;
4137680SMark.Shellenbaum@Sun.COM 			if (error = getsidname(acep->a_who, B_FALSE,
4147680SMark.Shellenbaum@Sun.COM 			    &sidp, flags & ACL_NORESOLVE))
4157680SMark.Shellenbaum@Sun.COM 				break;
4167680SMark.Shellenbaum@Sun.COM 			error = str_append(dynstr, sidp);
4177057Smarks 		} else {
4187057Smarks 			if (error = str_append(dynstr, GROUP_TXT))
4197057Smarks 				break;
4207057Smarks 			error = str_append(dynstr, prgname(acep->a_who, idp,
4217057Smarks 			    sizeof (idp), flags & ACL_NORESOLVE));
4227057Smarks 		}
4237057Smarks 		if (error == 0)
4247057Smarks 			error = str_append(dynstr, ":");
4251420Smarks 		break;
4261420Smarks 
4271420Smarks 	case ACE_EVERYONE:
4287057Smarks 		error = str_append(dynstr, EVERYONEAT_TXT);
4291420Smarks 		break;
4301420Smarks 
4311420Smarks 	case 0:
4327057Smarks 		if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) {
4337057Smarks 			if (error = str_append(dynstr, USERSID_TXT))
4347057Smarks 				break;
4357680SMark.Shellenbaum@Sun.COM 			if (error = getsidname(acep->a_who, B_TRUE,
4367680SMark.Shellenbaum@Sun.COM 			    &sidp, flags & ACL_NORESOLVE))
4377680SMark.Shellenbaum@Sun.COM 				break;
4387680SMark.Shellenbaum@Sun.COM 			error = str_append(dynstr, sidp);
4397057Smarks 		} else {
4407057Smarks 			if (error = str_append(dynstr, USER_TXT))
4417057Smarks 				break;
4427057Smarks 			error = str_append(dynstr, pruname(acep->a_who, idp,
4437057Smarks 			    sizeof (idp), flags & ACL_NORESOLVE));
4447057Smarks 		}
4457057Smarks 		if (error == 0)
4467057Smarks 			error = str_append(dynstr, ":");
4477057Smarks 		break;
4487057Smarks 	default:
4497057Smarks 		error = 0;
4501420Smarks 		break;
4511420Smarks 	}
4521420Smarks 
4537057Smarks 	if (sidp)
4547057Smarks 		free(sidp);
4557057Smarks 	return (error);
4561420Smarks }
4571420Smarks 
4587057Smarks /*
4597057Smarks  * compute string of permissions, such as read_data/write_data or
4607057Smarks  * rwxp,...
4617057Smarks  * The format depends on the flags field which indicates whether the compact
4627057Smarks  * or verbose format should be used.
4637057Smarks  */
4647057Smarks static int
4657057Smarks ace_perm_txt(dynaclstr_t *dstr, uint32_t mask,
4661420Smarks     uint32_t iflags, int isdir, int flags)
4671420Smarks {
4687057Smarks 	int error = 0;
4691420Smarks 
4701420Smarks 	if (flags & ACL_COMPACT_FMT) {
4717057Smarks 		char buf[16];
472789Sahrens 
4731420Smarks 		if (mask & ACE_READ_DATA)
4741420Smarks 			buf[0] = 'r';
4751420Smarks 		else
4761420Smarks 			buf[0] = '-';
4771420Smarks 		if (mask & ACE_WRITE_DATA)
4781420Smarks 			buf[1] = 'w';
4791420Smarks 		else
4801420Smarks 			buf[1] = '-';
4811420Smarks 		if (mask & ACE_EXECUTE)
4821420Smarks 			buf[2] = 'x';
4831420Smarks 		else
4841420Smarks 			buf[2] = '-';
4851420Smarks 		if (mask & ACE_APPEND_DATA)
4861420Smarks 			buf[3] = 'p';
4871420Smarks 		else
4881420Smarks 			buf[3] = '-';
4891420Smarks 		if (mask & ACE_DELETE)
4901420Smarks 			buf[4] = 'd';
4911420Smarks 		else
4921420Smarks 			buf[4] = '-';
4931420Smarks 		if (mask & ACE_DELETE_CHILD)
4941420Smarks 			buf[5] = 'D';
4951420Smarks 		else
4961420Smarks 			buf[5] = '-';
4971420Smarks 		if (mask & ACE_READ_ATTRIBUTES)
4981420Smarks 			buf[6] = 'a';
4991420Smarks 		else
5001420Smarks 			buf[6] = '-';
5011420Smarks 		if (mask & ACE_WRITE_ATTRIBUTES)
5021420Smarks 			buf[7] = 'A';
5031420Smarks 		else
5041420Smarks 			buf[7] = '-';
5051420Smarks 		if (mask & ACE_READ_NAMED_ATTRS)
5061420Smarks 			buf[8] = 'R';
5071420Smarks 		else
5081420Smarks 			buf[8] = '-';
5091420Smarks 		if (mask & ACE_WRITE_NAMED_ATTRS)
5101420Smarks 			buf[9] = 'W';
5111420Smarks 		else
5121420Smarks 			buf[9] = '-';
5131420Smarks 		if (mask & ACE_READ_ACL)
5141420Smarks 			buf[10] = 'c';
5151420Smarks 		else
5161420Smarks 			buf[10] = '-';
5171420Smarks 		if (mask & ACE_WRITE_ACL)
5181420Smarks 			buf[11] = 'C';
5191420Smarks 		else
5201420Smarks 			buf[11] = '-';
5211420Smarks 		if (mask & ACE_WRITE_OWNER)
5221420Smarks 			buf[12] = 'o';
5231420Smarks 		else
5241420Smarks 			buf[12] = '-';
5251420Smarks 		if (mask & ACE_SYNCHRONIZE)
5261420Smarks 			buf[13] = 's';
5271420Smarks 		else
5281420Smarks 			buf[13] = '-';
5297057Smarks 		buf[14] = ':';
5307057Smarks 		buf[15] = '\0';
5317057Smarks 		error = str_append(dstr, buf);
5321420Smarks 	} else {
5331420Smarks 		/*
5341420Smarks 		 * If ACE is a directory, but inheritance indicates its
5351420Smarks 		 * for a file then print permissions for file rather than
5361420Smarks 		 * dir.
5371420Smarks 		 */
5381420Smarks 		if (isdir) {
5391420Smarks 			if (mask & ACE_LIST_DIRECTORY) {
5401420Smarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
5417057Smarks 					error = str_append(dstr,
5427057Smarks 					    READ_DATA_TXT);
5431420Smarks 				} else {
5447057Smarks 					error =
5457057Smarks 					    str_append(dstr, READ_DIR_TXT);
5461420Smarks 				}
5471420Smarks 			}
5487057Smarks 			if (error == 0 && (mask & ACE_ADD_FILE)) {
5491420Smarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
5507057Smarks 					error =
5517057Smarks 					    str_append(dstr, WRITE_DATA_TXT);
5521420Smarks 				} else {
5537057Smarks 					error =
5547057Smarks 					    str_append(dstr, ADD_FILE_TXT);
5551420Smarks 				}
5561420Smarks 			}
5577057Smarks 			if (error == 0 && (mask & ACE_ADD_SUBDIRECTORY)) {
5581420Smarks 				if (iflags == ACE_FILE_INHERIT_ACE) {
5597057Smarks 					error = str_append(dstr,
5607057Smarks 					    APPEND_DATA_TXT);
5611420Smarks 				} else {
5627057Smarks 					error = str_append(dstr,
5637057Smarks 					    ADD_DIR_TXT);
5641420Smarks 				}
5651420Smarks 			}
5661420Smarks 		} else {
5671420Smarks 			if (mask & ACE_READ_DATA) {
5687057Smarks 				error = str_append(dstr, READ_DATA_TXT);
5691420Smarks 			}
5707057Smarks 			if (error == 0 && (mask & ACE_WRITE_DATA)) {
5717057Smarks 				error = str_append(dstr, WRITE_DATA_TXT);
5721420Smarks 			}
5737057Smarks 			if (error == 0 && (mask & ACE_APPEND_DATA)) {
5747057Smarks 				error = str_append(dstr, APPEND_DATA_TXT);
5751420Smarks 			}
5761420Smarks 		}
5777057Smarks 		if (error == 0 && (mask & ACE_READ_NAMED_ATTRS)) {
5787057Smarks 			error = str_append(dstr, READ_XATTR_TXT);
5791420Smarks 		}
5807057Smarks 		if (error == 0 && (mask & ACE_WRITE_NAMED_ATTRS)) {
5817057Smarks 			error = str_append(dstr, WRITE_XATTR_TXT);
5821420Smarks 		}
5837057Smarks 		if (error == 0 && (mask & ACE_EXECUTE)) {
5847057Smarks 			error = str_append(dstr, EXECUTE_TXT);
5851420Smarks 		}
5867057Smarks 		if (error == 0 && (mask & ACE_DELETE_CHILD)) {
5877057Smarks 			error = str_append(dstr, DELETE_CHILD_TXT);
5881420Smarks 		}
5897057Smarks 		if (error == 0 && (mask & ACE_READ_ATTRIBUTES)) {
5907057Smarks 			error = str_append(dstr, READ_ATTRIBUTES_TXT);
5911420Smarks 		}
5927057Smarks 		if (error == 0 && (mask & ACE_WRITE_ATTRIBUTES)) {
5937057Smarks 			error = str_append(dstr, WRITE_ATTRIBUTES_TXT);
5941420Smarks 		}
5957057Smarks 		if (error == 0 && (mask & ACE_DELETE)) {
5967057Smarks 			error = str_append(dstr, DELETE_TXT);
5971420Smarks 		}
5987057Smarks 		if (error == 0 && (mask & ACE_READ_ACL)) {
5997057Smarks 			error = str_append(dstr, READ_ACL_TXT);
6001420Smarks 		}
6017057Smarks 		if (error == 0 && (mask & ACE_WRITE_ACL)) {
6027057Smarks 			error = str_append(dstr, WRITE_ACL_TXT);
6031420Smarks 		}
6047057Smarks 		if (error == 0 && (mask & ACE_WRITE_OWNER)) {
6057057Smarks 			error = str_append(dstr, WRITE_OWNER_TXT);
6061420Smarks 		}
6077057Smarks 		if (error == 0 && (mask & ACE_SYNCHRONIZE)) {
6087057Smarks 			error = str_append(dstr, SYNCHRONIZE_TXT);
6091420Smarks 		}
6107057Smarks 		if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') {
6117057Smarks 			dstr->d_aclexport[--dstr->d_pos] = '\0';
6127057Smarks 		}
6137057Smarks 		if (error == 0)
6147057Smarks 			error = str_append(dstr, ":");
6151420Smarks 	}
6167057Smarks 	return (error);
6171420Smarks }
6181420Smarks 
6197057Smarks /*
6207057Smarks  * compute string of access type, such as allow, deny, ...
6217057Smarks  */
6227057Smarks static int
6237057Smarks ace_access_txt(dynaclstr_t *dstr, int type)
6241420Smarks {
6257057Smarks 	int error;
6261420Smarks 
6277057Smarks 	if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
6287057Smarks 		error = str_append(dstr, ALLOW_TXT);
6297057Smarks 	else if (type == ACE_ACCESS_DENIED_ACE_TYPE)
6307057Smarks 		error = str_append(dstr, DENY_TXT);
6317057Smarks 	else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE)
6327057Smarks 		error = str_append(dstr, AUDIT_TXT);
6337057Smarks 	else if (type == ACE_SYSTEM_ALARM_ACE_TYPE)
6347057Smarks 		error = str_append(dstr, ALARM_TXT);
6357057Smarks 	else
6367057Smarks 		error = str_append(dstr, UNKNOWN_TXT);
6371420Smarks 
6387057Smarks 	return (error);
6391420Smarks }
6401420Smarks 
6417057Smarks static int
6427057Smarks ace_inherit_txt(dynaclstr_t *dstr, uint32_t iflags, int flags)
6431420Smarks {
6447057Smarks 	int error = 0;
645789Sahrens 
6461420Smarks 	if (flags & ACL_COMPACT_FMT) {
6477057Smarks 		char buf[9];
6487057Smarks 
6491420Smarks 		if (iflags & ACE_FILE_INHERIT_ACE)
6501420Smarks 			buf[0] = 'f';
6511420Smarks 		else
6521420Smarks 			buf[0] = '-';
6531420Smarks 		if (iflags & ACE_DIRECTORY_INHERIT_ACE)
6541420Smarks 			buf[1] = 'd';
6551420Smarks 		else
6561420Smarks 			buf[1] = '-';
6571420Smarks 		if (iflags & ACE_INHERIT_ONLY_ACE)
6581420Smarks 			buf[2] = 'i';
6591420Smarks 		else
6601420Smarks 			buf[2] = '-';
6611420Smarks 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)
6621420Smarks 			buf[3] = 'n';
6631420Smarks 		else
6641420Smarks 			buf[3] = '-';
6651420Smarks 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
6661420Smarks 			buf[4] = 'S';
6671420Smarks 		else
6681420Smarks 			buf[4] = '-';
6691420Smarks 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG)
6701420Smarks 			buf[5] = 'F';
6711420Smarks 		else
6721420Smarks 			buf[5] = '-';
6735331Samw 		if (iflags & ACE_INHERITED_ACE)
6745331Samw 			buf[6] = 'I';
6755331Samw 		else
6765331Samw 			buf[6] = '-';
6777057Smarks 		buf[7] = ':';
6787057Smarks 		buf[8] = '\0';
6797057Smarks 		error = str_append(dstr, buf);
6801420Smarks 	} else {
6811420Smarks 		if (iflags & ACE_FILE_INHERIT_ACE) {
6827057Smarks 			error = str_append(dstr, FILE_INHERIT_TXT);
6831420Smarks 		}
6847057Smarks 		if (error == 0 && (iflags & ACE_DIRECTORY_INHERIT_ACE)) {
6857057Smarks 			error = str_append(dstr, DIR_INHERIT_TXT);
6861420Smarks 		}
6877057Smarks 		if (error == 0 && (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) {
6887057Smarks 			error = str_append(dstr, NO_PROPAGATE_TXT);
6891420Smarks 		}
6907057Smarks 		if (error == 0 && (iflags & ACE_INHERIT_ONLY_ACE)) {
6917057Smarks 			error = str_append(dstr, INHERIT_ONLY_TXT);
6921420Smarks 		}
6937057Smarks 		if (error == 0 && (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)) {
6947057Smarks 			error = str_append(dstr, SUCCESSFUL_ACCESS_TXT);
6955331Samw 		}
6967057Smarks 		if (error == 0 && (iflags & ACE_FAILED_ACCESS_ACE_FLAG)) {
6977057Smarks 			error = str_append(dstr, FAILED_ACCESS_TXT);
6985331Samw 		}
6997057Smarks 		if (error == 0 && (iflags & ACE_INHERITED_ACE)) {
7007057Smarks 			error = str_append(dstr, INHERITED_ACE_TXT);
7015331Samw 		}
7027057Smarks 		if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') {
7037057Smarks 			dstr->d_aclexport[--dstr->d_pos] = '\0';
7047057Smarks 			error = str_append(dstr, ":");
7057057Smarks 		}
7061420Smarks 	}
7071420Smarks 
7087057Smarks 	return (error);
709789Sahrens }
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate /*
7120Sstevel@tonic-gate  * Convert internal acl representation to external representation.
7130Sstevel@tonic-gate  *
7140Sstevel@tonic-gate  * The length of a non-owning user name or non-owning group name ie entries
7150Sstevel@tonic-gate  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
7160Sstevel@tonic-gate  * thus check the length of these entries, and if greater than LOGNAME_MAX,
7170Sstevel@tonic-gate  * we realloc() via increase_length().
7180Sstevel@tonic-gate  *
7190Sstevel@tonic-gate  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
7200Sstevel@tonic-gate  * adhered to.
7210Sstevel@tonic-gate  */
7221420Smarks 
7231420Smarks /*
7241420Smarks  * acltotext() converts each ACL entry to look like this:
7251420Smarks  *
7261420Smarks  *    entry_type:uid^gid^name:perms[:id]
7271420Smarks  *
7281420Smarks  * The maximum length of entry_type is 14 ("defaultgroup::" and
7291420Smarks  * "defaultother::") hence ENTRYTYPELEN is set to 14.
7301420Smarks  *
7311420Smarks  * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
7321420Smarks  * however the ID could be a number so we therefore use ID_STR_MAX
7331420Smarks  *
7341420Smarks  * The length of a perms entry is 4 to allow for the comma appended to each
7351420Smarks  * to each acl entry.  Hence PERMS is set to 4.
7361420Smarks  */
7371420Smarks 
7381420Smarks #define	ENTRYTYPELEN	14
7391420Smarks #define	PERMS		4
7401420Smarks #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
7411420Smarks 
7420Sstevel@tonic-gate char *
7431420Smarks aclent_acltotext(aclent_t  *aclp, int aclcnt, int flags)
7440Sstevel@tonic-gate {
7457057Smarks 	dynaclstr_t 	*dstr;
7467680SMark.Shellenbaum@Sun.COM 	char		*aclexport = NULL;
7477057Smarks 	int		i;
7487057Smarks 	int 		error = 0;
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 	if (aclp == NULL)
7510Sstevel@tonic-gate 		return (NULL);
7527057Smarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
7530Sstevel@tonic-gate 		return (NULL);
7547057Smarks 	dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE;
7557057Smarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
7560Sstevel@tonic-gate 		free(dstr);
7570Sstevel@tonic-gate 		return (NULL);
7580Sstevel@tonic-gate 	}
7597057Smarks 	*dstr->d_aclexport = '\0';
7607057Smarks 	dstr->d_pos = 0;
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	for (i = 0; i < aclcnt; i++, aclp++) {
7637057Smarks 		if (error = aclent_type_txt(dstr, aclp, flags))
7640Sstevel@tonic-gate 			break;
7657057Smarks 		if (error = aclent_perm_txt(dstr, aclp->a_perm))
7660Sstevel@tonic-gate 			break;
7671420Smarks 
7681420Smarks 		if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) ||
7691420Smarks 		    (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) ||
7701420Smarks 		    (aclp->a_type == DEF_GROUP))) {
7717057Smarks 			char id[ID_STR_MAX], *idstr;
7727057Smarks 
7737057Smarks 			if (error = str_append(dstr, ":"))
7747057Smarks 				break;
7751420Smarks 			id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */
7761420Smarks 			idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]);
7777057Smarks 			if (error = str_append(dstr, idstr))
7787057Smarks 				break;
7791420Smarks 		}
7800Sstevel@tonic-gate 		if (i < aclcnt - 1)
7817057Smarks 			if (error = str_append(dstr, ","))
7827057Smarks 				break;
7830Sstevel@tonic-gate 	}
7847057Smarks 	if (error) {
7857057Smarks 		if (dstr->d_aclexport)
7867057Smarks 			free(dstr->d_aclexport);
7877057Smarks 	} else {
7887057Smarks 		aclexport = dstr->d_aclexport;
7897057Smarks 	}
7900Sstevel@tonic-gate 	free(dstr);
7910Sstevel@tonic-gate 	return (aclexport);
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate 
7941420Smarks char *
7951420Smarks acltotext(aclent_t *aclp, int aclcnt)
7960Sstevel@tonic-gate {
7971420Smarks 	return (aclent_acltotext(aclp, aclcnt, 0));
7981420Smarks }
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 
801789Sahrens aclent_t *
802789Sahrens aclfromtext(char *aclstr, int *aclcnt)
803789Sahrens {
804789Sahrens 	acl_t *aclp;
805789Sahrens 	aclent_t *aclentp;
806789Sahrens 	int error;
807789Sahrens 
8081420Smarks 	error = acl_fromtext(aclstr, &aclp);
809789Sahrens 	if (error)
810789Sahrens 		return (NULL);
811789Sahrens 
812789Sahrens 	aclentp = aclp->acl_aclp;
813789Sahrens 	aclp->acl_aclp = NULL;
8141420Smarks 	*aclcnt = aclp->acl_cnt;
815789Sahrens 
8161420Smarks 	acl_free(aclp);
817789Sahrens 	return (aclentp);
818789Sahrens }
819789Sahrens 
820789Sahrens 
8217057Smarks /*
8227680SMark.Shellenbaum@Sun.COM  * Append string onto dynaclstr_t.
8237680SMark.Shellenbaum@Sun.COM  *
8247680SMark.Shellenbaum@Sun.COM  * Return 0 on success, 1 for failure.
8257057Smarks  */
8267057Smarks static int
8277057Smarks str_append(dynaclstr_t *dstr, char *newstr)
8280Sstevel@tonic-gate {
8297057Smarks 	size_t len = strlen(newstr);
8307057Smarks 
8317057Smarks 	if ((len + dstr->d_pos) >= dstr->d_bufsize) {
8327057Smarks 		dstr->d_aclexport = realloc(dstr->d_aclexport,
8337057Smarks 		    dstr->d_bufsize + len + 1);
8347057Smarks 		if (dstr->d_aclexport == NULL)
8357057Smarks 			return (1);
8367057Smarks 		dstr->d_bufsize += len;
8377057Smarks 	}
8387057Smarks 	(void) strcat(&dstr->d_aclexport[dstr->d_pos], newstr);
8397057Smarks 	dstr->d_pos += len;
8407057Smarks 	return (0);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate 
8437057Smarks static int
8447057Smarks aclent_perm_txt(dynaclstr_t *dstr, o_mode_t perm)
8450Sstevel@tonic-gate {
8467057Smarks 	char buf[4];
8470Sstevel@tonic-gate 
8487057Smarks 	if (perm & S_IROTH)
8497057Smarks 		buf[0] = 'r';
8507057Smarks 	else
8517057Smarks 		buf[0] = '-';
8527057Smarks 	if (perm & S_IWOTH)
8537057Smarks 		buf[1] = 'w';
8547057Smarks 	else
8557057Smarks 		buf[1] = '-';
8567057Smarks 	if (perm & S_IXOTH)
8577057Smarks 		buf[2] = 'x';
8587057Smarks 	else
8597057Smarks 		buf[2] = '-';
8607057Smarks 	buf[3] = '\0';
8617057Smarks 	return (str_append(dstr, buf));
8620Sstevel@tonic-gate }
863789Sahrens 
864789Sahrens /*
8651420Smarks  * ace_acltotext() convert each ace formatted acl to look like this:
866789Sahrens  *
8671420Smarks  * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
868789Sahrens  *
869789Sahrens  * The maximum length of entry_type is 5 ("group")
870789Sahrens  *
8711420Smarks  * The max length of a uid^gid^name entry (in theory) is 8,
8721420Smarks  * however id could be a number so we therefore use ID_STR_MAX
873789Sahrens  *
874789Sahrens  * The length of a perms entry is 144 i.e read_data/write_data...
875789Sahrens  * to each acl entry.
876789Sahrens  *
8775331Samw  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access
8785331Samw  *         /failed_access
879789Sahrens  *
880789Sahrens  */
881789Sahrens 
882789Sahrens #define	ACE_ENTRYTYPLEN		6
8835331Samw #define	IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \
8845331Samw 	"successful_access/failed_access/inherited"
8855331Samw #define	IFLAGS_SIZE		(sizeof (IFLAGS_STR) - 1)
8861420Smarks #define	ACCESS_TYPE_SIZE	7	/* if unknown */
887789Sahrens #define	COLON_CNT		3
888789Sahrens #define	PERMS_LEN		216
8895331Samw #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \
8901420Smarks     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
891789Sahrens 
892789Sahrens static char *
8931420Smarks ace_acltotext(acl_t *aceaclp, int flags)
894789Sahrens {
895789Sahrens 	ace_t		*aclp = aceaclp->acl_aclp;
896789Sahrens 	int		aclcnt = aceaclp->acl_cnt;
8977057Smarks 	int		i;
8987057Smarks 	int		error = 0;
8997057Smarks 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
9007057Smarks 	dynaclstr_t 	*dstr;
9017680SMark.Shellenbaum@Sun.COM 	char		*aclexport = NULL;
90211605SGowtham.Thommandra@Sun.COM 	char		*rawsidp = NULL;
903789Sahrens 
904789Sahrens 	if (aclp == NULL)
905789Sahrens 		return (NULL);
906789Sahrens 
9077057Smarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
9087057Smarks 		return (NULL);
9097057Smarks 	dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE;
9107057Smarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
9117057Smarks 		free(dstr);
9127057Smarks 		return (NULL);
9137057Smarks 	}
9147057Smarks 	*dstr->d_aclexport = '\0';
9157057Smarks 	dstr->d_pos = 0;
9167057Smarks 
917789Sahrens 	for (i = 0; i < aclcnt; i++, aclp++) {
9181420Smarks 
9197057Smarks 		if (error = ace_type_txt(dstr, aclp, flags))
9207057Smarks 			break;
9217057Smarks 		if (error = ace_perm_txt(dstr, aclp->a_access_mask,
9227057Smarks 		    aclp->a_flags, isdir, flags))
9237057Smarks 			break;
9247057Smarks 		if (error = ace_inherit_txt(dstr, aclp->a_flags, flags))
9257057Smarks 			break;
9267057Smarks 		if (error = ace_access_txt(dstr, aclp->a_type))
9277057Smarks 			break;
928789Sahrens 
9291420Smarks 		if ((flags & ACL_APPEND_ID) &&
9301420Smarks 		    (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ||
9311420Smarks 		    ((aclp->a_flags & ACE_TYPE_FLAGS) ==
9321420Smarks 		    ACE_IDENTIFIER_GROUP))) {
9337057Smarks 			char id[ID_STR_MAX], *idstr;
9347057Smarks 
9357057Smarks 			if (error = str_append(dstr, ":"))
9367057Smarks 				break;
9378268SMark.Shellenbaum@Sun.COM 
9388268SMark.Shellenbaum@Sun.COM 			rawsidp = NULL;
9398268SMark.Shellenbaum@Sun.COM 			id[ID_STR_MAX -1] = '\0'; /* null terminate */
9408268SMark.Shellenbaum@Sun.COM 			if (aclp->a_who > MAXUID && (flags & ACL_SID_FMT)) {
9418268SMark.Shellenbaum@Sun.COM 
9428268SMark.Shellenbaum@Sun.COM 				error = getsidname(aclp->a_who,
9438268SMark.Shellenbaum@Sun.COM 				    ((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ?
9448268SMark.Shellenbaum@Sun.COM 				    B_TRUE : B_FALSE, &idstr, 1);
94511605SGowtham.Thommandra@Sun.COM 				rawsidp = idstr;
9468268SMark.Shellenbaum@Sun.COM 				if (error)
9478268SMark.Shellenbaum@Sun.COM 					break;
9488268SMark.Shellenbaum@Sun.COM 			} else if (aclp->a_who > MAXUID &&
9498268SMark.Shellenbaum@Sun.COM 			    !(flags & ACL_NORESOLVE)) {
9508268SMark.Shellenbaum@Sun.COM 				idstr = lltostr(UID_NOBODY,
9518268SMark.Shellenbaum@Sun.COM 				    &id[ID_STR_MAX - 1]);
9528268SMark.Shellenbaum@Sun.COM 			} else {
9538268SMark.Shellenbaum@Sun.COM 				idstr = lltostr(aclp->a_who,
9548268SMark.Shellenbaum@Sun.COM 				    &id[ID_STR_MAX - 1]);
9558268SMark.Shellenbaum@Sun.COM 			}
9567057Smarks 			if (error = str_append(dstr, idstr))
9577057Smarks 				break;
95811605SGowtham.Thommandra@Sun.COM 			if (rawsidp) {
9598268SMark.Shellenbaum@Sun.COM 				free(rawsidp);
96011605SGowtham.Thommandra@Sun.COM 				rawsidp = NULL;
96111605SGowtham.Thommandra@Sun.COM 			}
962789Sahrens 		}
9631420Smarks 		if (i < aclcnt - 1) {
9647057Smarks 			if (error = str_append(dstr, ","))
9657057Smarks 				break;
966789Sahrens 		}
967789Sahrens 	}
96811605SGowtham.Thommandra@Sun.COM 
96911605SGowtham.Thommandra@Sun.COM 	if (rawsidp)
97011605SGowtham.Thommandra@Sun.COM 		free(rawsidp);
9717057Smarks 	if (error) {
9727057Smarks 		if (dstr->d_aclexport)
9737057Smarks 			free(dstr->d_aclexport);
9747057Smarks 	} else {
9757057Smarks 		aclexport = dstr->d_aclexport;
9767057Smarks 	}
9777057Smarks 	free(dstr);
978789Sahrens 	return (aclexport);
979789Sahrens }
980789Sahrens 
9811420Smarks char *
9821420Smarks acl_totext(acl_t *aclp, int flags)
983789Sahrens {
9841420Smarks 	char *txtp;
985789Sahrens 
986789Sahrens 	if (aclp == NULL)
987789Sahrens 		return (NULL);
988789Sahrens 
989789Sahrens 	switch (aclp->acl_type) {
990789Sahrens 	case ACE_T:
9911420Smarks 		txtp = ace_acltotext(aclp, flags);
9921420Smarks 		break;
993789Sahrens 	case ACLENT_T:
9941420Smarks 		txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags);
9951420Smarks 		break;
996789Sahrens 	}
9971420Smarks 
9981420Smarks 	return (txtp);
999789Sahrens }
1000789Sahrens 
1001789Sahrens int
1002789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp)
1003789Sahrens {
10041420Smarks 	int error;
10051420Smarks 	char *buf;
10061420Smarks 
10071420Smarks 	buf = malloc(strlen(acltextp) + 2);
10081420Smarks 	if (buf == NULL)
10091420Smarks 		return (EACL_MEM_ERROR);
10101420Smarks 	strcpy(buf, acltextp);
10111420Smarks 	strcat(buf, "\n");
1012*11963SAfshin.Ardakani@Sun.COM 
1013*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&yymutex);
10141420Smarks 	yybuf = buf;
10151420Smarks 	yyreset();
10161420Smarks 	error = yyparse();
10171420Smarks 	free(buf);
10181420Smarks 
10191420Smarks 	if (yyacl) {
10201420Smarks 		if (error == 0)
10211420Smarks 			*ret_aclp = yyacl;
10221420Smarks 		else {
10231420Smarks 			acl_free(yyacl);
10241420Smarks 		}
10251420Smarks 		yyacl = NULL;
10261420Smarks 	}
1027*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&yymutex);
1028*11963SAfshin.Ardakani@Sun.COM 
10291420Smarks 	return (error);
10301420Smarks }
10311420Smarks 
10321420Smarks int
10331420Smarks acl_parse(const char *acltextp, acl_t **aclp)
10341420Smarks {
1035789Sahrens 	int error;
1036789Sahrens 
10371420Smarks 	yyinteractive = 1;
10381420Smarks 	error = acl_fromtext(acltextp, aclp);
10391420Smarks 	yyinteractive = 0;
10401420Smarks 	return (error);
10411420Smarks }
10421420Smarks 
10431420Smarks static void
10441420Smarks ace_compact_printacl(acl_t *aclp)
10451420Smarks {
10461420Smarks 	int cnt;
10471420Smarks 	ace_t *acep;
10487057Smarks 	dynaclstr_t *dstr;
10497057Smarks 	int len;
1050789Sahrens 
10517057Smarks 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
10527057Smarks 		return;
10537057Smarks 	dstr->d_bufsize = ACE_ENTRY_SIZE;
10547057Smarks 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
10557057Smarks 		free(dstr);
10567057Smarks 		return;
10577057Smarks 	}
10587057Smarks 	*dstr->d_aclexport = '\0';
10597057Smarks 
10607057Smarks 	dstr->d_pos = 0;
10611420Smarks 	for (cnt = 0, acep = aclp->acl_aclp;
10621420Smarks 	    cnt != aclp->acl_cnt; cnt++, acep++) {
10637057Smarks 		dstr->d_aclexport[0] = '\0';
10647057Smarks 		dstr->d_pos = 0;
10657057Smarks 
10667057Smarks 		if (ace_type_txt(dstr, acep, 0))
10677057Smarks 			break;
10687057Smarks 		len = strlen(&dstr->d_aclexport[0]);
10697057Smarks 		if (ace_perm_txt(dstr, acep->a_access_mask, acep->a_flags,
10707057Smarks 		    aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT))
10717057Smarks 			break;
10727057Smarks 		if (ace_inherit_txt(dstr, acep->a_flags, ACL_COMPACT_FMT))
10737057Smarks 			break;
10747057Smarks 		if (ace_access_txt(dstr, acep->a_type) == -1)
10757057Smarks 			break;
10767057Smarks 		(void) printf("    %20.*s%s\n", len, dstr->d_aclexport,
10777057Smarks 		    &dstr->d_aclexport[len]);
10781420Smarks 	}
10797057Smarks 
10807057Smarks 	if (dstr->d_aclexport)
10817057Smarks 		free(dstr->d_aclexport);
10827057Smarks 	free(dstr);
10831420Smarks }
1084789Sahrens 
10851420Smarks static void
10861420Smarks ace_printacl(acl_t *aclp, int cols, int compact)
10871420Smarks {
10881420Smarks 	int  slot = 0;
10891420Smarks 	char *token;
10901420Smarks 	char *acltext;
10911420Smarks 
10921420Smarks 	if (compact) {
10931420Smarks 		ace_compact_printacl(aclp);
10941420Smarks 		return;
1095789Sahrens 	}
1096789Sahrens 
10971420Smarks 	acltext = acl_totext(aclp, 0);
10981420Smarks 
10991420Smarks 	if (acltext == NULL)
11001420Smarks 		return;
11011420Smarks 
11021420Smarks 	token = strtok(acltext, ",");
11031420Smarks 	if (token == NULL) {
11041420Smarks 		free(acltext);
11051420Smarks 		return;
1106789Sahrens 	}
1107789Sahrens 
11081420Smarks 	do {
11091420Smarks 		(void) printf("     %d:", slot++);
11101420Smarks 		split_line(token, cols - 5);
11111420Smarks 	} while (token = strtok(NULL, ","));
11121420Smarks 	free(acltext);
11131420Smarks }
11141420Smarks 
11151420Smarks /*
11161420Smarks  * pretty print an ACL.
11171420Smarks  * For aclent_t ACL's the format is
11181420Smarks  * similar to the old format used by getfacl,
11191420Smarks  * with the addition of adding a "slot" number
11201420Smarks  * before each entry.
11211420Smarks  *
11221420Smarks  * for ace_t ACL's the cols variable will break up
11231420Smarks  * the long lines into multiple lines and will also
11241420Smarks  * print a "slot" number.
11251420Smarks  */
11261420Smarks void
11271420Smarks acl_printacl(acl_t *aclp, int cols, int compact)
11281420Smarks {
11291420Smarks 
11301420Smarks 	switch (aclp->acl_type) {
11311420Smarks 	case ACLENT_T:
11321420Smarks 		aclent_printacl(aclp);
11331420Smarks 		break;
11341420Smarks 	case ACE_T:
11351420Smarks 		ace_printacl(aclp, cols, compact);
11361420Smarks 		break;
11371420Smarks 	}
11381420Smarks }
11391420Smarks 
11401420Smarks typedef struct value_table {
11411420Smarks 	char		p_letter; /* perm letter such as 'r' */
11421420Smarks 	uint32_t	p_value; /* value for perm when pletter found */
11431420Smarks } value_table_t;
11441420Smarks 
11451420Smarks /*
11465331Samw  * The permission tables are laid out in positional order
11471420Smarks  * a '-' character will indicate a permission at a given
11481420Smarks  * position is not specified.  The '-' is not part of the
11491420Smarks  * table, but will be checked for in the permission computation
11501420Smarks  * routine.
11511420Smarks  */
11525331Samw value_table_t ace_perm_table[] = {
11531420Smarks 	{ 'r', ACE_READ_DATA},
11541420Smarks 	{ 'w', ACE_WRITE_DATA},
11551420Smarks 	{ 'x', ACE_EXECUTE},
11561420Smarks 	{ 'p', ACE_APPEND_DATA},
11571420Smarks 	{ 'd', ACE_DELETE},
11581420Smarks 	{ 'D', ACE_DELETE_CHILD},
11591420Smarks 	{ 'a', ACE_READ_ATTRIBUTES},
11601420Smarks 	{ 'A', ACE_WRITE_ATTRIBUTES},
11611420Smarks 	{ 'R', ACE_READ_NAMED_ATTRS},
11621420Smarks 	{ 'W', ACE_WRITE_NAMED_ATTRS},
11631420Smarks 	{ 'c', ACE_READ_ACL},
11641420Smarks 	{ 'C', ACE_WRITE_ACL},
11651420Smarks 	{ 'o', ACE_WRITE_OWNER},
11661420Smarks 	{ 's', ACE_SYNCHRONIZE}
11671420Smarks };
11681420Smarks 
11695331Samw #define	ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t))
11701420Smarks 
11715331Samw value_table_t aclent_perm_table[] = {
11721420Smarks 	{ 'r', S_IROTH},
11731420Smarks 	{ 'w', S_IWOTH},
11741420Smarks 	{ 'x', S_IXOTH}
11751420Smarks };
11761420Smarks 
11775331Samw #define	ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t))
11785331Samw 
11795331Samw value_table_t inherit_table[] = {
11801420Smarks 	{'f', ACE_FILE_INHERIT_ACE},
11811420Smarks 	{'d', ACE_DIRECTORY_INHERIT_ACE},
11821420Smarks 	{'i', ACE_INHERIT_ONLY_ACE},
11831420Smarks 	{'n', ACE_NO_PROPAGATE_INHERIT_ACE},
11841420Smarks 	{'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
11855331Samw 	{'F', ACE_FAILED_ACCESS_ACE_FLAG},
11865331Samw 	{'I', ACE_INHERITED_ACE}
11871420Smarks };
11881420Smarks 
11895331Samw #define	IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t))
11906269Smarks #define	IFLAG_COUNT_V1 6 /* Older version compatibility */
11915331Samw 
11921420Smarks /*
11931420Smarks  * compute value from a permission table or inheritance table
11941420Smarks  * based on string passed in.  If positional is set then
11951420Smarks  * string must match order in permtab, otherwise any order
11961420Smarks  * is allowed.
11971420Smarks  */
11981420Smarks int
11991420Smarks compute_values(value_table_t *permtab, int count,
12001420Smarks     char *permstr, int positional, uint32_t *mask)
12011420Smarks {
12021420Smarks 	uint32_t perm_val = 0;
12031420Smarks 	char *pstr;
12041420Smarks 	int i, found;
12051420Smarks 
12061420Smarks 	if (count < 0)
12071420Smarks 		return (1);
12081420Smarks 
12091420Smarks 	if (positional) {
12101420Smarks 		for (i = 0, pstr = permstr; i != count && pstr &&
12111420Smarks 		    *pstr; i++, pstr++) {
12121420Smarks 			if (*pstr == permtab[i].p_letter) {
12131420Smarks 				perm_val |= permtab[i].p_value;
12141420Smarks 			} else if (*pstr != '-') {
12151420Smarks 				return (1);
12161420Smarks 			}
1217789Sahrens 		}
12181420Smarks 	} else {  /* random order single letters with no '-' */
12191420Smarks 		for (pstr = permstr; pstr && *pstr; pstr++) {
12201420Smarks 			for (found = 0, i = 0; i != count; i++) {
12211420Smarks 				if (*pstr == permtab[i].p_letter) {
12221420Smarks 					perm_val |= permtab[i].p_value;
12231420Smarks 					found = 1;
12241420Smarks 					break;
12251420Smarks 				}
12261420Smarks 			}
12271420Smarks 			if (found == 0)
12281420Smarks 				return (1);
12291420Smarks 		}
1230789Sahrens 	}
1231789Sahrens 
12321420Smarks 	*mask = perm_val;
12331420Smarks 	return (0);
12341420Smarks }
1235789Sahrens 
12366269Smarks 
12376269Smarks int
12386269Smarks ace_inherit_helper(char *str, uint32_t *imask, int table_length)
12396269Smarks {
12406269Smarks 	int rc = 0;
12416269Smarks 
12426269Smarks 	if (strlen(str) == table_length) {
12436269Smarks 		/*
12446269Smarks 		 * If the string == table_length then first check to see it's
12456269Smarks 		 * in positional format.  If that fails then see if it's in
12466269Smarks 		 * non-positional format.
12476269Smarks 		 */
12486269Smarks 		if (compute_values(inherit_table, table_length, str,
12496269Smarks 		    1, imask) && compute_values(inherit_table,
12506269Smarks 		    table_length, str, 0, imask)) {
12516269Smarks 			rc = 1;
12526269Smarks 		}
12536269Smarks 	} else {
12546269Smarks 		rc = compute_values(inherit_table, table_length, str, 0, imask);
12556269Smarks 	}
12566269Smarks 
12576269Smarks 	return (rc ? EACL_INHERIT_ERROR : 0);
12586269Smarks }
12596269Smarks 
12601420Smarks /*
12611420Smarks  * compute value for inheritance flags.
12621420Smarks  */
12631420Smarks int
12641420Smarks compute_ace_inherit(char *str, uint32_t *imask)
12651420Smarks {
12666269Smarks 	int rc = 0;
1267789Sahrens 
12686269Smarks 	rc = ace_inherit_helper(str, imask, IFLAG_COUNT);
12696269Smarks 
12706269Smarks 	if (rc && strlen(str) != IFLAG_COUNT) {
12711420Smarks 
12726269Smarks 		/* is it an old formatted inherit string? */
12736269Smarks 		rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1);
12746269Smarks 	}
12751420Smarks 
12766269Smarks 	return (rc);
1277789Sahrens }
12781420Smarks 
12791420Smarks 
12801420Smarks /*
12811420Smarks  * compute value for ACE permissions.
12821420Smarks  */
12831420Smarks int
12841420Smarks compute_ace_perms(char *str, uint32_t *mask)
12851420Smarks {
12861420Smarks 	int positional = 0;
12871420Smarks 	int error;
12881420Smarks 
12891420Smarks 	if (strlen(str) == ACE_PERM_COUNT)
12901420Smarks 		positional = 1;
12911420Smarks 
12921420Smarks 	error = compute_values(ace_perm_table, ACE_PERM_COUNT,
12931420Smarks 	    str, positional, mask);
12941420Smarks 
12951420Smarks 	if (error && positional) {
12961420Smarks 		/*
12971420Smarks 		 * If positional was set, then make sure permissions
12981420Smarks 		 * aren't actually valid in non positional case where
12991420Smarks 		 * all permissions are specified, just in random order.
13001420Smarks 		 */
13011420Smarks 		error = compute_values(ace_perm_table,
13021420Smarks 		    ACE_PERM_COUNT, str, 0, mask);
13031420Smarks 	}
13041420Smarks 	if (error)
13051420Smarks 		error = EACL_PERM_MASK_ERROR;
13061420Smarks 
13071420Smarks 	return (error);
13081420Smarks }
13091420Smarks 
13101420Smarks 
13111420Smarks 
13121420Smarks /*
13131420Smarks  * compute values for aclent permissions.
13141420Smarks  */
13151420Smarks int
13161420Smarks compute_aclent_perms(char *str, o_mode_t *mask)
13171420Smarks {
13181420Smarks 	int error;
13191420Smarks 	uint32_t pmask;
13201420Smarks 
13211420Smarks 	if (strlen(str) != ACLENT_PERM_COUNT)
13221420Smarks 		return (EACL_PERM_MASK_ERROR);
13231420Smarks 
13241420Smarks 	*mask = 0;
13251420Smarks 	error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT,
13261420Smarks 	    str, 1, &pmask);
13271420Smarks 	if (error == 0) {
13281420Smarks 		*mask = (o_mode_t)pmask;
13291420Smarks 	} else
13301420Smarks 		error = EACL_PERM_MASK_ERROR;
13311420Smarks 	return (error);
13321420Smarks }
13331420Smarks 
13341420Smarks /*
13351420Smarks  * determine ACE permissions.
13361420Smarks  */
13371420Smarks int
13381420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask)
13391420Smarks {
13401420Smarks 	int error;
13411420Smarks 
13421420Smarks 	if (aclperm->perm_style == PERM_TYPE_EMPTY) {
13431420Smarks 		*mask = 0;
13441420Smarks 		return (0);
13451420Smarks 	}
13461420Smarks 
13471420Smarks 	if (aclperm->perm_style == PERM_TYPE_ACE) {
13481420Smarks 		*mask = aclperm->perm_val;
13491420Smarks 		return (0);
13501420Smarks 	}
13511420Smarks 
13521420Smarks 	error = compute_ace_perms(aclperm->perm_str, mask);
13531420Smarks 	if (error) {
13541567Smarks 		acl_error(dgettext(TEXT_DOMAIN,
13551567Smarks 		    "Invalid permission(s) '%s' specified\n"),
13561420Smarks 		    aclperm->perm_str);
13571420Smarks 		return (EACL_PERM_MASK_ERROR);
13581420Smarks 	}
13591420Smarks 
13601420Smarks 	return (0);
13611420Smarks }
1362