xref: /titanic_53/usr/src/lib/libsec/common/acltext.c (revision 11e3217022ca85e61c9af16135a16592fe10dc6b)
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>
35fa9e4066Sahrens #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <sys/param.h>
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <sys/acl.h>
39fa9e4066Sahrens #include <aclutils.h>
40fa9e4066Sahrens #include <libintl.h>
41fa9e4066Sahrens 
42fa9e4066Sahrens 
43fa9e4066Sahrens 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 
64*11e32170Shm123892 #define	UPDATE_WHERE	where = dstr->aclexport + strlen(dstr->aclexport)
65*11e32170Shm123892 
667c478bd9Sstevel@tonic-gate struct dynaclstr {
677c478bd9Sstevel@tonic-gate 	size_t bufsize;		/* current size of aclexport */
687c478bd9Sstevel@tonic-gate 	char *aclexport;
697c478bd9Sstevel@tonic-gate };
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate static char *strappend(char *, char *);
727c478bd9Sstevel@tonic-gate static char *convert_perm(char *, o_mode_t);
737c478bd9Sstevel@tonic-gate static int increase_length(struct dynaclstr *, size_t);
747c478bd9Sstevel@tonic-gate 
75fa9e4066Sahrens static int
76fa9e4066Sahrens acl_str_to_id(char *str, int *id)
77fa9e4066Sahrens {
78fa9e4066Sahrens 	char *end;
79fa9e4066Sahrens 	uid_t value;
80fa9e4066Sahrens 
81fa9e4066Sahrens 	value = strtol(str, &end, 10);
82fa9e4066Sahrens 
83fa9e4066Sahrens 	if (errno != 0 || *end != '\0')
84fa9e4066Sahrens 		return (EACL_INVALID_USER_GROUP);
85fa9e4066Sahrens 
86fa9e4066Sahrens 	*id = value;
87fa9e4066Sahrens 
88fa9e4066Sahrens 	return (0);
89fa9e4066Sahrens }
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate /*
927c478bd9Sstevel@tonic-gate  * Convert internal acl representation to external representation.
937c478bd9Sstevel@tonic-gate  *
947c478bd9Sstevel@tonic-gate  * The length of a non-owning user name or non-owning group name ie entries
957c478bd9Sstevel@tonic-gate  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
967c478bd9Sstevel@tonic-gate  * thus check the length of these entries, and if greater than LOGNAME_MAX,
977c478bd9Sstevel@tonic-gate  * we realloc() via increase_length().
987c478bd9Sstevel@tonic-gate  *
997c478bd9Sstevel@tonic-gate  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
1007c478bd9Sstevel@tonic-gate  * adhered to.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate char *
1037c478bd9Sstevel@tonic-gate acltotext(aclent_t *aclp, int aclcnt)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	char		*aclexport;
1067c478bd9Sstevel@tonic-gate 	char		*where;
1077c478bd9Sstevel@tonic-gate 	struct group	*groupp;
1087c478bd9Sstevel@tonic-gate 	struct passwd	*passwdp;
1097c478bd9Sstevel@tonic-gate 	struct dynaclstr *dstr;
1107c478bd9Sstevel@tonic-gate 	int		i, rtn;
1117c478bd9Sstevel@tonic-gate 	size_t		excess = 0;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	if (aclp == NULL)
1147c478bd9Sstevel@tonic-gate 		return (NULL);
1157c478bd9Sstevel@tonic-gate 	if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL)
1167c478bd9Sstevel@tonic-gate 		return (NULL);
1177c478bd9Sstevel@tonic-gate 	dstr->bufsize = aclcnt * ACL_ENTRY_SIZE;
1187c478bd9Sstevel@tonic-gate 	if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) {
1197c478bd9Sstevel@tonic-gate 		free(dstr);
1207c478bd9Sstevel@tonic-gate 		return (NULL);
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 	*dstr->aclexport = '\0';
1237c478bd9Sstevel@tonic-gate 	where = dstr->aclexport;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	for (i = 0; i < aclcnt; i++, aclp++) {
1267c478bd9Sstevel@tonic-gate 		switch (aclp->a_type) {
1277c478bd9Sstevel@tonic-gate 		case DEF_USER_OBJ:
1287c478bd9Sstevel@tonic-gate 		case USER_OBJ:
1297c478bd9Sstevel@tonic-gate 			if (aclp->a_type == USER_OBJ)
1307c478bd9Sstevel@tonic-gate 				where = strappend(where, "user::");
1317c478bd9Sstevel@tonic-gate 			else
1327c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultuser::");
1337c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
1347c478bd9Sstevel@tonic-gate 			break;
1357c478bd9Sstevel@tonic-gate 		case DEF_USER:
1367c478bd9Sstevel@tonic-gate 		case USER:
1377c478bd9Sstevel@tonic-gate 			if (aclp->a_type == USER)
1387c478bd9Sstevel@tonic-gate 				where = strappend(where, "user:");
1397c478bd9Sstevel@tonic-gate 			else
1407c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultuser:");
1417c478bd9Sstevel@tonic-gate 			passwdp = getpwuid(aclp->a_id);
1427c478bd9Sstevel@tonic-gate 			if (passwdp == (struct passwd *)NULL) {
1437c478bd9Sstevel@tonic-gate 				/* put in uid instead */
1447c478bd9Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
145*11e32170Shm123892 				UPDATE_WHERE;
1467c478bd9Sstevel@tonic-gate 			} else {
1477c478bd9Sstevel@tonic-gate 				excess = strlen(passwdp->pw_name) - LOGNAME_MAX;
1487c478bd9Sstevel@tonic-gate 				if (excess > 0) {
1497c478bd9Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
1507c478bd9Sstevel@tonic-gate 					if (rtn == 1) {
151*11e32170Shm123892 						UPDATE_WHERE;
1527c478bd9Sstevel@tonic-gate 					} else {
1537c478bd9Sstevel@tonic-gate 						free(dstr->aclexport);
1547c478bd9Sstevel@tonic-gate 						free(dstr);
1557c478bd9Sstevel@tonic-gate 						return (NULL);
1567c478bd9Sstevel@tonic-gate 					}
1577c478bd9Sstevel@tonic-gate 				}
1587c478bd9Sstevel@tonic-gate 				where = strappend(where, passwdp->pw_name);
1597c478bd9Sstevel@tonic-gate 			}
1607c478bd9Sstevel@tonic-gate 			where = strappend(where, ":");
1617c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
1627c478bd9Sstevel@tonic-gate 			break;
1637c478bd9Sstevel@tonic-gate 		case DEF_GROUP_OBJ:
1647c478bd9Sstevel@tonic-gate 		case GROUP_OBJ:
1657c478bd9Sstevel@tonic-gate 			if (aclp->a_type == GROUP_OBJ)
1667c478bd9Sstevel@tonic-gate 				where = strappend(where, "group::");
1677c478bd9Sstevel@tonic-gate 			else
1687c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultgroup::");
1697c478bd9Sstevel@tonic-gate 			where = convert_perm(where, aclp->a_perm);
1707c478bd9Sstevel@tonic-gate 			break;
1717c478bd9Sstevel@tonic-gate 		case DEF_GROUP:
1727c478bd9Sstevel@tonic-gate 		case GROUP:
1737c478bd9Sstevel@tonic-gate 			if (aclp->a_type == GROUP)
1747c478bd9Sstevel@tonic-gate 				where = strappend(where, "group:");
1757c478bd9Sstevel@tonic-gate 			else
1767c478bd9Sstevel@tonic-gate 				where = strappend(where, "defaultgroup:");
1777c478bd9Sstevel@tonic-gate 			groupp = getgrgid(aclp->a_id);
1787c478bd9Sstevel@tonic-gate 			if (groupp == (struct group *)NULL) {
1797c478bd9Sstevel@tonic-gate 				/* put in gid instead */
1807c478bd9Sstevel@tonic-gate 				(void) sprintf(where, "%d", aclp->a_id);
181*11e32170Shm123892 				UPDATE_WHERE;
1827c478bd9Sstevel@tonic-gate 			} else {
1837c478bd9Sstevel@tonic-gate 				excess = strlen(groupp->gr_name) - LOGNAME_MAX;
1847c478bd9Sstevel@tonic-gate 				if (excess > 0) {
1857c478bd9Sstevel@tonic-gate 					rtn = increase_length(dstr, excess);
1867c478bd9Sstevel@tonic-gate 					if (rtn == 1) {
187*11e32170Shm123892 						UPDATE_WHERE;
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  */
235fa9e4066Sahrens static int
236fa9e4066Sahrens 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;
246fa9e4066Sahrens 	int		error;
2477c478bd9Sstevel@tonic-gate 	o_mode_t	perm;
2487c478bd9Sstevel@tonic-gate 	aclent_t	*tmpaclp;
249fa9e4066Sahrens 	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 
258fa9e4066Sahrens 	aclp = acl_alloc(ACLENT_T);
259fa9e4066Sahrens 	if (aclp == NULL) {
260fa9e4066Sahrens 		return (EACL_MEM_ERROR);
261fa9e4066Sahrens 	}
262fa9e4066Sahrens 
263fa9e4066Sahrens 	*ret_aclp = NULL;
264fa9e4066Sahrens 
2657c478bd9Sstevel@tonic-gate 	len = strlen(aclstr);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if ((aclimport = allocp = strdup(aclstr)) == NULL) {
268fa9e4066Sahrens 		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 
284fa9e4066Sahrens 		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 		 */
291fa9e4066Sahrens 		if (aclp->acl_cnt > 1)
292fa9e4066Sahrens 			tmpaclp = (aclent_t *)realloc(aclp->acl_aclp,
293fa9e4066Sahrens 			    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);
298fa9e4066Sahrens 			acl_free(aclp);
299fa9e4066Sahrens 			return (EACL_MEM_ERROR);
3007c478bd9Sstevel@tonic-gate 		}
301fa9e4066Sahrens 		aclp->acl_aclp = tmpaclp;
302fa9e4066Sahrens 		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) {
307fa9e4066Sahrens 			free(allocp);
308fa9e4066Sahrens 			if (aclp)
309fa9e4066Sahrens 				acl_free(aclp);
310fa9e4066Sahrens 			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 {
342fa9e4066Sahrens 			free(allocp);
343fa9e4066Sahrens 			acl_free(aclp);
344fa9e4066Sahrens 			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) {
354fa9e4066Sahrens 				free(allocp);
355fa9e4066Sahrens 				acl_free(aclp);
356fa9e4066Sahrens 				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 					 */
372fa9e4066Sahrens 					error = 0;
3737c478bd9Sstevel@tonic-gate 					passwdp = getpwnam(fieldp);
3747c478bd9Sstevel@tonic-gate 					if (passwdp == NULL) {
375fa9e4066Sahrens 						error = acl_str_to_id(fieldp,
376fa9e4066Sahrens 						    &id);
3777c478bd9Sstevel@tonic-gate 					} else {
378fa9e4066Sahrens 						id = passwdp->pw_uid;
379fa9e4066Sahrens 					}
380fa9e4066Sahrens 
381fa9e4066Sahrens 					if (error) {
382fa9e4066Sahrens 						free(allocp);
383fa9e4066Sahrens 						acl_free(aclp);
384fa9e4066Sahrens 						return (error);
385fa9e4066Sahrens 					}
386fa9e4066Sahrens 
387fa9e4066Sahrens 				} else {
388fa9e4066Sahrens 					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) {
393fa9e4066Sahrens 							error = acl_str_to_id(
394fa9e4066Sahrens 							    fieldp, &id);
3957c478bd9Sstevel@tonic-gate 						}
396fa9e4066Sahrens 						if (error == 0)
3977c478bd9Sstevel@tonic-gate 							id = groupp->gr_gid;
398fa9e4066Sahrens 					}
399fa9e4066Sahrens 					if (error) {
400fa9e4066Sahrens 						free(allocp);
401fa9e4066Sahrens 						acl_free(aclp);
402fa9e4066Sahrens 						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 */
426fa9e4066Sahrens 			free(allocp);
427fa9e4066Sahrens 			acl_free(aclp);
428fa9e4066Sahrens 			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] != '-') {
439fa9e4066Sahrens 					free(allocp);
440fa9e4066Sahrens 					acl_free(aclp);
441fa9e4066Sahrens 					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);
452fa9e4066Sahrens 	*ret_aclp = aclp;
453fa9e4066Sahrens 	return (0);
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate 
456fa9e4066Sahrens aclent_t *
457fa9e4066Sahrens aclfromtext(char *aclstr, int *aclcnt)
458fa9e4066Sahrens {
459fa9e4066Sahrens 	acl_t *aclp;
460fa9e4066Sahrens 	aclent_t *aclentp;
461fa9e4066Sahrens 	int error;
462fa9e4066Sahrens 
463fa9e4066Sahrens 	error = aclent_aclfromtext(aclstr, &aclp);
464fa9e4066Sahrens 	if (error)
465fa9e4066Sahrens 		return (NULL);
466fa9e4066Sahrens 
467fa9e4066Sahrens 	aclentp = aclp->acl_aclp;
468fa9e4066Sahrens 	aclp->acl_aclp = NULL;
469fa9e4066Sahrens 	acl_free(aclp);
470fa9e4066Sahrens 
471fa9e4066Sahrens 	*aclcnt = aclp->acl_cnt;
472fa9e4066Sahrens 	return (aclentp);
473fa9e4066Sahrens }
474fa9e4066Sahrens 
475fa9e4066Sahrens 
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 
502fa9e4066Sahrens static char *
503fa9e4066Sahrens ace_convert_perm(char *where, mode_t perm, int isdir, int iflags)
504fa9e4066Sahrens {
505fa9e4066Sahrens 	char *start = where;
506fa9e4066Sahrens 
507fa9e4066Sahrens 	/*
508fa9e4066Sahrens 	 * The following mneumonics all have the
509fa9e4066Sahrens 	 * same value.  The only difference is the
510fa9e4066Sahrens 	 * first value is for files and second for directories
511fa9e4066Sahrens 	 * ACE_READ_DATA/ACE_LIST_DIRECTORY
512fa9e4066Sahrens 	 * ACE_WRITE_DATA/ACE_ADD_FILE
513fa9e4066Sahrens 	 * ACE_APPEND_DATA/ACE_ADD_SUBDIRECTORY
514fa9e4066Sahrens 	 */
515fa9e4066Sahrens 
516fa9e4066Sahrens 	/*
517fa9e4066Sahrens 	 * If ACE is a directory, but inheritance indicates its
518fa9e4066Sahrens 	 * for a file then print permissions for file rather than
519fa9e4066Sahrens 	 * dir.
520fa9e4066Sahrens 	 */
521fa9e4066Sahrens 	if (isdir) {
522fa9e4066Sahrens 		if (perm & ACE_LIST_DIRECTORY) {
523fa9e4066Sahrens 			if (iflags == ACE_FILE_INHERIT_ACE)
524fa9e4066Sahrens 				where = strappend(where, "read_data/");
525fa9e4066Sahrens 			else
526fa9e4066Sahrens 				where = strappend(where,
527fa9e4066Sahrens 				    "list_directory/read_data/");
528fa9e4066Sahrens 		}
529fa9e4066Sahrens 		if (perm & ACE_ADD_FILE) {
530fa9e4066Sahrens 			if (iflags == ACE_FILE_INHERIT_ACE)
531fa9e4066Sahrens 				where = strappend(where, "write_data/");
532fa9e4066Sahrens 			else
533fa9e4066Sahrens 				where = strappend(where,
534fa9e4066Sahrens 				    "add_file/write_data/");
535fa9e4066Sahrens 		}
536fa9e4066Sahrens 		if (perm & ACE_ADD_SUBDIRECTORY) {
537fa9e4066Sahrens 			if (iflags == ACE_FILE_INHERIT_ACE)
538fa9e4066Sahrens 				where = strappend(where, "append_data/");
539fa9e4066Sahrens 			else
540fa9e4066Sahrens 				where = strappend(where,
541fa9e4066Sahrens 				    "add_subdirectory/append_data/");
542fa9e4066Sahrens 		}
543fa9e4066Sahrens 	} else {
544fa9e4066Sahrens 		if (perm & ACE_READ_DATA)
545fa9e4066Sahrens 			where = strappend(where, "read_data/");
546fa9e4066Sahrens 		if (perm & ACE_WRITE_DATA)
547fa9e4066Sahrens 			where = strappend(where, "write_data/");
548fa9e4066Sahrens 		if (perm & ACE_APPEND_DATA)
549fa9e4066Sahrens 			where = strappend(where, "append_data/");
550fa9e4066Sahrens 	}
551fa9e4066Sahrens 	if (perm & ACE_READ_NAMED_ATTRS)
552fa9e4066Sahrens 		where = strappend(where, "read_xattr/");
553fa9e4066Sahrens 	if (perm & ACE_WRITE_NAMED_ATTRS)
554fa9e4066Sahrens 		where = strappend(where, "write_xattr/");
555fa9e4066Sahrens 	if (perm & ACE_EXECUTE)
556fa9e4066Sahrens 		where = strappend(where, "execute/");
557fa9e4066Sahrens 	if (perm & ACE_DELETE_CHILD)
558fa9e4066Sahrens 		where = strappend(where, "delete_child/");
559fa9e4066Sahrens 	if (perm & ACE_READ_ATTRIBUTES)
560fa9e4066Sahrens 		where = strappend(where, "read_attributes/");
561fa9e4066Sahrens 	if (perm & ACE_WRITE_ATTRIBUTES)
562fa9e4066Sahrens 		where = strappend(where, "write_attributes/");
563fa9e4066Sahrens 	if (perm & ACE_DELETE)
564fa9e4066Sahrens 		where = strappend(where, "delete/");
565fa9e4066Sahrens 	if (perm & ACE_READ_ACL)
566fa9e4066Sahrens 		where = strappend(where, "read_acl/");
567fa9e4066Sahrens 	if (perm & ACE_WRITE_ACL)
568fa9e4066Sahrens 		where = strappend(where, "write_acl/");
569fa9e4066Sahrens 	if (perm & ACE_WRITE_OWNER)
570fa9e4066Sahrens 		where = strappend(where, "write_owner/");
571fa9e4066Sahrens 	if (perm & ACE_SYNCHRONIZE)
572fa9e4066Sahrens 		where = strappend(where, "synchronize");
573fa9e4066Sahrens 
574fa9e4066Sahrens 	if (start[strlen(start) - 1] == '/') {
575fa9e4066Sahrens 		start[strlen(start) - 1] = '\0';
576fa9e4066Sahrens 		where = start + strlen(start);
577fa9e4066Sahrens 	}
578fa9e4066Sahrens 	return (where);
579fa9e4066Sahrens }
580fa9e4066Sahrens 
581fa9e4066Sahrens int
582fa9e4066Sahrens ace_permask(char *perm_tok, int *perm)
583fa9e4066Sahrens {
584fa9e4066Sahrens 	if (strcmp(perm_tok, "read_data") == 0)
585fa9e4066Sahrens 		*perm |= ACE_READ_DATA;
586fa9e4066Sahrens 	else if (strcmp(perm_tok, "list_directory") == 0)
587fa9e4066Sahrens 		*perm |= ACE_LIST_DIRECTORY;
588fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_data") == 0)
589fa9e4066Sahrens 		*perm |= ACE_WRITE_DATA;
590fa9e4066Sahrens 	else if (strcmp(perm_tok, "add_file") == 0)
591fa9e4066Sahrens 		*perm |= ACE_ADD_FILE;
592fa9e4066Sahrens 	else if (strcmp(perm_tok, "append_data") == 0)
593fa9e4066Sahrens 		*perm |= ACE_APPEND_DATA;
594fa9e4066Sahrens 	else if (strcmp(perm_tok, "add_subdirectory") == 0)
595fa9e4066Sahrens 		*perm |= ACE_ADD_SUBDIRECTORY;
596fa9e4066Sahrens 	else if (strcmp(perm_tok, "read_xattr") == 0)
597fa9e4066Sahrens 		*perm |= ACE_READ_NAMED_ATTRS;
598fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_xattr") == 0)
599fa9e4066Sahrens 		*perm |= ACE_WRITE_NAMED_ATTRS;
600fa9e4066Sahrens 	else if (strcmp(perm_tok, "execute") == 0)
601fa9e4066Sahrens 		*perm |= ACE_EXECUTE;
602fa9e4066Sahrens 	else if (strcmp(perm_tok, "delete_child") == 0)
603fa9e4066Sahrens 		*perm |= ACE_DELETE_CHILD;
604fa9e4066Sahrens 	else if (strcmp(perm_tok, "read_attributes") == 0)
605fa9e4066Sahrens 		*perm |= ACE_READ_ATTRIBUTES;
606fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_attributes") == 0)
607fa9e4066Sahrens 		*perm |= ACE_WRITE_ATTRIBUTES;
608fa9e4066Sahrens 	else if (strcmp(perm_tok, "delete") == 0)
609fa9e4066Sahrens 		*perm |= ACE_DELETE;
610fa9e4066Sahrens 	else if (strcmp(perm_tok, "read_acl") == 0)
611fa9e4066Sahrens 		*perm |= ACE_READ_ACL;
612fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_acl") == 0)
613fa9e4066Sahrens 		*perm |= ACE_WRITE_ACL;
614fa9e4066Sahrens 	else if (strcmp(perm_tok, "write_owner") == 0)
615fa9e4066Sahrens 		*perm |= ACE_WRITE_OWNER;
616fa9e4066Sahrens 	else if (strcmp(perm_tok, "synchronize") == 0)
617fa9e4066Sahrens 		*perm |= ACE_SYNCHRONIZE;
618fa9e4066Sahrens 	else {
619fa9e4066Sahrens 		return (1);
620fa9e4066Sahrens 	}
621fa9e4066Sahrens 
622fa9e4066Sahrens 	return (0);
623fa9e4066Sahrens }
624fa9e4066Sahrens 
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 }
644fa9e4066Sahrens 
645fa9e4066Sahrens /*
646fa9e4066Sahrens  * ace_acltotext() conver each ace formatted acl to look like this:
647fa9e4066Sahrens  *
648fa9e4066Sahrens  * entry_type:uid^gid^name:perms:allow^deny[:flags][,]
649fa9e4066Sahrens  *
650fa9e4066Sahrens  * The maximum length of entry_type is 5 ("group")
651fa9e4066Sahrens  *
652fa9e4066Sahrens  * The max length of a uid^gid^name entry (in theory) is 8, hence we use
653fa9e4066Sahrens  * LOGNAME_MAX.
654fa9e4066Sahrens  *
655fa9e4066Sahrens  * The length of a perms entry is 144 i.e read_data/write_data...
656fa9e4066Sahrens  * to each acl entry.
657fa9e4066Sahrens  *
658fa9e4066Sahrens  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate
659fa9e4066Sahrens  *
660fa9e4066Sahrens  */
661fa9e4066Sahrens 
662fa9e4066Sahrens #define	ACE_ENTRYTYPLEN		6
663fa9e4066Sahrens #define	IFLAGS_SIZE		51
664fa9e4066Sahrens #define	ACCESS_TYPE_SIZE	5
665fa9e4066Sahrens #define	COLON_CNT		3
666fa9e4066Sahrens #define	PERMS_LEN		216
667fa9e4066Sahrens #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + LOGNAME_MAX + PERMS_LEN +\
668fa9e4066Sahrens     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT)
669fa9e4066Sahrens 
670fa9e4066Sahrens static char *
671fa9e4066Sahrens ace_acltotext(acl_t *aceaclp)
672fa9e4066Sahrens {
673fa9e4066Sahrens 	ace_t		*aclp = aceaclp->acl_aclp;
674fa9e4066Sahrens 	int		aclcnt = aceaclp->acl_cnt;
675fa9e4066Sahrens 	char		*aclexport;
676fa9e4066Sahrens 	char		*where;
677fa9e4066Sahrens 	char		*start;
678fa9e4066Sahrens 	struct group	*groupp;
679fa9e4066Sahrens 	struct passwd	*passwdp;
680fa9e4066Sahrens 	struct dynaclstr *dstr;
681fa9e4066Sahrens 	int		i, rtn;
682fa9e4066Sahrens 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
683fa9e4066Sahrens 	size_t		excess = 0;
684fa9e4066Sahrens 
685fa9e4066Sahrens 	if (aclp == NULL)
686fa9e4066Sahrens 		return (NULL);
687fa9e4066Sahrens 	if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL)
688fa9e4066Sahrens 		return (NULL);
689fa9e4066Sahrens 	dstr->bufsize = aclcnt * ACE_ENTRY_SIZE;
690fa9e4066Sahrens 	if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL)
691fa9e4066Sahrens 		return (NULL);
692fa9e4066Sahrens 	*dstr->aclexport = '\0';
693fa9e4066Sahrens 	where = dstr->aclexport;
694fa9e4066Sahrens 
695fa9e4066Sahrens 	for (i = 0; i < aclcnt; i++, aclp++) {
696fa9e4066Sahrens 		switch (aclp->a_flags & 0xf040) {
697fa9e4066Sahrens 		case ACE_OWNER:
698fa9e4066Sahrens 		case 0:
699fa9e4066Sahrens 			if ((aclp->a_flags & 0xf040) == ACE_OWNER)
700fa9e4066Sahrens 				where = strappend(where, "owner@");
701fa9e4066Sahrens 			else
702fa9e4066Sahrens 				where = strappend(where, "user:");
703fa9e4066Sahrens 			if ((aclp->a_flags & 0xf040) == 0) {
704fa9e4066Sahrens 				passwdp = getpwuid(aclp->a_who);
705fa9e4066Sahrens 				if (passwdp == (struct passwd *)NULL) {
706fa9e4066Sahrens 					/* put in uid instead */
707fa9e4066Sahrens 					(void) sprintf(where, "%d",
708fa9e4066Sahrens 					    aclp->a_who);
709fa9e4066Sahrens 				} else {
710fa9e4066Sahrens 					excess = strlen(passwdp->pw_name) -
711fa9e4066Sahrens 					    LOGNAME_MAX;
712fa9e4066Sahrens 					if (excess > 0) {
713fa9e4066Sahrens 						rtn = increase_length(dstr,
714fa9e4066Sahrens 						    excess);
715fa9e4066Sahrens 						if (rtn == 1)
716fa9e4066Sahrens 							/* reset where */
717fa9e4066Sahrens 							where =
718fa9e4066Sahrens 							    dstr->aclexport +
719fa9e4066Sahrens 							    strlen(
720fa9e4066Sahrens 							    dstr->aclexport);
721fa9e4066Sahrens 						else
722fa9e4066Sahrens 							return (NULL);
723fa9e4066Sahrens 					}
724fa9e4066Sahrens 					where = strappend(where,
725fa9e4066Sahrens 					    passwdp->pw_name);
726fa9e4066Sahrens 				}
727fa9e4066Sahrens 			} else {
728fa9e4066Sahrens 				where = strappend(where, "");
729fa9e4066Sahrens 			}
730fa9e4066Sahrens 			where = strappend(where, ":");
731fa9e4066Sahrens 			break;
732fa9e4066Sahrens 		case ACE_GROUP|ACE_IDENTIFIER_GROUP:
733fa9e4066Sahrens 		case ACE_IDENTIFIER_GROUP:
734fa9e4066Sahrens 			if ((aclp->a_flags & 0xf040) ==
735fa9e4066Sahrens 			    (ACE_GROUP | ACE_IDENTIFIER_GROUP))
736fa9e4066Sahrens 				where = strappend(where, "group@");
737fa9e4066Sahrens 			else
738fa9e4066Sahrens 				where = strappend(where, "group:");
739fa9e4066Sahrens 			if (!(aclp->a_flags & ACE_GROUP)) {
740fa9e4066Sahrens 				groupp = getgrgid(aclp->a_who);
741fa9e4066Sahrens 				if (groupp == (struct group *)NULL) {
742fa9e4066Sahrens 					/* put in gid instead */
743fa9e4066Sahrens 					(void) sprintf(where,
744fa9e4066Sahrens 					    "%d", aclp->a_who);
745fa9e4066Sahrens 				} else {
746fa9e4066Sahrens 					excess = strlen(groupp->gr_name) -
747fa9e4066Sahrens 					    LOGNAME_MAX;
748fa9e4066Sahrens 					if (excess > 0) {
749fa9e4066Sahrens 						rtn = increase_length(dstr,
750fa9e4066Sahrens 						    excess);
751fa9e4066Sahrens 						if (rtn == 1)
752fa9e4066Sahrens 							/* reset where */
753fa9e4066Sahrens 							where =
754fa9e4066Sahrens 							    dstr->aclexport +
755fa9e4066Sahrens 							    strlen(
756fa9e4066Sahrens 							    dstr->aclexport);
757fa9e4066Sahrens 						else
758fa9e4066Sahrens 							return (NULL);
759fa9e4066Sahrens 					}
760fa9e4066Sahrens 					where = strappend(where,
761fa9e4066Sahrens 					    groupp->gr_name);
762fa9e4066Sahrens 				}
763fa9e4066Sahrens 			} else {
764fa9e4066Sahrens 					where = strappend(where, "");
765fa9e4066Sahrens 			}
766fa9e4066Sahrens 			where = strappend(where, ":");
767fa9e4066Sahrens 			break;
768fa9e4066Sahrens 		case ACE_EVERYONE:
769fa9e4066Sahrens 			where = strappend(where, "everyone@:");
770fa9e4066Sahrens 			break;
771fa9e4066Sahrens 		default:
772fa9e4066Sahrens 			free(dstr->aclexport);
773fa9e4066Sahrens 			free(dstr);
774fa9e4066Sahrens 			return (NULL);
775fa9e4066Sahrens 
776fa9e4066Sahrens 		}
777fa9e4066Sahrens 		where = ace_convert_perm(where, aclp->a_access_mask,
778fa9e4066Sahrens 		    isdir, (aclp->a_flags &
779fa9e4066Sahrens 		    (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE)));
780fa9e4066Sahrens 		where = strappend(where,
781fa9e4066Sahrens 		    (aclp->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) ?
782fa9e4066Sahrens 		    ":allow" : ":deny");
783fa9e4066Sahrens 
784fa9e4066Sahrens 		/*
785fa9e4066Sahrens 		 * slap on inheritance flags if we have any
786fa9e4066Sahrens 		 */
787fa9e4066Sahrens 
788fa9e4066Sahrens 		if (aclp->a_flags & 0xf) {
789fa9e4066Sahrens 			where = strappend(where, ":");
790fa9e4066Sahrens 			start = where;
791fa9e4066Sahrens 			if (aclp->a_flags & ACE_FILE_INHERIT_ACE)
792fa9e4066Sahrens 				where = strappend(where, "file_inherit/");
793fa9e4066Sahrens 			if (aclp->a_flags & ACE_DIRECTORY_INHERIT_ACE)
794fa9e4066Sahrens 				where = strappend(where, "dir_inherit/");
795fa9e4066Sahrens 			if (aclp->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE)
796fa9e4066Sahrens 				where = strappend(where, "no_propagate/");
797fa9e4066Sahrens 			if (aclp->a_flags & ACE_INHERIT_ONLY_ACE)
798fa9e4066Sahrens 				where = strappend(where, "inherit_only");
799fa9e4066Sahrens 
800fa9e4066Sahrens 			/*
801fa9e4066Sahrens 			 * chop off trailing slash, if present
802fa9e4066Sahrens 			 */
803fa9e4066Sahrens 			if (start[strlen(start) - 1] == '/') {
804fa9e4066Sahrens 				start[strlen(start) - 1] = '\0';
805fa9e4066Sahrens 				where = start + strlen(start);
806fa9e4066Sahrens 			}
807fa9e4066Sahrens 		}
808fa9e4066Sahrens 		if (i < aclcnt - 1)
809fa9e4066Sahrens 			where = strappend(where, ",");
810fa9e4066Sahrens 	}
811fa9e4066Sahrens 	aclexport = dstr->aclexport;
812fa9e4066Sahrens 	free(dstr);
813fa9e4066Sahrens 	return (aclexport);
814fa9e4066Sahrens }
815fa9e4066Sahrens 
816fa9e4066Sahrens static int
817fa9e4066Sahrens build_iflags(char *str, int *iflags)
818fa9e4066Sahrens {
819fa9e4066Sahrens 
820fa9e4066Sahrens 	char *tok;
821fa9e4066Sahrens 	*iflags = 0;
822fa9e4066Sahrens 
823fa9e4066Sahrens 	tok = strtok(str, "/");
824fa9e4066Sahrens 
825fa9e4066Sahrens 	if (tok == NULL)
826fa9e4066Sahrens 		return (1);
827fa9e4066Sahrens 
828fa9e4066Sahrens 	do {
829fa9e4066Sahrens 		if (strcmp(tok, "file_inherit") == 0)
830fa9e4066Sahrens 			*iflags |= ACE_FILE_INHERIT_ACE;
831fa9e4066Sahrens 		else if (strcmp(tok, "dir_inherit") == 0)
832fa9e4066Sahrens 			*iflags |= ACE_DIRECTORY_INHERIT_ACE;
833fa9e4066Sahrens 		else if (strcmp(tok, "inherit_only") == 0)
834fa9e4066Sahrens 			*iflags |= ACE_INHERIT_ONLY_ACE;
835fa9e4066Sahrens 		else if (strcmp(tok, "no_propagate") == 0)
836fa9e4066Sahrens 			*iflags |= ACE_NO_PROPAGATE_INHERIT_ACE;
837fa9e4066Sahrens 		else
838fa9e4066Sahrens 			return (1);
839fa9e4066Sahrens 	} while (tok = strtok(NULL, "/"));
840fa9e4066Sahrens 	return (0);
841fa9e4066Sahrens }
842fa9e4066Sahrens 
843fa9e4066Sahrens /*
844fa9e4066Sahrens  * Convert external acl representation to internal representation.
845fa9e4066Sahrens  * The accepted syntax is: <acl_entry>[,<acl_entry>]*[,]
846fa9e4066Sahrens  * The comma at the end is not prescribed by the man pages.
847fa9e4066Sahrens  * But it is needed not to break the old programs.
848fa9e4066Sahrens  */
849fa9e4066Sahrens 
850fa9e4066Sahrens int
851fa9e4066Sahrens ace_aclfromtext(char *aclstr, acl_t **ret_aclp)
852fa9e4066Sahrens {
853fa9e4066Sahrens 	char		*fieldp;
854fa9e4066Sahrens 	char		*tp;
855fa9e4066Sahrens 	char		*nextp;
856fa9e4066Sahrens 	char		*allocp;
857fa9e4066Sahrens 	char		*aclimport;
858fa9e4066Sahrens 	char 		*str;
859fa9e4066Sahrens 	char		*perm_tok;
860fa9e4066Sahrens 	int		entry_type;
861fa9e4066Sahrens 	int		id;
862fa9e4066Sahrens 	int		type;
863fa9e4066Sahrens 	int		iflags;
864fa9e4066Sahrens 	int		len;
865fa9e4066Sahrens 	int		error;
866fa9e4066Sahrens 	int32_t		perm;
867fa9e4066Sahrens 	ace_t		*tmpaclp;
868fa9e4066Sahrens 	acl_t		*aclp;
869fa9e4066Sahrens 	struct group	*groupp;
870fa9e4066Sahrens 	struct passwd	*passwdp;
871fa9e4066Sahrens 
872fa9e4066Sahrens 	if (! aclstr)
873fa9e4066Sahrens 		return (EACL_INVALID_STR);
874fa9e4066Sahrens 
875fa9e4066Sahrens 	len = strlen(aclstr);
876fa9e4066Sahrens 
877fa9e4066Sahrens 	aclp = acl_alloc(ACE_T);
878fa9e4066Sahrens 	if (aclp == NULL) {
879fa9e4066Sahrens 		return (EACL_MEM_ERROR);
880fa9e4066Sahrens 	}
881fa9e4066Sahrens 
882fa9e4066Sahrens 	*ret_aclp = NULL;
883fa9e4066Sahrens 
884fa9e4066Sahrens 	if ((aclimport = allocp = strdup(aclstr)) == NULL) {
885fa9e4066Sahrens 		return (EACL_MEM_ERROR);
886fa9e4066Sahrens 	}
887fa9e4066Sahrens 
888fa9e4066Sahrens 
889fa9e4066Sahrens 	if (aclimport[len - 1] == ',')
890fa9e4066Sahrens 		aclimport[len - 1] = '\0';
891fa9e4066Sahrens 
892fa9e4066Sahrens 	for (; aclimport; ) {
893fa9e4066Sahrens 		/* look for an ACL entry */
894fa9e4066Sahrens 		tp = strchr(aclimport, ',');
895fa9e4066Sahrens 		if (tp == NULL) {
896fa9e4066Sahrens 			nextp = NULL;
897fa9e4066Sahrens 		} else {
898fa9e4066Sahrens 			*tp = '\0';
899fa9e4066Sahrens 			nextp = tp + 1;
900fa9e4066Sahrens 		}
901fa9e4066Sahrens 
902fa9e4066Sahrens 		aclp->acl_cnt += 1;
903fa9e4066Sahrens 
904fa9e4066Sahrens 		/*
905fa9e4066Sahrens 		 * get additional memory:
906fa9e4066Sahrens 		 * can be more efficient by allocating a bigger block
907fa9e4066Sahrens 		 * each time.
908fa9e4066Sahrens 		 */
909fa9e4066Sahrens 		if (aclp->acl_cnt > 1)
910fa9e4066Sahrens 			tmpaclp = (ace_t *)realloc(aclp->acl_aclp,
911fa9e4066Sahrens 			    sizeof (ace_t) * (aclp->acl_cnt));
912fa9e4066Sahrens 		else
913fa9e4066Sahrens 			tmpaclp = (ace_t *)malloc(sizeof (ace_t));
914fa9e4066Sahrens 		if (tmpaclp == NULL) {
915fa9e4066Sahrens 			free(allocp);
916fa9e4066Sahrens 			acl_free(aclp);
917fa9e4066Sahrens 			return (EACL_MEM_ERROR);
918fa9e4066Sahrens 		}
919fa9e4066Sahrens 		aclp->acl_aclp = tmpaclp;
920fa9e4066Sahrens 		tmpaclp = (ace_t *)aclp->acl_aclp + (aclp->acl_cnt - 1);
921fa9e4066Sahrens 
922fa9e4066Sahrens 		/* look for entry type field */
923fa9e4066Sahrens 		tp = strchr(aclimport, ':');
924fa9e4066Sahrens 		if (tp == NULL) {
925fa9e4066Sahrens 			free(allocp);
926fa9e4066Sahrens 			acl_free(aclp);
927fa9e4066Sahrens 			return (EACL_ENTRY_ERROR);
928fa9e4066Sahrens 		} else
929fa9e4066Sahrens 			*tp = '\0';
930fa9e4066Sahrens 		if (strcmp(aclimport, "owner@") == 0) {
931fa9e4066Sahrens 			entry_type = ACE_OWNER;
932fa9e4066Sahrens 		} else if (strcmp(aclimport, "group@") == 0) {
933fa9e4066Sahrens 			entry_type = ACE_GROUP | ACE_IDENTIFIER_GROUP;
934fa9e4066Sahrens 		} else if (strcmp(aclimport, "everyone@") == 0) {
935fa9e4066Sahrens 			entry_type = ACE_EVERYONE;
936fa9e4066Sahrens 		} else if (strcmp(aclimport, "group") == 0) {
937fa9e4066Sahrens 			entry_type = ACE_IDENTIFIER_GROUP;
938fa9e4066Sahrens 		} else if (strcmp(aclimport, "user") == 0) {
939fa9e4066Sahrens 			entry_type = 0;
940fa9e4066Sahrens 		} else {
941fa9e4066Sahrens 			free(allocp);
942fa9e4066Sahrens 			acl_free(aclp);
943fa9e4066Sahrens 			return (EACL_ENTRY_ERROR);
944fa9e4066Sahrens 		}
945fa9e4066Sahrens 
946fa9e4066Sahrens 		/*
947fa9e4066Sahrens 		 * If not an abstraction owner@, group@ or everyone@
948fa9e4066Sahrens 		 * then we must have a user/group name next
949fa9e4066Sahrens 		 */
950fa9e4066Sahrens 
951fa9e4066Sahrens 		if (entry_type == 0 || entry_type == ACE_IDENTIFIER_GROUP) {
952fa9e4066Sahrens 			fieldp = tp + 1;
953fa9e4066Sahrens 			tp = strchr(fieldp, ':');
954fa9e4066Sahrens 			if (tp == NULL) {
955fa9e4066Sahrens 				free(allocp);
956fa9e4066Sahrens 				acl_free(aclp);
957fa9e4066Sahrens 				return (EACL_INVALID_USER_GROUP);
958fa9e4066Sahrens 			} else
959fa9e4066Sahrens 				*tp = '\0';
960fa9e4066Sahrens 			if (fieldp != tp) {
961fa9e4066Sahrens 				/*
962fa9e4066Sahrens 				 * The second field could be empty. We only care
963fa9e4066Sahrens 				 * when the field has user/group name.
964fa9e4066Sahrens 				 */
965fa9e4066Sahrens 				if (entry_type == 0) {
966fa9e4066Sahrens 					/*
967fa9e4066Sahrens 					 * The reentrant interface getpwnam_r()
968fa9e4066Sahrens 					 * is uncommitted and subject to
969fa9e4066Sahrens 					 * change. Use the friendlier interface
970fa9e4066Sahrens 					 * getpwnam().
971fa9e4066Sahrens 					 */
972fa9e4066Sahrens 					error = 0;
973fa9e4066Sahrens 					passwdp = getpwnam(fieldp);
974fa9e4066Sahrens 					if (passwdp == NULL) {
975fa9e4066Sahrens 						error = acl_str_to_id(
976fa9e4066Sahrens 						    fieldp, &id);
977fa9e4066Sahrens 					} else {
978fa9e4066Sahrens 						id = passwdp->pw_uid;
979fa9e4066Sahrens 					}
980fa9e4066Sahrens 
981fa9e4066Sahrens 					if (error) {
982fa9e4066Sahrens 						free(allocp);
983fa9e4066Sahrens 						acl_free(aclp);
984fa9e4066Sahrens 						return (error);
985fa9e4066Sahrens 					}
986fa9e4066Sahrens 				} else {
987fa9e4066Sahrens 					error = 0;
988fa9e4066Sahrens 					if (entry_type ==
989fa9e4066Sahrens 					    ACE_IDENTIFIER_GROUP) {
990fa9e4066Sahrens 						groupp = getgrnam(fieldp);
991fa9e4066Sahrens 						if (groupp == NULL) {
992fa9e4066Sahrens 							/* no group? */
993fa9e4066Sahrens 							error = acl_str_to_id(
994fa9e4066Sahrens 							    fieldp, &id);
995fa9e4066Sahrens 						} else
996fa9e4066Sahrens 							id = groupp->gr_gid;
997fa9e4066Sahrens 
998fa9e4066Sahrens 					} else if ((entry_type == ACE_OWNER) ||
999fa9e4066Sahrens 					    (entry_type ==
1000fa9e4066Sahrens 					    (ACE_IDENTIFIER_GROUP|ACE_GROUP)) ||
1001fa9e4066Sahrens 					    (entry_type != ACE_EVERYONE)) {
1002fa9e4066Sahrens 						error = EACL_FIELD_NOT_BLANK;
1003fa9e4066Sahrens 					} else {
1004fa9e4066Sahrens 						error = EACL_ENTRY_ERROR;
1005fa9e4066Sahrens 					}
1006fa9e4066Sahrens 
1007fa9e4066Sahrens 					if (error) {
1008fa9e4066Sahrens 						free(allocp);
1009fa9e4066Sahrens 						acl_free(aclp);
1010fa9e4066Sahrens 						return (error);
1011fa9e4066Sahrens 					}
1012fa9e4066Sahrens 				}
1013fa9e4066Sahrens 			}
1014fa9e4066Sahrens 		} else {
1015fa9e4066Sahrens 			id = -1;
1016fa9e4066Sahrens 		}
1017fa9e4066Sahrens 
1018fa9e4066Sahrens 		/* next field: permission */
1019fa9e4066Sahrens 		fieldp = tp + 1;
1020fa9e4066Sahrens 		tp = strchr(fieldp, ':');
1021fa9e4066Sahrens 		if (tp == NULL) {
1022fa9e4066Sahrens 			free(allocp);
1023fa9e4066Sahrens 			acl_free(aclp);
1024fa9e4066Sahrens 			return (EACL_PERM_MASK_ERROR);
1025fa9e4066Sahrens 		} else
1026fa9e4066Sahrens 			*tp = '\0';
1027fa9e4066Sahrens 
1028fa9e4066Sahrens 		perm = 0;
1029fa9e4066Sahrens 
1030fa9e4066Sahrens 		perm_tok = strtok(fieldp, "/");
1031fa9e4066Sahrens 		if (perm_tok == NULL) {
1032fa9e4066Sahrens 			perm = 0;
1033fa9e4066Sahrens 		} else {
1034fa9e4066Sahrens 			do {
1035fa9e4066Sahrens 				if (ace_permask(perm_tok, &perm) != 0) {
1036fa9e4066Sahrens 					free(allocp);
1037fa9e4066Sahrens 					acl_free(aclp);
1038fa9e4066Sahrens 					return (EACL_PERM_MASK_ERROR);
1039fa9e4066Sahrens 				}
1040fa9e4066Sahrens 			} while (perm_tok = strtok(NULL, "/"));
1041fa9e4066Sahrens 		}
1042fa9e4066Sahrens 
1043fa9e4066Sahrens 		/* grab allow/deny */
1044fa9e4066Sahrens 		fieldp = tp + 1;
1045fa9e4066Sahrens 		tp = strchr(fieldp, ':');
1046fa9e4066Sahrens 		if (tp != NULL)
1047fa9e4066Sahrens 			*tp = '\0';
1048fa9e4066Sahrens 
1049fa9e4066Sahrens 		if (strcmp(fieldp, "allow") == 0)
1050fa9e4066Sahrens 			type = ACE_ACCESS_ALLOWED_ACE_TYPE;
1051fa9e4066Sahrens 		else if (strcmp(fieldp, "deny") == 0)
1052fa9e4066Sahrens 			type = ACE_ACCESS_DENIED_ACE_TYPE;
1053fa9e4066Sahrens 		else {
1054fa9e4066Sahrens 			free(allocp);
1055fa9e4066Sahrens 			acl_free(aclp);
1056fa9e4066Sahrens 			return (EACL_INVALID_ACCESS_TYPE);
1057fa9e4066Sahrens 		}
1058fa9e4066Sahrens 
1059fa9e4066Sahrens 		/* grab option inherit flags */
1060fa9e4066Sahrens 
1061fa9e4066Sahrens 		iflags = 0;
1062fa9e4066Sahrens 		if (tp != NULL) {
1063fa9e4066Sahrens 			fieldp = tp + 1;
1064fa9e4066Sahrens 			if (fieldp != NULL) {
1065fa9e4066Sahrens 				*tp = '\0';
1066fa9e4066Sahrens 				str = fieldp;
1067fa9e4066Sahrens 				if (build_iflags(str, &iflags) != 0) {
1068fa9e4066Sahrens 					free(allocp);
1069fa9e4066Sahrens 					acl_free(aclp);
1070fa9e4066Sahrens 					return (EACL_INHERIT_ERROR);
1071fa9e4066Sahrens 				}
1072fa9e4066Sahrens 			} else {
1073fa9e4066Sahrens 				free(allocp);
1074fa9e4066Sahrens 				acl_free(aclp);
1075fa9e4066Sahrens 				return (EACL_UNKNOWN_DATA);
1076fa9e4066Sahrens 			}
1077fa9e4066Sahrens 		}
1078fa9e4066Sahrens 		/* slap fields into ace_t structure */
1079fa9e4066Sahrens 
1080fa9e4066Sahrens 		tmpaclp->a_flags = entry_type;
1081fa9e4066Sahrens 		tmpaclp->a_flags |= iflags;
1082fa9e4066Sahrens 		tmpaclp->a_who = id;
1083fa9e4066Sahrens 		tmpaclp->a_access_mask = perm;
1084fa9e4066Sahrens 		tmpaclp->a_type = type;
1085fa9e4066Sahrens 		aclimport = nextp;
1086fa9e4066Sahrens 	}
1087fa9e4066Sahrens 	free(allocp);
1088fa9e4066Sahrens 	*ret_aclp = aclp;
1089fa9e4066Sahrens 	return (0);
1090fa9e4066Sahrens }
1091fa9e4066Sahrens 
1092fa9e4066Sahrens char
1093fa9e4066Sahrens *acl_totext(acl_t *aclp)
1094fa9e4066Sahrens {
1095fa9e4066Sahrens 	if (aclp == NULL)
1096fa9e4066Sahrens 		return (NULL);
1097fa9e4066Sahrens 
1098fa9e4066Sahrens 	switch (aclp->acl_type) {
1099fa9e4066Sahrens 	case ACE_T:
1100fa9e4066Sahrens 		return (ace_acltotext(aclp));
1101fa9e4066Sahrens 	case ACLENT_T:
1102fa9e4066Sahrens 		return (acltotext(aclp->acl_aclp, aclp->acl_cnt));
1103fa9e4066Sahrens 	}
1104fa9e4066Sahrens 	return (NULL);
1105fa9e4066Sahrens }
1106fa9e4066Sahrens 
1107fa9e4066Sahrens int
1108fa9e4066Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp)
1109fa9e4066Sahrens {
1110fa9e4066Sahrens 	acl_t *aclp;
1111fa9e4066Sahrens 	char *token;
1112fa9e4066Sahrens 	char *ptr;
1113fa9e4066Sahrens 	char *textp;
1114fa9e4066Sahrens 	enum acl_type flavor;
1115fa9e4066Sahrens 	int colon_cnt = 0;
1116fa9e4066Sahrens 	int error;
1117fa9e4066Sahrens 
1118fa9e4066Sahrens 	/*
1119fa9e4066Sahrens 	 * first try and detect what type of acl entries we have
1120fa9e4066Sahrens 	 *
1121fa9e4066Sahrens 	 * aclent_t can have 1, 2 or 3 colons
1122fa9e4066Sahrens 	 * if 3 then must have word default:
1123fa9e4066Sahrens 	 *
1124fa9e4066Sahrens 	 * ace_t can have 2, 3 or 4
1125fa9e4066Sahrens 	 * for 2 then must be owner@, group@ or everyone@
1126fa9e4066Sahrens 	 */
1127fa9e4066Sahrens 
1128fa9e4066Sahrens 	textp = strdup(acltextp);
1129fa9e4066Sahrens 	if (textp == NULL)
1130fa9e4066Sahrens 		return (-1);
1131fa9e4066Sahrens 
1132fa9e4066Sahrens 	token = strtok(textp, ",");
1133fa9e4066Sahrens 	if (token == NULL) {
1134fa9e4066Sahrens 		free(textp);
1135fa9e4066Sahrens 		return (-1);
1136fa9e4066Sahrens 	}
1137fa9e4066Sahrens 
1138fa9e4066Sahrens 	for (ptr = token; *ptr; ptr++) {
1139fa9e4066Sahrens 		if (*ptr == ':')
1140fa9e4066Sahrens 			colon_cnt++;
1141fa9e4066Sahrens 	}
1142fa9e4066Sahrens 
1143fa9e4066Sahrens 	if (colon_cnt == 1 || colon_cnt == 2) {
1144fa9e4066Sahrens 		if ((strncmp(acltextp, "owner@", 6) == 0) ||
1145fa9e4066Sahrens 		    (strncmp(acltextp, "group@", 6) == 0) ||
1146fa9e4066Sahrens 		    (strncmp(acltextp, "everyone@", 9) == 0))
1147fa9e4066Sahrens 			flavor = ACE_T;
1148fa9e4066Sahrens 		else
1149fa9e4066Sahrens 			flavor = ACLENT_T;
1150fa9e4066Sahrens 	} else if (colon_cnt == 3) {
1151fa9e4066Sahrens 		ptr = strtok(token, ":");
1152fa9e4066Sahrens 		if (ptr == NULL) {
1153fa9e4066Sahrens 			free(textp);
1154fa9e4066Sahrens 			return (EACL_MISSING_FIELDS);
1155fa9e4066Sahrens 		} else if (strcmp(ptr, "default") == 0) {
1156fa9e4066Sahrens 			flavor = ACLENT_T;
1157fa9e4066Sahrens 		} else {
1158fa9e4066Sahrens 			flavor = ACE_T;
1159fa9e4066Sahrens 		}
1160fa9e4066Sahrens 	} else if (colon_cnt == 4) {
1161fa9e4066Sahrens 		flavor = ACE_T;
1162fa9e4066Sahrens 	} else {
1163fa9e4066Sahrens 		free(textp);
1164fa9e4066Sahrens 		return (EACL_MISSING_FIELDS);
1165fa9e4066Sahrens 	}
1166fa9e4066Sahrens 
1167fa9e4066Sahrens 
1168fa9e4066Sahrens 	free(textp);
1169fa9e4066Sahrens 
1170fa9e4066Sahrens 	if (flavor == ACLENT_T)
1171fa9e4066Sahrens 		error = aclent_aclfromtext((char *)acltextp, &aclp);
1172fa9e4066Sahrens 	else
1173fa9e4066Sahrens 		error = ace_aclfromtext((char *)acltextp, &aclp);
1174fa9e4066Sahrens 
1175fa9e4066Sahrens 	*ret_aclp = aclp;
1176fa9e4066Sahrens 	return (error);
1177fa9e4066Sahrens }
1178