xref: /titanic_52/usr/src/lib/libsec/common/acltext.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <grp.h>
317c478bd9Sstevel@tonic-gate #include <pwd.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <limits.h>
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*fa9e4066Sahrens #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <sys/param.h>
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <sys/acl.h>
39*fa9e4066Sahrens #include <aclutils.h>
40*fa9e4066Sahrens #include <libintl.h>
41*fa9e4066Sahrens 
42*fa9e4066Sahrens 
43*fa9e4066Sahrens extern acl_t *acl_alloc(enum acl_type);
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * acltotext() converts each ACL entry to look like this:
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  *    entry_type:uid^gid^name:perms
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * The maximum length of entry_type is 14 ("defaultgroup::" and
517c478bd9Sstevel@tonic-gate  * "defaultother::") hence ENTRYTYPELEN is set to 14.
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  * The max length of a uid^gid^name entry (in theory) is 8, hence we use
547c478bd9Sstevel@tonic-gate  * LOGNAME_MAX.
557c478bd9Sstevel@tonic-gate  *
567c478bd9Sstevel@tonic-gate  * The length of a perms entry is 4 to allow for the comma appended to each
577c478bd9Sstevel@tonic-gate  * to each acl entry.  Hence PERMS is set to 4.
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #define	ENTRYTYPELEN	14
617c478bd9Sstevel@tonic-gate #define	PERMS		4
627c478bd9Sstevel@tonic-gate #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + LOGNAME_MAX + PERMS)
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate struct dynaclstr {
657c478bd9Sstevel@tonic-gate 	size_t bufsize;		/* current size of aclexport */
667c478bd9Sstevel@tonic-gate 	char *aclexport;
677c478bd9Sstevel@tonic-gate };
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate static char *strappend(char *, char *);
707c478bd9Sstevel@tonic-gate static char *convert_perm(char *, o_mode_t);
717c478bd9Sstevel@tonic-gate static int increase_length(struct dynaclstr *, size_t);
727c478bd9Sstevel@tonic-gate 
73*fa9e4066Sahrens static int
74*fa9e4066Sahrens acl_str_to_id(char *str, int *id)
75*fa9e4066Sahrens {
76*fa9e4066Sahrens 	char *end;
77*fa9e4066Sahrens 	uid_t value;
78*fa9e4066Sahrens 
79*fa9e4066Sahrens 	value = strtol(str, &end, 10);
80*fa9e4066Sahrens 
81*fa9e4066Sahrens 	if (errno != 0 || *end != '\0')
82*fa9e4066Sahrens 		return (EACL_INVALID_USER_GROUP);
83*fa9e4066Sahrens 
84*fa9e4066Sahrens 	*id = value;
85*fa9e4066Sahrens 
86*fa9e4066Sahrens 	return (0);
87*fa9e4066Sahrens }
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /*
907c478bd9Sstevel@tonic-gate  * Convert internal acl representation to external representation.
917c478bd9Sstevel@tonic-gate  *
927c478bd9Sstevel@tonic-gate  * The length of a non-owning user name or non-owning group name ie entries
937c478bd9Sstevel@tonic-gate  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
947c478bd9Sstevel@tonic-gate  * thus check the length of these entries, and if greater than LOGNAME_MAX,
957c478bd9Sstevel@tonic-gate  * we realloc() via increase_length().
967c478bd9Sstevel@tonic-gate  *
977c478bd9Sstevel@tonic-gate  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
987c478bd9Sstevel@tonic-gate  * adhered to.
997c478bd9Sstevel@tonic-gate  */
1007c478bd9Sstevel@tonic-gate char *
1017c478bd9Sstevel@tonic-gate acltotext(aclent_t *aclp, int aclcnt)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	char		*aclexport;
1047c478bd9Sstevel@tonic-gate 	char		*where;
1057c478bd9Sstevel@tonic-gate 	struct group	*groupp;
1067c478bd9Sstevel@tonic-gate 	struct passwd	*passwdp;
1077c478bd9Sstevel@tonic-gate 	struct dynaclstr *dstr;
1087c478bd9Sstevel@tonic-gate 	int		i, rtn;
1097c478bd9Sstevel@tonic-gate 	size_t		excess = 0;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	if (aclp == NULL)
1127c478bd9Sstevel@tonic-gate 		return (NULL);
1137c478bd9Sstevel@tonic-gate 	if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL)
1147c478bd9Sstevel@tonic-gate 		return (NULL);
1157c478bd9Sstevel@tonic-gate 	dstr->bufsize = aclcnt * ACL_ENTRY_SIZE;
1167c478bd9Sstevel@tonic-gate 	if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) {
1177c478bd9Sstevel@tonic-gate 		free(dstr);
1187c478bd9Sstevel@tonic-gate 		return (NULL);
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 	*dstr->aclexport = '\0';
1217c478bd9Sstevel@tonic-gate 	where = dstr->aclexport;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	for (i = 0; i < aclcnt; i++, aclp++) {
1247c478bd9Sstevel@tonic-gate 		switch (aclp->a_type) {
1257c478bd9Sstevel@tonic-gate 		case DEF_USER_OBJ:
1267c478bd9Sstevel@tonic-gate 		case USER_OBJ:
1277c478bd9Sstevel@tonic-gate 			if (aclp->a_type == USER_OBJ)
1287c478bd9Sstevel@tonic-gate 				where = strappend(where, "user::");
1297c478bd9Sstevel@tonic-gate 			else
1307c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultuser::");
1317c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
1327c478bd9Sstevel@tonic-gate 			break;
1337c478bd9Sstevel@tonic-gate 		case DEF_USER:
1347c478bd9Sstevel@tonic-gate 		case USER:
1357c478bd9Sstevel@tonic-gate 			if (aclp->a_type == USER)
1367c478bd9Sstevel@tonic-gate 				where = strappend(where, "user:");
1377c478bd9Sstevel@tonic-gate 			else
1387c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultuser:");
1397c478bd9Sstevel@tonic-gate 			passwdp = getpwuid(aclp->a_id);
1407c478bd9Sstevel@tonic-gate 			if (passwdp == (struct passwd *)NULL) {
1417c478bd9Sstevel@tonic-gate 				/* put in uid instead */
1427c478bd9Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
1437c478bd9Sstevel@tonic-gate 			} else {
1447c478bd9Sstevel@tonic-gate 				excess = strlen(passwdp->pw_name) - LOGNAME_MAX;
1457c478bd9Sstevel@tonic-gate 				if (excess > 0) {
1467c478bd9Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
1477c478bd9Sstevel@tonic-gate 					if (rtn == 1) {
1487c478bd9Sstevel@tonic-gate 						/* reset where */
1497c478bd9Sstevel@tonic-gate 						where = dstr->aclexport +
1507c478bd9Sstevel@tonic-gate 							strlen(dstr->aclexport);
1517c478bd9Sstevel@tonic-gate 					} else {
1527c478bd9Sstevel@tonic-gate 						free(dstr->aclexport);
1537c478bd9Sstevel@tonic-gate 						free(dstr);
1547c478bd9Sstevel@tonic-gate 						return (NULL);
1557c478bd9Sstevel@tonic-gate 					}
1567c478bd9Sstevel@tonic-gate 				}
1577c478bd9Sstevel@tonic-gate 				where = strappend(where, passwdp->pw_name);
1587c478bd9Sstevel@tonic-gate 			}
1597c478bd9Sstevel@tonic-gate 			where = strappend(where, ":");
1607c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
1617c478bd9Sstevel@tonic-gate 			break;
1627c478bd9Sstevel@tonic-gate 		case DEF_GROUP_OBJ:
1637c478bd9Sstevel@tonic-gate 		case GROUP_OBJ:
1647c478bd9Sstevel@tonic-gate 			if (aclp->a_type == GROUP_OBJ)
1657c478bd9Sstevel@tonic-gate 				where = strappend(where, "group::");
1667c478bd9Sstevel@tonic-gate 			else
1677c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultgroup::");
1687c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
1697c478bd9Sstevel@tonic-gate 			break;
1707c478bd9Sstevel@tonic-gate 		case DEF_GROUP:
1717c478bd9Sstevel@tonic-gate 		case GROUP:
1727c478bd9Sstevel@tonic-gate 			if (aclp->a_type == GROUP)
1737c478bd9Sstevel@tonic-gate 				where = strappend(where, "group:");
1747c478bd9Sstevel@tonic-gate 			else
1757c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultgroup:");
1767c478bd9Sstevel@tonic-gate 			groupp = getgrgid(aclp->a_id);
1777c478bd9Sstevel@tonic-gate 			if (groupp == (struct group *)NULL) {
1787c478bd9Sstevel@tonic-gate 				/* put in gid instead */
1797c478bd9Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
1807c478bd9Sstevel@tonic-gate 			} else {
1817c478bd9Sstevel@tonic-gate 				excess = strlen(groupp->gr_name) - LOGNAME_MAX;
1827c478bd9Sstevel@tonic-gate 				if (excess > 0) {
1837c478bd9Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
1847c478bd9Sstevel@tonic-gate 					if (rtn == 1) {
1857c478bd9Sstevel@tonic-gate 						/* reset where */
1867c478bd9Sstevel@tonic-gate 						where = dstr->aclexport +
1877c478bd9Sstevel@tonic-gate 							strlen(dstr->aclexport);
1887c478bd9Sstevel@tonic-gate 					} else {
1897c478bd9Sstevel@tonic-gate 						free(dstr->aclexport);
1907c478bd9Sstevel@tonic-gate 						free(dstr);
1917c478bd9Sstevel@tonic-gate 						return (NULL);
1927c478bd9Sstevel@tonic-gate 					}
1937c478bd9Sstevel@tonic-gate 				}
1947c478bd9Sstevel@tonic-gate 				where = strappend(where, groupp->gr_name);
1957c478bd9Sstevel@tonic-gate 			}
1967c478bd9Sstevel@tonic-gate 			where = strappend(where, ":");
1977c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
1987c478bd9Sstevel@tonic-gate 			break;
1997c478bd9Sstevel@tonic-gate 		case DEF_CLASS_OBJ:
2007c478bd9Sstevel@tonic-gate 		case CLASS_OBJ:
2017c478bd9Sstevel@tonic-gate 			if (aclp->a_type == CLASS_OBJ)
2027c478bd9Sstevel@tonic-gate 				where = strappend(where, "mask:");
2037c478bd9Sstevel@tonic-gate 			else
2047c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultmask:");
2057c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
2067c478bd9Sstevel@tonic-gate 			break;
2077c478bd9Sstevel@tonic-gate 		case DEF_OTHER_OBJ:
2087c478bd9Sstevel@tonic-gate 		case OTHER_OBJ:
2097c478bd9Sstevel@tonic-gate 			if (aclp->a_type == OTHER_OBJ)
2107c478bd9Sstevel@tonic-gate 				where = strappend(where, "other:");
2117c478bd9Sstevel@tonic-gate 			else
2127c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultother:");
2137c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
2147c478bd9Sstevel@tonic-gate 			break;
2157c478bd9Sstevel@tonic-gate 		default:
2167c478bd9Sstevel@tonic-gate 			free(dstr->aclexport);
2177c478bd9Sstevel@tonic-gate 			free(dstr);
2187c478bd9Sstevel@tonic-gate 			return (NULL);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 		if (i < aclcnt - 1)
2227c478bd9Sstevel@tonic-gate 			where = strappend(where, ",");
2237c478bd9Sstevel@tonic-gate 	}
2247c478bd9Sstevel@tonic-gate 	aclexport = dstr->aclexport;
2257c478bd9Sstevel@tonic-gate 	free(dstr);
2267c478bd9Sstevel@tonic-gate 	return (aclexport);
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate /*
2307c478bd9Sstevel@tonic-gate  * Convert external acl representation to internal representation.
2317c478bd9Sstevel@tonic-gate  * The accepted syntax is: <acl_entry>[,<acl_entry>]*[,]
2327c478bd9Sstevel@tonic-gate  * The comma at the end is not prescribed by the man pages.
2337c478bd9Sstevel@tonic-gate  * But it is needed not to break the old programs.
2347c478bd9Sstevel@tonic-gate  */
235*fa9e4066Sahrens static int
236*fa9e4066Sahrens aclent_aclfromtext(char *aclstr, acl_t **ret_aclp)
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate 	char		*fieldp;
2397c478bd9Sstevel@tonic-gate 	char		*tp;
2407c478bd9Sstevel@tonic-gate 	char		*nextp;
2417c478bd9Sstevel@tonic-gate 	char		*allocp;
2427c478bd9Sstevel@tonic-gate 	char		*aclimport;
2437c478bd9Sstevel@tonic-gate 	int		entry_type;
2447c478bd9Sstevel@tonic-gate 	int		id;
2457c478bd9Sstevel@tonic-gate 	int		len;
246*fa9e4066Sahrens 	int		error;
2477c478bd9Sstevel@tonic-gate 	o_mode_t	perm;
2487c478bd9Sstevel@tonic-gate 	aclent_t	*tmpaclp;
249*fa9e4066Sahrens 	acl_t		*aclp;
2507c478bd9Sstevel@tonic-gate 	struct group	*groupp;
2517c478bd9Sstevel@tonic-gate 	struct passwd	*passwdp;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	aclp = NULL;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	if (! aclstr)
2567c478bd9Sstevel@tonic-gate 		return (NULL);
2577c478bd9Sstevel@tonic-gate 
258*fa9e4066Sahrens 	aclp = acl_alloc(ACLENT_T);
259*fa9e4066Sahrens 	if (aclp == NULL) {
260*fa9e4066Sahrens 		return (EACL_MEM_ERROR);
261*fa9e4066Sahrens 	}
262*fa9e4066Sahrens 
263*fa9e4066Sahrens 	*ret_aclp = NULL;
264*fa9e4066Sahrens 
2657c478bd9Sstevel@tonic-gate 	len = strlen(aclstr);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if ((aclimport = allocp = strdup(aclstr)) == NULL) {
268*fa9e4066Sahrens 		return (EACL_MEM_ERROR);
2697c478bd9Sstevel@tonic-gate 	}
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	if (aclimport[len - 1] == ',')
2727c478bd9Sstevel@tonic-gate 		aclimport[len - 1] = '\0';
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	for (; aclimport; ) {
2757c478bd9Sstevel@tonic-gate 		/* look for an ACL entry */
2767c478bd9Sstevel@tonic-gate 		tp = strchr(aclimport, ',');
2777c478bd9Sstevel@tonic-gate 		if (tp == NULL) {
2787c478bd9Sstevel@tonic-gate 			nextp = NULL;
2797c478bd9Sstevel@tonic-gate 		} else {
2807c478bd9Sstevel@tonic-gate 			*tp = '\0';
2817c478bd9Sstevel@tonic-gate 			nextp = tp + 1;
2827c478bd9Sstevel@tonic-gate 		}
2837c478bd9Sstevel@tonic-gate 
284*fa9e4066Sahrens 		aclp->acl_cnt += 1;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 		/*
2877c478bd9Sstevel@tonic-gate 		 * get additional memory:
2887c478bd9Sstevel@tonic-gate 		 * can be more efficient by allocating a bigger block
2897c478bd9Sstevel@tonic-gate 		 * each time.
2907c478bd9Sstevel@tonic-gate 		 */
291*fa9e4066Sahrens 		if (aclp->acl_cnt > 1)
292*fa9e4066Sahrens 			tmpaclp = (aclent_t *)realloc(aclp->acl_aclp,
293*fa9e4066Sahrens 			    sizeof (aclent_t) * (aclp->acl_cnt));
2947c478bd9Sstevel@tonic-gate 		else
2957c478bd9Sstevel@tonic-gate 			tmpaclp = (aclent_t *)malloc(sizeof (aclent_t));
2967c478bd9Sstevel@tonic-gate 		if (tmpaclp == NULL) {
2977c478bd9Sstevel@tonic-gate 			free(allocp);
298*fa9e4066Sahrens 			acl_free(aclp);
299*fa9e4066Sahrens 			return (EACL_MEM_ERROR);
3007c478bd9Sstevel@tonic-gate 		}
301*fa9e4066Sahrens 		aclp->acl_aclp = tmpaclp;
302*fa9e4066Sahrens 		tmpaclp = (aclent_t *)aclp->acl_aclp + (aclp->acl_cnt - 1);
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 		/* look for entry type field */
3057c478bd9Sstevel@tonic-gate 		tp = strchr(aclimport, ':');
3067c478bd9Sstevel@tonic-gate 		if (tp == NULL) {
307*fa9e4066Sahrens 			free(allocp);
308*fa9e4066Sahrens 			if (aclp)
309*fa9e4066Sahrens 				acl_free(aclp);
310*fa9e4066Sahrens 			return (EACL_ENTRY_ERROR);
3117c478bd9Sstevel@tonic-gate 		} else
3127c478bd9Sstevel@tonic-gate 			*tp = '\0';
3137c478bd9Sstevel@tonic-gate 		if (strcmp(aclimport, "user") == 0) {
3147c478bd9Sstevel@tonic-gate 			if (*(tp+1) == ':')
3157c478bd9Sstevel@tonic-gate 				entry_type = USER_OBJ;
3167c478bd9Sstevel@tonic-gate 			else
3177c478bd9Sstevel@tonic-gate 				entry_type = USER;
3187c478bd9Sstevel@tonic-gate 		} else if (strcmp(aclimport, "group") == 0) {
3197c478bd9Sstevel@tonic-gate 			if (*(tp+1) == ':')
3207c478bd9Sstevel@tonic-gate 				entry_type = GROUP_OBJ;
3217c478bd9Sstevel@tonic-gate 			else
3227c478bd9Sstevel@tonic-gate 				entry_type = GROUP;
3237c478bd9Sstevel@tonic-gate 		} else if (strcmp(aclimport, "other") == 0)
3247c478bd9Sstevel@tonic-gate 			entry_type = OTHER_OBJ;
3257c478bd9Sstevel@tonic-gate 		else if (strcmp(aclimport, "mask") == 0)
3267c478bd9Sstevel@tonic-gate 			entry_type = CLASS_OBJ;
3277c478bd9Sstevel@tonic-gate 		else if (strcmp(aclimport, "defaultuser") == 0) {
3287c478bd9Sstevel@tonic-gate 			if (*(tp+1) == ':')
3297c478bd9Sstevel@tonic-gate 				entry_type = DEF_USER_OBJ;
3307c478bd9Sstevel@tonic-gate 			else
3317c478bd9Sstevel@tonic-gate 				entry_type = DEF_USER;
3327c478bd9Sstevel@tonic-gate 		} else if (strcmp(aclimport, "defaultgroup") == 0) {
3337c478bd9Sstevel@tonic-gate 			if (*(tp+1) == ':')
3347c478bd9Sstevel@tonic-gate 				entry_type = DEF_GROUP_OBJ;
3357c478bd9Sstevel@tonic-gate 			else
3367c478bd9Sstevel@tonic-gate 				entry_type = DEF_GROUP;
3377c478bd9Sstevel@tonic-gate 		} else if (strcmp(aclimport, "defaultmask") == 0)
3387c478bd9Sstevel@tonic-gate 			entry_type = DEF_CLASS_OBJ;
3397c478bd9Sstevel@tonic-gate 		else if (strcmp(aclimport, "defaultother") == 0)
3407c478bd9Sstevel@tonic-gate 			entry_type = DEF_OTHER_OBJ;
3417c478bd9Sstevel@tonic-gate 		else {
342*fa9e4066Sahrens 			free(allocp);
343*fa9e4066Sahrens 			acl_free(aclp);
344*fa9e4066Sahrens 			return (EACL_ENTRY_ERROR);
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 		/* look for user/group name */
3487c478bd9Sstevel@tonic-gate 		if (entry_type != CLASS_OBJ && entry_type != OTHER_OBJ &&
3497c478bd9Sstevel@tonic-gate 		    entry_type != DEF_CLASS_OBJ &&
3507c478bd9Sstevel@tonic-gate 		    entry_type != DEF_OTHER_OBJ) {
3517c478bd9Sstevel@tonic-gate 			fieldp = tp + 1;
3527c478bd9Sstevel@tonic-gate 			tp = strchr(fieldp, ':');
3537c478bd9Sstevel@tonic-gate 			if (tp == NULL) {
354*fa9e4066Sahrens 				free(allocp);
355*fa9e4066Sahrens 				acl_free(aclp);
356*fa9e4066Sahrens 				return (EACL_INVALID_USER_GROUP);
3577c478bd9Sstevel@tonic-gate 			} else
3587c478bd9Sstevel@tonic-gate 				*tp = '\0';
3597c478bd9Sstevel@tonic-gate 			if (fieldp != tp) {
3607c478bd9Sstevel@tonic-gate 				/*
3617c478bd9Sstevel@tonic-gate 				 * The second field could be empty. We only care
3627c478bd9Sstevel@tonic-gate 				 * when the field has user/group name.
3637c478bd9Sstevel@tonic-gate 				 */
3647c478bd9Sstevel@tonic-gate 				if (entry_type == USER ||
3657c478bd9Sstevel@tonic-gate 				    entry_type == DEF_USER) {
3667c478bd9Sstevel@tonic-gate 					/*
3677c478bd9Sstevel@tonic-gate 					 * The reentrant interface getpwnam_r()
3687c478bd9Sstevel@tonic-gate 					 * is uncommitted and subject to
3697c478bd9Sstevel@tonic-gate 					 * change. Use the friendlier interface
3707c478bd9Sstevel@tonic-gate 					 * getpwnam().
3717c478bd9Sstevel@tonic-gate 					 */
372*fa9e4066Sahrens 					error = 0;
3737c478bd9Sstevel@tonic-gate 					passwdp = getpwnam(fieldp);
3747c478bd9Sstevel@tonic-gate 					if (passwdp == NULL) {
375*fa9e4066Sahrens 						error = acl_str_to_id(fieldp,
376*fa9e4066Sahrens 						    &id);
3777c478bd9Sstevel@tonic-gate 					} else {
378*fa9e4066Sahrens 						id = passwdp->pw_uid;
379*fa9e4066Sahrens 					}
380*fa9e4066Sahrens 
381*fa9e4066Sahrens 					if (error) {
382*fa9e4066Sahrens 						free(allocp);
383*fa9e4066Sahrens 						acl_free(aclp);
384*fa9e4066Sahrens 						return (error);
385*fa9e4066Sahrens 					}
386*fa9e4066Sahrens 
387*fa9e4066Sahrens 				} else {
388*fa9e4066Sahrens 					error = 0;
3897c478bd9Sstevel@tonic-gate 					if (entry_type == GROUP ||
3907c478bd9Sstevel@tonic-gate 					    entry_type == DEF_GROUP) {
3917c478bd9Sstevel@tonic-gate 						groupp = getgrnam(fieldp);
3927c478bd9Sstevel@tonic-gate 						if (groupp == NULL) {
393*fa9e4066Sahrens 							error = acl_str_to_id(
394*fa9e4066Sahrens 							    fieldp, &id);
3957c478bd9Sstevel@tonic-gate 						}
396*fa9e4066Sahrens 						if (error == 0)
3977c478bd9Sstevel@tonic-gate 							id = groupp->gr_gid;
398*fa9e4066Sahrens 					}
399*fa9e4066Sahrens 					if (error) {
400*fa9e4066Sahrens 						free(allocp);
401*fa9e4066Sahrens 						acl_free(aclp);
402*fa9e4066Sahrens 						return (error);
4037c478bd9Sstevel@tonic-gate 					}
4047c478bd9Sstevel@tonic-gate 				}
4057c478bd9Sstevel@tonic-gate 			} else {
4067c478bd9Sstevel@tonic-gate 				/*
4077c478bd9Sstevel@tonic-gate 				 * The second field is empty.
4087c478bd9Sstevel@tonic-gate 				 * Treat it as undefined (-1)
4097c478bd9Sstevel@tonic-gate 				 */
4107c478bd9Sstevel@tonic-gate 				id = -1;
4117c478bd9Sstevel@tonic-gate 			}
4127c478bd9Sstevel@tonic-gate 		} else {
4137c478bd9Sstevel@tonic-gate 			/*
4147c478bd9Sstevel@tonic-gate 			 * Let's not break the old applications
4157c478bd9Sstevel@tonic-gate 			 * that use mask::rwx, other::rwx format,
4167c478bd9Sstevel@tonic-gate 			 * though they violate the man pages.
4177c478bd9Sstevel@tonic-gate 			 */
4187c478bd9Sstevel@tonic-gate 			if (*(tp + 1) == ':')
4197c478bd9Sstevel@tonic-gate 				*++tp = 0;
4207c478bd9Sstevel@tonic-gate 		}
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 		/* next field: permission */
4237c478bd9Sstevel@tonic-gate 		fieldp = tp + 1;
4247c478bd9Sstevel@tonic-gate 		if (strlen(fieldp) != 3) {
4257c478bd9Sstevel@tonic-gate 			/*  not "rwx" format */
426*fa9e4066Sahrens 			free(allocp);
427*fa9e4066Sahrens 			acl_free(aclp);
428*fa9e4066Sahrens 			return (EACL_PERM_MASK_ERROR);
4297c478bd9Sstevel@tonic-gate 		} else {
4307c478bd9Sstevel@tonic-gate 			char	s[] = "rwx";
4317c478bd9Sstevel@tonic-gate 			int	mask = 0x04;
4327c478bd9Sstevel@tonic-gate 			int	i;
4337c478bd9Sstevel@tonic-gate 			perm = 0;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 			for (i = 0; i < 3; i++, mask /= 2) {
4367c478bd9Sstevel@tonic-gate 				if (fieldp[i] == s[i])
4377c478bd9Sstevel@tonic-gate 					perm |= mask;
4387c478bd9Sstevel@tonic-gate 				else if (fieldp[i] != '-') {
439*fa9e4066Sahrens 					free(allocp);
440*fa9e4066Sahrens 					acl_free(aclp);
441*fa9e4066Sahrens 					return (EACL_PERM_MASK_ERROR);
4427c478bd9Sstevel@tonic-gate 				}
4437c478bd9Sstevel@tonic-gate 			}
4447c478bd9Sstevel@tonic-gate 		}
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 		tmpaclp->a_type = entry_type;
4477c478bd9Sstevel@tonic-gate 		tmpaclp->a_id = id;
4487c478bd9Sstevel@tonic-gate 		tmpaclp->a_perm = perm;
4497c478bd9Sstevel@tonic-gate 		aclimport = nextp;
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate 	free(allocp);
452*fa9e4066Sahrens 	*ret_aclp = aclp;
453*fa9e4066Sahrens 	return (0);
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate 
456*fa9e4066Sahrens aclent_t *
457*fa9e4066Sahrens aclfromtext(char *aclstr, int *aclcnt)
458*fa9e4066Sahrens {
459*fa9e4066Sahrens 	acl_t *aclp;
460*fa9e4066Sahrens 	aclent_t *aclentp;
461*fa9e4066Sahrens 	int error;
462*fa9e4066Sahrens 
463*fa9e4066Sahrens 	error = aclent_aclfromtext(aclstr, &aclp);
464*fa9e4066Sahrens 	if (error)
465*fa9e4066Sahrens 		return (NULL);
466*fa9e4066Sahrens 
467*fa9e4066Sahrens 	aclentp = aclp->acl_aclp;
468*fa9e4066Sahrens 	aclp->acl_aclp = NULL;
469*fa9e4066Sahrens 	acl_free(aclp);
470*fa9e4066Sahrens 
471*fa9e4066Sahrens 	*aclcnt = aclp->acl_cnt;
472*fa9e4066Sahrens 	return (aclentp);
473*fa9e4066Sahrens }
474*fa9e4066Sahrens 
475*fa9e4066Sahrens 
4767c478bd9Sstevel@tonic-gate static char *
4777c478bd9Sstevel@tonic-gate strappend(char *where, char *newstr)
4787c478bd9Sstevel@tonic-gate {
4797c478bd9Sstevel@tonic-gate 	(void) strcat(where, newstr);
4807c478bd9Sstevel@tonic-gate 	return (where + strlen(newstr));
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate static char *
4847c478bd9Sstevel@tonic-gate convert_perm(char *where, o_mode_t perm)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate 	if (perm & 04)
4877c478bd9Sstevel@tonic-gate 		where = strappend(where, "r");
4887c478bd9Sstevel@tonic-gate 	else
4897c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
4907c478bd9Sstevel@tonic-gate 	if (perm & 02)
4917c478bd9Sstevel@tonic-gate 		where = strappend(where, "w");
4927c478bd9Sstevel@tonic-gate 	else
4937c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
4947c478bd9Sstevel@tonic-gate 	if (perm & 01)
4957c478bd9Sstevel@tonic-gate 		where = strappend(where, "x");
4967c478bd9Sstevel@tonic-gate 	else
4977c478bd9Sstevel@tonic-gate 		where = strappend(where, "-");
4987c478bd9Sstevel@tonic-gate 	/* perm is the last field */
4997c478bd9Sstevel@tonic-gate 	return (where);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate 
502*fa9e4066Sahrens static char *
503*fa9e4066Sahrens ace_convert_perm(char *where, mode_t perm, int isdir, int iflags)
504*fa9e4066Sahrens {
505*fa9e4066Sahrens 	char *start = where;
506*fa9e4066Sahrens 
507*fa9e4066Sahrens 	/*
508*fa9e4066Sahrens 	 * The following mneumonics all have the
509*fa9e4066Sahrens 	 * same value.  The only difference is the
510*fa9e4066Sahrens 	 * first value is for files and second for directories
511*fa9e4066Sahrens 	 * ACE_READ_DATA/ACE_LIST_DIRECTORY
512*fa9e4066Sahrens 	 * ACE_WRITE_DATA/ACE_ADD_FILE
513*fa9e4066Sahrens 	 * ACE_APPEND_DATA/ACE_ADD_SUBDIRECTORY
514*fa9e4066Sahrens 	 */
515*fa9e4066Sahrens 
516*fa9e4066Sahrens 	/*
517*fa9e4066Sahrens 	 * If ACE is a directory, but inheritance indicates its
518*fa9e4066Sahrens 	 * for a file then print permissions for file rather than
519*fa9e4066Sahrens 	 * dir.
520*fa9e4066Sahrens 	 */
521*fa9e4066Sahrens 	if (isdir) {
522*fa9e4066Sahrens 		if (perm & ACE_LIST_DIRECTORY) {
523*fa9e4066Sahrens 			if (iflags == ACE_FILE_INHERIT_ACE)
524*fa9e4066Sahrens 				where = strappend(where, "read_data/");
525*fa9e4066Sahrens 			else
526*fa9e4066Sahrens 				where = strappend(where,
527*fa9e4066Sahrens 				    "list_directory/read_data/");
528*fa9e4066Sahrens 		}
529*fa9e4066Sahrens 		if (perm & ACE_ADD_FILE) {
530*fa9e4066Sahrens 			if (iflags == ACE_FILE_INHERIT_ACE)
531*fa9e4066Sahrens 				where = strappend(where, "write_data/");
532*fa9e4066Sahrens 			else
533*fa9e4066Sahrens 				where = strappend(where,
534*fa9e4066Sahrens 				    "add_file/write_data/");
535*fa9e4066Sahrens 		}
536*fa9e4066Sahrens 		if (perm & ACE_ADD_SUBDIRECTORY) {
537*fa9e4066Sahrens 			if (iflags == ACE_FILE_INHERIT_ACE)
538*fa9e4066Sahrens 				where = strappend(where, "append_data/");
539*fa9e4066Sahrens 			else
540*fa9e4066Sahrens 				where = strappend(where,
541*fa9e4066Sahrens 				    "add_subdirectory/append_data/");
542*fa9e4066Sahrens 		}
543*fa9e4066Sahrens 	} else {
544*fa9e4066Sahrens 		if (perm & ACE_READ_DATA)
545*fa9e4066Sahrens 			where = strappend(where, "read_data/");
546*fa9e4066Sahrens 		if (perm & ACE_WRITE_DATA)
547*fa9e4066Sahrens 			where = strappend(where, "write_data/");
548*fa9e4066Sahrens 		if (perm & ACE_APPEND_DATA)
549*fa9e4066Sahrens 			where = strappend(where, "append_data/");
550*fa9e4066Sahrens 	}
551*fa9e4066Sahrens 	if (perm & ACE_READ_NAMED_ATTRS)
552*fa9e4066Sahrens 		where = strappend(where, "read_xattr/");
553*fa9e4066Sahrens 	if (perm & ACE_WRITE_NAMED_ATTRS)
554*fa9e4066Sahrens 		where = strappend(where, "write_xattr/");
555*fa9e4066Sahrens 	if (perm & ACE_EXECUTE)
556*fa9e4066Sahrens 		where = strappend(where, "execute/");
557*fa9e4066Sahrens 	if (perm & ACE_DELETE_CHILD)
558*fa9e4066Sahrens 		where = strappend(where, "delete_child/");
559*fa9e4066Sahrens 	if (perm & ACE_READ_ATTRIBUTES)
560*fa9e4066Sahrens 		where = strappend(where, "read_attributes/");
561*fa9e4066Sahrens 	if (perm & ACE_WRITE_ATTRIBUTES)
562*fa9e4066Sahrens 		where = strappend(where, "write_attributes/");
563*fa9e4066Sahrens 	if (perm & ACE_DELETE)
564*fa9e4066Sahrens 		where = strappend(where, "delete/");
565*fa9e4066Sahrens 	if (perm & ACE_READ_ACL)
566*fa9e4066Sahrens 		where = strappend(where, "read_acl/");
567*fa9e4066Sahrens 	if (perm & ACE_WRITE_ACL)
568*fa9e4066Sahrens 		where = strappend(where, "write_acl/");
569*fa9e4066Sahrens 	if (perm & ACE_WRITE_OWNER)
570*fa9e4066Sahrens 		where = strappend(where, "write_owner/");
571*fa9e4066Sahrens 	if (perm & ACE_SYNCHRONIZE)
572*fa9e4066Sahrens 		where = strappend(where, "synchronize");
573*fa9e4066Sahrens 
574*fa9e4066Sahrens 	if (start[strlen(start) - 1] == '/') {
575*fa9e4066Sahrens 		start[strlen(start) - 1] = '\0';
576*fa9e4066Sahrens 		where = start + strlen(start);
577*fa9e4066Sahrens 	}
578*fa9e4066Sahrens 	return (where);
579*fa9e4066Sahrens }
580*fa9e4066Sahrens 
581*fa9e4066Sahrens int
582*fa9e4066Sahrens ace_permask(char *perm_tok, int *perm)
583*fa9e4066Sahrens {
584*fa9e4066Sahrens 	if (strcmp(perm_tok, "read_data") == 0)
585*fa9e4066Sahrens 		*perm |= ACE_READ_DATA;
586*fa9e4066Sahrens 	else if (strcmp(perm_tok, "list_directory") == 0)
587*fa9e4066Sahrens 		*perm |= ACE_LIST_DIRECTORY;
588*fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_data") == 0)
589*fa9e4066Sahrens 		*perm |= ACE_WRITE_DATA;
590*fa9e4066Sahrens 	else if (strcmp(perm_tok, "add_file") == 0)
591*fa9e4066Sahrens 		*perm |= ACE_ADD_FILE;
592*fa9e4066Sahrens 	else if (strcmp(perm_tok, "append_data") == 0)
593*fa9e4066Sahrens 		*perm |= ACE_APPEND_DATA;
594*fa9e4066Sahrens 	else if (strcmp(perm_tok, "add_subdirectory") == 0)
595*fa9e4066Sahrens 		*perm |= ACE_ADD_SUBDIRECTORY;
596*fa9e4066Sahrens 	else if (strcmp(perm_tok, "read_xattr") == 0)
597*fa9e4066Sahrens 		*perm |= ACE_READ_NAMED_ATTRS;
598*fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_xattr") == 0)
599*fa9e4066Sahrens 		*perm |= ACE_WRITE_NAMED_ATTRS;
600*fa9e4066Sahrens 	else if (strcmp(perm_tok, "execute") == 0)
601*fa9e4066Sahrens 		*perm |= ACE_EXECUTE;
602*fa9e4066Sahrens 	else if (strcmp(perm_tok, "delete_child") == 0)
603*fa9e4066Sahrens 		*perm |= ACE_DELETE_CHILD;
604*fa9e4066Sahrens 	else if (strcmp(perm_tok, "read_attributes") == 0)
605*fa9e4066Sahrens 		*perm |= ACE_READ_ATTRIBUTES;
606*fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_attributes") == 0)
607*fa9e4066Sahrens 		*perm |= ACE_WRITE_ATTRIBUTES;
608*fa9e4066Sahrens 	else if (strcmp(perm_tok, "delete") == 0)
609*fa9e4066Sahrens 		*perm |= ACE_DELETE;
610*fa9e4066Sahrens 	else if (strcmp(perm_tok, "read_acl") == 0)
611*fa9e4066Sahrens 		*perm |= ACE_READ_ACL;
612*fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_acl") == 0)
613*fa9e4066Sahrens 		*perm |= ACE_WRITE_ACL;
614*fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_owner") == 0)
615*fa9e4066Sahrens 		*perm |= ACE_WRITE_OWNER;
616*fa9e4066Sahrens 	else if (strcmp(perm_tok, "synchronize") == 0)
617*fa9e4066Sahrens 		*perm |= ACE_SYNCHRONIZE;
618*fa9e4066Sahrens 	else {
619*fa9e4066Sahrens 		return (1);
620*fa9e4066Sahrens 	}
621*fa9e4066Sahrens 
622*fa9e4066Sahrens 	return (0);
623*fa9e4066Sahrens }
624*fa9e4066Sahrens 
6257c478bd9Sstevel@tonic-gate /*
6267c478bd9Sstevel@tonic-gate  * Callers should check the return code as this routine may change the string
6277c478bd9Sstevel@tonic-gate  * pointer in dynaclstr.
6287c478bd9Sstevel@tonic-gate  */
6297c478bd9Sstevel@tonic-gate static int
6307c478bd9Sstevel@tonic-gate increase_length(struct dynaclstr *dacl, size_t increase)
6317c478bd9Sstevel@tonic-gate {
6327c478bd9Sstevel@tonic-gate 	char *tptr;
6337c478bd9Sstevel@tonic-gate 	size_t newsize;
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 	newsize = dacl->bufsize + increase;
6367c478bd9Sstevel@tonic-gate 	tptr = realloc(dacl->aclexport, newsize);
6377c478bd9Sstevel@tonic-gate 	if (tptr != NULL) {
6387c478bd9Sstevel@tonic-gate 		dacl->aclexport = tptr;
6397c478bd9Sstevel@tonic-gate 		dacl->bufsize = newsize;
6407c478bd9Sstevel@tonic-gate 		return (1);
6417c478bd9Sstevel@tonic-gate 	} else
6427c478bd9Sstevel@tonic-gate 		return (0);
6437c478bd9Sstevel@tonic-gate }
644*fa9e4066Sahrens 
645*fa9e4066Sahrens /*
646*fa9e4066Sahrens  * ace_acltotext() conver each ace formatted acl to look like this:
647*fa9e4066Sahrens  *
648*fa9e4066Sahrens  * entry_type:uid^gid^name:perms:allow^deny[:flags][,]
649*fa9e4066Sahrens  *
650*fa9e4066Sahrens  * The maximum length of entry_type is 5 ("group")
651*fa9e4066Sahrens  *
652*fa9e4066Sahrens  * The max length of a uid^gid^name entry (in theory) is 8, hence we use
653*fa9e4066Sahrens  * LOGNAME_MAX.
654*fa9e4066Sahrens  *
655*fa9e4066Sahrens  * The length of a perms entry is 144 i.e read_data/write_data...
656*fa9e4066Sahrens  * to each acl entry.
657*fa9e4066Sahrens  *
658*fa9e4066Sahrens  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate
659*fa9e4066Sahrens  *
660*fa9e4066Sahrens  */
661*fa9e4066Sahrens 
662*fa9e4066Sahrens #define	ACE_ENTRYTYPLEN		6
663*fa9e4066Sahrens #define	IFLAGS_SIZE		51
664*fa9e4066Sahrens #define	ACCESS_TYPE_SIZE	5
665*fa9e4066Sahrens #define	COLON_CNT		3
666*fa9e4066Sahrens #define	PERMS_LEN		216
667*fa9e4066Sahrens #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + LOGNAME_MAX + PERMS_LEN +\
668*fa9e4066Sahrens     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT)
669*fa9e4066Sahrens 
670*fa9e4066Sahrens static char *
671*fa9e4066Sahrens ace_acltotext(acl_t *aceaclp)
672*fa9e4066Sahrens {
673*fa9e4066Sahrens 	ace_t		*aclp = aceaclp->acl_aclp;
674*fa9e4066Sahrens 	int		aclcnt = aceaclp->acl_cnt;
675*fa9e4066Sahrens 	char		*aclexport;
676*fa9e4066Sahrens 	char		*where;
677*fa9e4066Sahrens 	char		*start;
678*fa9e4066Sahrens 	struct group	*groupp;
679*fa9e4066Sahrens 	struct passwd	*passwdp;
680*fa9e4066Sahrens 	struct dynaclstr *dstr;
681*fa9e4066Sahrens 	int		i, rtn;
682*fa9e4066Sahrens 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
683*fa9e4066Sahrens 	size_t		excess = 0;
684*fa9e4066Sahrens 
685*fa9e4066Sahrens 	if (aclp == NULL)
686*fa9e4066Sahrens 		return (NULL);
687*fa9e4066Sahrens 	if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL)
688*fa9e4066Sahrens 		return (NULL);
689*fa9e4066Sahrens 	dstr->bufsize = aclcnt * ACE_ENTRY_SIZE;
690*fa9e4066Sahrens 	if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL)
691*fa9e4066Sahrens 		return (NULL);
692*fa9e4066Sahrens 	*dstr->aclexport = '\0';
693*fa9e4066Sahrens 	where = dstr->aclexport;
694*fa9e4066Sahrens 
695*fa9e4066Sahrens 	for (i = 0; i < aclcnt; i++, aclp++) {
696*fa9e4066Sahrens 		switch (aclp->a_flags & 0xf040) {
697*fa9e4066Sahrens 		case ACE_OWNER:
698*fa9e4066Sahrens 		case 0:
699*fa9e4066Sahrens 			if ((aclp->a_flags & 0xf040) == ACE_OWNER)
700*fa9e4066Sahrens 				where = strappend(where, "owner@");
701*fa9e4066Sahrens 			else
702*fa9e4066Sahrens 				where = strappend(where, "user:");
703*fa9e4066Sahrens 			if ((aclp->a_flags & 0xf040) == 0) {
704*fa9e4066Sahrens 				passwdp = getpwuid(aclp->a_who);
705*fa9e4066Sahrens 				if (passwdp == (struct passwd *)NULL) {
706*fa9e4066Sahrens 					/* put in uid instead */
707*fa9e4066Sahrens 					(void) sprintf(where, "%d",
708*fa9e4066Sahrens 					    aclp->a_who);
709*fa9e4066Sahrens 				} else {
710*fa9e4066Sahrens 					excess = strlen(passwdp->pw_name) -
711*fa9e4066Sahrens 					    LOGNAME_MAX;
712*fa9e4066Sahrens 					if (excess > 0) {
713*fa9e4066Sahrens 						rtn = increase_length(dstr,
714*fa9e4066Sahrens 						    excess);
715*fa9e4066Sahrens 						if (rtn == 1)
716*fa9e4066Sahrens 							/* reset where */
717*fa9e4066Sahrens 							where =
718*fa9e4066Sahrens 							    dstr->aclexport +
719*fa9e4066Sahrens 							    strlen(
720*fa9e4066Sahrens 							    dstr->aclexport);
721*fa9e4066Sahrens 						else
722*fa9e4066Sahrens 							return (NULL);
723*fa9e4066Sahrens 					}
724*fa9e4066Sahrens 					where = strappend(where,
725*fa9e4066Sahrens 					    passwdp->pw_name);
726*fa9e4066Sahrens 				}
727*fa9e4066Sahrens 			} else {
728*fa9e4066Sahrens 				where = strappend(where, "");
729*fa9e4066Sahrens 			}
730*fa9e4066Sahrens 			where = strappend(where, ":");
731*fa9e4066Sahrens 			break;
732*fa9e4066Sahrens 		case ACE_GROUP|ACE_IDENTIFIER_GROUP:
733*fa9e4066Sahrens 		case ACE_IDENTIFIER_GROUP:
734*fa9e4066Sahrens 			if ((aclp->a_flags & 0xf040) ==
735*fa9e4066Sahrens 			    (ACE_GROUP | ACE_IDENTIFIER_GROUP))
736*fa9e4066Sahrens 				where = strappend(where, "group@");
737*fa9e4066Sahrens 			else
738*fa9e4066Sahrens 				where = strappend(where, "group:");
739*fa9e4066Sahrens 			if (!(aclp->a_flags & ACE_GROUP)) {
740*fa9e4066Sahrens 				groupp = getgrgid(aclp->a_who);
741*fa9e4066Sahrens 				if (groupp == (struct group *)NULL) {
742*fa9e4066Sahrens 					/* put in gid instead */
743*fa9e4066Sahrens 					(void) sprintf(where,
744*fa9e4066Sahrens 					    "%d", aclp->a_who);
745*fa9e4066Sahrens 				} else {
746*fa9e4066Sahrens 					excess = strlen(groupp->gr_name) -
747*fa9e4066Sahrens 					    LOGNAME_MAX;
748*fa9e4066Sahrens 					if (excess > 0) {
749*fa9e4066Sahrens 						rtn = increase_length(dstr,
750*fa9e4066Sahrens 						    excess);
751*fa9e4066Sahrens 						if (rtn == 1)
752*fa9e4066Sahrens 							/* reset where */
753*fa9e4066Sahrens 							where =
754*fa9e4066Sahrens 							    dstr->aclexport +
755*fa9e4066Sahrens 							    strlen(
756*fa9e4066Sahrens 							    dstr->aclexport);
757*fa9e4066Sahrens 						else
758*fa9e4066Sahrens 							return (NULL);
759*fa9e4066Sahrens 					}
760*fa9e4066Sahrens 					where = strappend(where,
761*fa9e4066Sahrens 					    groupp->gr_name);
762*fa9e4066Sahrens 				}
763*fa9e4066Sahrens 			} else {
764*fa9e4066Sahrens 					where = strappend(where, "");
765*fa9e4066Sahrens 			}
766*fa9e4066Sahrens 			where = strappend(where, ":");
767*fa9e4066Sahrens 			break;
768*fa9e4066Sahrens 		case ACE_EVERYONE:
769*fa9e4066Sahrens 			where = strappend(where, "everyone@:");
770*fa9e4066Sahrens 			break;
771*fa9e4066Sahrens 		default:
772*fa9e4066Sahrens 			free(dstr->aclexport);
773*fa9e4066Sahrens 			free(dstr);
774*fa9e4066Sahrens 			return (NULL);
775*fa9e4066Sahrens 
776*fa9e4066Sahrens 		}
777*fa9e4066Sahrens 		where = ace_convert_perm(where, aclp->a_access_mask,
778*fa9e4066Sahrens 		    isdir, (aclp->a_flags &
779*fa9e4066Sahrens 		    (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE)));
780*fa9e4066Sahrens 		where = strappend(where,
781*fa9e4066Sahrens 		    (aclp->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) ?
782*fa9e4066Sahrens 		    ":allow" : ":deny");
783*fa9e4066Sahrens 
784*fa9e4066Sahrens 		/*
785*fa9e4066Sahrens 		 * slap on inheritance flags if we have any
786*fa9e4066Sahrens 		 */
787*fa9e4066Sahrens 
788*fa9e4066Sahrens 		if (aclp->a_flags & 0xf) {
789*fa9e4066Sahrens 			where = strappend(where, ":");
790*fa9e4066Sahrens 			start = where;
791*fa9e4066Sahrens 			if (aclp->a_flags & ACE_FILE_INHERIT_ACE)
792*fa9e4066Sahrens 				where = strappend(where, "file_inherit/");
793*fa9e4066Sahrens 			if (aclp->a_flags & ACE_DIRECTORY_INHERIT_ACE)
794*fa9e4066Sahrens 				where = strappend(where, "dir_inherit/");
795*fa9e4066Sahrens 			if (aclp->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE)
796*fa9e4066Sahrens 				where = strappend(where, "no_propagate/");
797*fa9e4066Sahrens 			if (aclp->a_flags & ACE_INHERIT_ONLY_ACE)
798*fa9e4066Sahrens 				where = strappend(where, "inherit_only");
799*fa9e4066Sahrens 
800*fa9e4066Sahrens 			/*
801*fa9e4066Sahrens 			 * chop off trailing slash, if present
802*fa9e4066Sahrens 			 */
803*fa9e4066Sahrens 			if (start[strlen(start) - 1] == '/') {
804*fa9e4066Sahrens 				start[strlen(start) - 1] = '\0';
805*fa9e4066Sahrens 				where = start + strlen(start);
806*fa9e4066Sahrens 			}
807*fa9e4066Sahrens 		}
808*fa9e4066Sahrens 		if (i < aclcnt - 1)
809*fa9e4066Sahrens 			where = strappend(where, ",");
810*fa9e4066Sahrens 	}
811*fa9e4066Sahrens 	aclexport = dstr->aclexport;
812*fa9e4066Sahrens 	free(dstr);
813*fa9e4066Sahrens 	return (aclexport);
814*fa9e4066Sahrens }
815*fa9e4066Sahrens 
816*fa9e4066Sahrens static int
817*fa9e4066Sahrens build_iflags(char *str, int *iflags)
818*fa9e4066Sahrens {
819*fa9e4066Sahrens 
820*fa9e4066Sahrens 	char *tok;
821*fa9e4066Sahrens 	*iflags = 0;
822*fa9e4066Sahrens 
823*fa9e4066Sahrens 	tok = strtok(str, "/");
824*fa9e4066Sahrens 
825*fa9e4066Sahrens 	if (tok == NULL)
826*fa9e4066Sahrens 		return (1);
827*fa9e4066Sahrens 
828*fa9e4066Sahrens 	do {
829*fa9e4066Sahrens 		if (strcmp(tok, "file_inherit") == 0)
830*fa9e4066Sahrens 			*iflags |= ACE_FILE_INHERIT_ACE;
831*fa9e4066Sahrens 		else if (strcmp(tok, "dir_inherit") == 0)
832*fa9e4066Sahrens 			*iflags |= ACE_DIRECTORY_INHERIT_ACE;
833*fa9e4066Sahrens 		else if (strcmp(tok, "inherit_only") == 0)
834*fa9e4066Sahrens 			*iflags |= ACE_INHERIT_ONLY_ACE;
835*fa9e4066Sahrens 		else if (strcmp(tok, "no_propagate") == 0)
836*fa9e4066Sahrens 			*iflags |= ACE_NO_PROPAGATE_INHERIT_ACE;
837*fa9e4066Sahrens 		else
838*fa9e4066Sahrens 			return (1);
839*fa9e4066Sahrens 	} while (tok = strtok(NULL, "/"));
840*fa9e4066Sahrens 	return (0);
841*fa9e4066Sahrens }
842*fa9e4066Sahrens 
843*fa9e4066Sahrens /*
844*fa9e4066Sahrens  * Convert external acl representation to internal representation.
845*fa9e4066Sahrens  * The accepted syntax is: <acl_entry>[,<acl_entry>]*[,]
846*fa9e4066Sahrens  * The comma at the end is not prescribed by the man pages.
847*fa9e4066Sahrens  * But it is needed not to break the old programs.
848*fa9e4066Sahrens  */
849*fa9e4066Sahrens 
850*fa9e4066Sahrens int
851*fa9e4066Sahrens ace_aclfromtext(char *aclstr, acl_t **ret_aclp)
852*fa9e4066Sahrens {
853*fa9e4066Sahrens 	char		*fieldp;
854*fa9e4066Sahrens 	char		*tp;
855*fa9e4066Sahrens 	char		*nextp;
856*fa9e4066Sahrens 	char		*allocp;
857*fa9e4066Sahrens 	char		*aclimport;
858*fa9e4066Sahrens 	char 		*str;
859*fa9e4066Sahrens 	char		*perm_tok;
860*fa9e4066Sahrens 	int		entry_type;
861*fa9e4066Sahrens 	int		id;
862*fa9e4066Sahrens 	int		type;
863*fa9e4066Sahrens 	int		iflags;
864*fa9e4066Sahrens 	int		len;
865*fa9e4066Sahrens 	int		error;
866*fa9e4066Sahrens 	int32_t		perm;
867*fa9e4066Sahrens 	ace_t		*tmpaclp;
868*fa9e4066Sahrens 	acl_t		*aclp;
869*fa9e4066Sahrens 	struct group	*groupp;
870*fa9e4066Sahrens 	struct passwd	*passwdp;
871*fa9e4066Sahrens 
872*fa9e4066Sahrens 	if (! aclstr)
873*fa9e4066Sahrens 		return (EACL_INVALID_STR);
874*fa9e4066Sahrens 
875*fa9e4066Sahrens 	len = strlen(aclstr);
876*fa9e4066Sahrens 
877*fa9e4066Sahrens 	aclp = acl_alloc(ACE_T);
878*fa9e4066Sahrens 	if (aclp == NULL) {
879*fa9e4066Sahrens 		return (EACL_MEM_ERROR);
880*fa9e4066Sahrens 	}
881*fa9e4066Sahrens 
882*fa9e4066Sahrens 	*ret_aclp = NULL;
883*fa9e4066Sahrens 
884*fa9e4066Sahrens 	if ((aclimport = allocp = strdup(aclstr)) == NULL) {
885*fa9e4066Sahrens 		return (EACL_MEM_ERROR);
886*fa9e4066Sahrens 	}
887*fa9e4066Sahrens 
888*fa9e4066Sahrens 
889*fa9e4066Sahrens 	if (aclimport[len - 1] == ',')
890*fa9e4066Sahrens 		aclimport[len - 1] = '\0';
891*fa9e4066Sahrens 
892*fa9e4066Sahrens 	for (; aclimport; ) {
893*fa9e4066Sahrens 		/* look for an ACL entry */
894*fa9e4066Sahrens 		tp = strchr(aclimport, ',');
895*fa9e4066Sahrens 		if (tp == NULL) {
896*fa9e4066Sahrens 			nextp = NULL;
897*fa9e4066Sahrens 		} else {
898*fa9e4066Sahrens 			*tp = '\0';
899*fa9e4066Sahrens 			nextp = tp + 1;
900*fa9e4066Sahrens 		}
901*fa9e4066Sahrens 
902*fa9e4066Sahrens 		aclp->acl_cnt += 1;
903*fa9e4066Sahrens 
904*fa9e4066Sahrens 		/*
905*fa9e4066Sahrens 		 * get additional memory:
906*fa9e4066Sahrens 		 * can be more efficient by allocating a bigger block
907*fa9e4066Sahrens 		 * each time.
908*fa9e4066Sahrens 		 */
909*fa9e4066Sahrens 		if (aclp->acl_cnt > 1)
910*fa9e4066Sahrens 			tmpaclp = (ace_t *)realloc(aclp->acl_aclp,
911*fa9e4066Sahrens 			    sizeof (ace_t) * (aclp->acl_cnt));
912*fa9e4066Sahrens 		else
913*fa9e4066Sahrens 			tmpaclp = (ace_t *)malloc(sizeof (ace_t));
914*fa9e4066Sahrens 		if (tmpaclp == NULL) {
915*fa9e4066Sahrens 			free(allocp);
916*fa9e4066Sahrens 			acl_free(aclp);
917*fa9e4066Sahrens 			return (EACL_MEM_ERROR);
918*fa9e4066Sahrens 		}
919*fa9e4066Sahrens 		aclp->acl_aclp = tmpaclp;
920*fa9e4066Sahrens 		tmpaclp = (ace_t *)aclp->acl_aclp + (aclp->acl_cnt - 1);
921*fa9e4066Sahrens 
922*fa9e4066Sahrens 		/* look for entry type field */
923*fa9e4066Sahrens 		tp = strchr(aclimport, ':');
924*fa9e4066Sahrens 		if (tp == NULL) {
925*fa9e4066Sahrens 			free(allocp);
926*fa9e4066Sahrens 			acl_free(aclp);
927*fa9e4066Sahrens 			return (EACL_ENTRY_ERROR);
928*fa9e4066Sahrens 		} else
929*fa9e4066Sahrens 			*tp = '\0';
930*fa9e4066Sahrens 		if (strcmp(aclimport, "owner@") == 0) {
931*fa9e4066Sahrens 			entry_type = ACE_OWNER;
932*fa9e4066Sahrens 		} else if (strcmp(aclimport, "group@") == 0) {
933*fa9e4066Sahrens 			entry_type = ACE_GROUP | ACE_IDENTIFIER_GROUP;
934*fa9e4066Sahrens 		} else if (strcmp(aclimport, "everyone@") == 0) {
935*fa9e4066Sahrens 			entry_type = ACE_EVERYONE;
936*fa9e4066Sahrens 		} else if (strcmp(aclimport, "group") == 0) {
937*fa9e4066Sahrens 			entry_type = ACE_IDENTIFIER_GROUP;
938*fa9e4066Sahrens 		} else if (strcmp(aclimport, "user") == 0) {
939*fa9e4066Sahrens 			entry_type = 0;
940*fa9e4066Sahrens 		} else {
941*fa9e4066Sahrens 			free(allocp);
942*fa9e4066Sahrens 			acl_free(aclp);
943*fa9e4066Sahrens 			return (EACL_ENTRY_ERROR);
944*fa9e4066Sahrens 		}
945*fa9e4066Sahrens 
946*fa9e4066Sahrens 		/*
947*fa9e4066Sahrens 		 * If not an abstraction owner@, group@ or everyone@
948*fa9e4066Sahrens 		 * then we must have a user/group name next
949*fa9e4066Sahrens 		 */
950*fa9e4066Sahrens 
951*fa9e4066Sahrens 		if (entry_type == 0 || entry_type == ACE_IDENTIFIER_GROUP) {
952*fa9e4066Sahrens 			fieldp = tp + 1;
953*fa9e4066Sahrens 			tp = strchr(fieldp, ':');
954*fa9e4066Sahrens 			if (tp == NULL) {
955*fa9e4066Sahrens 				free(allocp);
956*fa9e4066Sahrens 				acl_free(aclp);
957*fa9e4066Sahrens 				return (EACL_INVALID_USER_GROUP);
958*fa9e4066Sahrens 			} else
959*fa9e4066Sahrens 				*tp = '\0';
960*fa9e4066Sahrens 			if (fieldp != tp) {
961*fa9e4066Sahrens 				/*
962*fa9e4066Sahrens 				 * The second field could be empty. We only care
963*fa9e4066Sahrens 				 * when the field has user/group name.
964*fa9e4066Sahrens 				 */
965*fa9e4066Sahrens 				if (entry_type == 0) {
966*fa9e4066Sahrens 					/*
967*fa9e4066Sahrens 					 * The reentrant interface getpwnam_r()
968*fa9e4066Sahrens 					 * is uncommitted and subject to
969*fa9e4066Sahrens 					 * change. Use the friendlier interface
970*fa9e4066Sahrens 					 * getpwnam().
971*fa9e4066Sahrens 					 */
972*fa9e4066Sahrens 					error = 0;
973*fa9e4066Sahrens 					passwdp = getpwnam(fieldp);
974*fa9e4066Sahrens 					if (passwdp == NULL) {
975*fa9e4066Sahrens 						error = acl_str_to_id(
976*fa9e4066Sahrens 						    fieldp, &id);
977*fa9e4066Sahrens 					} else {
978*fa9e4066Sahrens 						id = passwdp->pw_uid;
979*fa9e4066Sahrens 					}
980*fa9e4066Sahrens 
981*fa9e4066Sahrens 					if (error) {
982*fa9e4066Sahrens 						free(allocp);
983*fa9e4066Sahrens 						acl_free(aclp);
984*fa9e4066Sahrens 						return (error);
985*fa9e4066Sahrens 					}
986*fa9e4066Sahrens 				} else {
987*fa9e4066Sahrens 					error = 0;
988*fa9e4066Sahrens 					if (entry_type ==
989*fa9e4066Sahrens 					    ACE_IDENTIFIER_GROUP) {
990*fa9e4066Sahrens 						groupp = getgrnam(fieldp);
991*fa9e4066Sahrens 						if (groupp == NULL) {
992*fa9e4066Sahrens 							/* no group? */
993*fa9e4066Sahrens 							error = acl_str_to_id(
994*fa9e4066Sahrens 							    fieldp, &id);
995*fa9e4066Sahrens 						} else
996*fa9e4066Sahrens 							id = groupp->gr_gid;
997*fa9e4066Sahrens 
998*fa9e4066Sahrens 					} else if ((entry_type == ACE_OWNER) ||
999*fa9e4066Sahrens 					    (entry_type ==
1000*fa9e4066Sahrens 					    (ACE_IDENTIFIER_GROUP|ACE_GROUP)) ||
1001*fa9e4066Sahrens 					    (entry_type != ACE_EVERYONE)) {
1002*fa9e4066Sahrens 						error = EACL_FIELD_NOT_BLANK;
1003*fa9e4066Sahrens 					} else {
1004*fa9e4066Sahrens 						error = EACL_ENTRY_ERROR;
1005*fa9e4066Sahrens 					}
1006*fa9e4066Sahrens 
1007*fa9e4066Sahrens 					if (error) {
1008*fa9e4066Sahrens 						free(allocp);
1009*fa9e4066Sahrens 						acl_free(aclp);
1010*fa9e4066Sahrens 						return (error);
1011*fa9e4066Sahrens 					}
1012*fa9e4066Sahrens 				}
1013*fa9e4066Sahrens 			}
1014*fa9e4066Sahrens 		} else {
1015*fa9e4066Sahrens 			id = -1;
1016*fa9e4066Sahrens 		}
1017*fa9e4066Sahrens 
1018*fa9e4066Sahrens 		/* next field: permission */
1019*fa9e4066Sahrens 		fieldp = tp + 1;
1020*fa9e4066Sahrens 		tp = strchr(fieldp, ':');
1021*fa9e4066Sahrens 		if (tp == NULL) {
1022*fa9e4066Sahrens 			free(allocp);
1023*fa9e4066Sahrens 			acl_free(aclp);
1024*fa9e4066Sahrens 			return (EACL_PERM_MASK_ERROR);
1025*fa9e4066Sahrens 		} else
1026*fa9e4066Sahrens 			*tp = '\0';
1027*fa9e4066Sahrens 
1028*fa9e4066Sahrens 		perm = 0;
1029*fa9e4066Sahrens 
1030*fa9e4066Sahrens 		perm_tok = strtok(fieldp, "/");
1031*fa9e4066Sahrens 		if (perm_tok == NULL) {
1032*fa9e4066Sahrens 			perm = 0;
1033*fa9e4066Sahrens 		} else {
1034*fa9e4066Sahrens 			do {
1035*fa9e4066Sahrens 				if (ace_permask(perm_tok, &perm) != 0) {
1036*fa9e4066Sahrens 					free(allocp);
1037*fa9e4066Sahrens 					acl_free(aclp);
1038*fa9e4066Sahrens 					return (EACL_PERM_MASK_ERROR);
1039*fa9e4066Sahrens 				}
1040*fa9e4066Sahrens 			} while (perm_tok = strtok(NULL, "/"));
1041*fa9e4066Sahrens 		}
1042*fa9e4066Sahrens 
1043*fa9e4066Sahrens 		/* grab allow/deny */
1044*fa9e4066Sahrens 		fieldp = tp + 1;
1045*fa9e4066Sahrens 		tp = strchr(fieldp, ':');
1046*fa9e4066Sahrens 		if (tp != NULL)
1047*fa9e4066Sahrens 			*tp = '\0';
1048*fa9e4066Sahrens 
1049*fa9e4066Sahrens 		if (strcmp(fieldp, "allow") == 0)
1050*fa9e4066Sahrens 			type = ACE_ACCESS_ALLOWED_ACE_TYPE;
1051*fa9e4066Sahrens 		else if (strcmp(fieldp, "deny") == 0)
1052*fa9e4066Sahrens 			type = ACE_ACCESS_DENIED_ACE_TYPE;
1053*fa9e4066Sahrens 		else {
1054*fa9e4066Sahrens 			free(allocp);
1055*fa9e4066Sahrens 			acl_free(aclp);
1056*fa9e4066Sahrens 			return (EACL_INVALID_ACCESS_TYPE);
1057*fa9e4066Sahrens 		}
1058*fa9e4066Sahrens 
1059*fa9e4066Sahrens 		/* grab option inherit flags */
1060*fa9e4066Sahrens 
1061*fa9e4066Sahrens 		iflags = 0;
1062*fa9e4066Sahrens 		if (tp != NULL) {
1063*fa9e4066Sahrens 			fieldp = tp + 1;
1064*fa9e4066Sahrens 			if (fieldp != NULL) {
1065*fa9e4066Sahrens 				*tp = '\0';
1066*fa9e4066Sahrens 				str = fieldp;
1067*fa9e4066Sahrens 				if (build_iflags(str, &iflags) != 0) {
1068*fa9e4066Sahrens 					free(allocp);
1069*fa9e4066Sahrens 					acl_free(aclp);
1070*fa9e4066Sahrens 					return (EACL_INHERIT_ERROR);
1071*fa9e4066Sahrens 				}
1072*fa9e4066Sahrens 			} else {
1073*fa9e4066Sahrens 				free(allocp);
1074*fa9e4066Sahrens 				acl_free(aclp);
1075*fa9e4066Sahrens 				return (EACL_UNKNOWN_DATA);
1076*fa9e4066Sahrens 			}
1077*fa9e4066Sahrens 		}
1078*fa9e4066Sahrens 		/* slap fields into ace_t structure */
1079*fa9e4066Sahrens 
1080*fa9e4066Sahrens 		tmpaclp->a_flags = entry_type;
1081*fa9e4066Sahrens 		tmpaclp->a_flags |= iflags;
1082*fa9e4066Sahrens 		tmpaclp->a_who = id;
1083*fa9e4066Sahrens 		tmpaclp->a_access_mask = perm;
1084*fa9e4066Sahrens 		tmpaclp->a_type = type;
1085*fa9e4066Sahrens 		aclimport = nextp;
1086*fa9e4066Sahrens 	}
1087*fa9e4066Sahrens 	free(allocp);
1088*fa9e4066Sahrens 	*ret_aclp = aclp;
1089*fa9e4066Sahrens 	return (0);
1090*fa9e4066Sahrens }
1091*fa9e4066Sahrens 
1092*fa9e4066Sahrens char
1093*fa9e4066Sahrens *acl_totext(acl_t *aclp)
1094*fa9e4066Sahrens {
1095*fa9e4066Sahrens 	if (aclp == NULL)
1096*fa9e4066Sahrens 		return (NULL);
1097*fa9e4066Sahrens 
1098*fa9e4066Sahrens 	switch (aclp->acl_type) {
1099*fa9e4066Sahrens 	case ACE_T:
1100*fa9e4066Sahrens 		return (ace_acltotext(aclp));
1101*fa9e4066Sahrens 	case ACLENT_T:
1102*fa9e4066Sahrens 		return (acltotext(aclp->acl_aclp, aclp->acl_cnt));
1103*fa9e4066Sahrens 	}
1104*fa9e4066Sahrens 	return (NULL);
1105*fa9e4066Sahrens }
1106*fa9e4066Sahrens 
1107*fa9e4066Sahrens int
1108*fa9e4066Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp)
1109*fa9e4066Sahrens {
1110*fa9e4066Sahrens 	acl_t *aclp;
1111*fa9e4066Sahrens 	char *token;
1112*fa9e4066Sahrens 	char *ptr;
1113*fa9e4066Sahrens 	char *textp;
1114*fa9e4066Sahrens 	enum acl_type flavor;
1115*fa9e4066Sahrens 	int colon_cnt = 0;
1116*fa9e4066Sahrens 	int error;
1117*fa9e4066Sahrens 
1118*fa9e4066Sahrens 	/*
1119*fa9e4066Sahrens 	 * first try and detect what type of acl entries we have
1120*fa9e4066Sahrens 	 *
1121*fa9e4066Sahrens 	 * aclent_t can have 1, 2 or 3 colons
1122*fa9e4066Sahrens 	 * if 3 then must have word default:
1123*fa9e4066Sahrens 	 *
1124*fa9e4066Sahrens 	 * ace_t can have 2, 3 or 4
1125*fa9e4066Sahrens 	 * for 2 then must be owner@, group@ or everyone@
1126*fa9e4066Sahrens 	 */
1127*fa9e4066Sahrens 
1128*fa9e4066Sahrens 	textp = strdup(acltextp);
1129*fa9e4066Sahrens 	if (textp == NULL)
1130*fa9e4066Sahrens 		return (-1);
1131*fa9e4066Sahrens 
1132*fa9e4066Sahrens 	token = strtok(textp, ",");
1133*fa9e4066Sahrens 	if (token == NULL) {
1134*fa9e4066Sahrens 		free(textp);
1135*fa9e4066Sahrens 		return (-1);
1136*fa9e4066Sahrens 	}
1137*fa9e4066Sahrens 
1138*fa9e4066Sahrens 	for (ptr = token; *ptr; ptr++) {
1139*fa9e4066Sahrens 		if (*ptr == ':')
1140*fa9e4066Sahrens 			colon_cnt++;
1141*fa9e4066Sahrens 	}
1142*fa9e4066Sahrens 
1143*fa9e4066Sahrens 	if (colon_cnt == 1 || colon_cnt == 2) {
1144*fa9e4066Sahrens 		if ((strncmp(acltextp, "owner@", 6) == 0) ||
1145*fa9e4066Sahrens 		    (strncmp(acltextp, "group@", 6) == 0) ||
1146*fa9e4066Sahrens 		    (strncmp(acltextp, "everyone@", 9) == 0))
1147*fa9e4066Sahrens 			flavor = ACE_T;
1148*fa9e4066Sahrens 		else
1149*fa9e4066Sahrens 			flavor = ACLENT_T;
1150*fa9e4066Sahrens 	} else if (colon_cnt == 3) {
1151*fa9e4066Sahrens 		ptr = strtok(token, ":");
1152*fa9e4066Sahrens 		if (ptr == NULL) {
1153*fa9e4066Sahrens 			free(textp);
1154*fa9e4066Sahrens 			return (EACL_MISSING_FIELDS);
1155*fa9e4066Sahrens 		} else if (strcmp(ptr, "default") == 0) {
1156*fa9e4066Sahrens 			flavor = ACLENT_T;
1157*fa9e4066Sahrens 		} else {
1158*fa9e4066Sahrens 			flavor = ACE_T;
1159*fa9e4066Sahrens 		}
1160*fa9e4066Sahrens 	} else if (colon_cnt == 4) {
1161*fa9e4066Sahrens 		flavor = ACE_T;
1162*fa9e4066Sahrens 	} else {
1163*fa9e4066Sahrens 		free(textp);
1164*fa9e4066Sahrens 		return (EACL_MISSING_FIELDS);
1165*fa9e4066Sahrens 	}
1166*fa9e4066Sahrens 
1167*fa9e4066Sahrens 
1168*fa9e4066Sahrens 	free(textp);
1169*fa9e4066Sahrens 
1170*fa9e4066Sahrens 	if (flavor == ACLENT_T)
1171*fa9e4066Sahrens 		error = aclent_aclfromtext((char *)acltextp, &aclp);
1172*fa9e4066Sahrens 	else
1173*fa9e4066Sahrens 		error = ace_aclfromtext((char *)acltextp, &aclp);
1174*fa9e4066Sahrens 
1175*fa9e4066Sahrens 	*ret_aclp = aclp;
1176*fa9e4066Sahrens 	return (error);
1177*fa9e4066Sahrens }
1178