Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*LINTLIBRARY*/
     27 
     28 #include <grp.h>
     29 #include <pwd.h>
     30 #include <string.h>
     31 #include <limits.h>
     32 #include <stdlib.h>
     33 #include <errno.h>
     34 #include <sys/param.h>
     35 #include <sys/types.h>
     36 #include <sys/stat.h>
     37 #include <sys/acl.h>
     38 #include <aclutils.h>
     39 #include <idmap.h>
     40 
     41 #define	ID_STR_MAX	20	/* digits in LONG_MAX */
     42 
     43 #define	APPENDED_ID_MAX	ID_STR_MAX + 1		/* id + colon */
     44 /*
     45  * yyinteractive controls whether yyparse should print out
     46  * error messages to stderr, and whether or not id's should be
     47  * allowed from acl_fromtext().
     48  */
     49 int	yyinteractive;
     50 acl_t	*yyacl;
     51 char	*yybuf;
     52 
     53 extern acl_t *acl_alloc(enum acl_type);
     54 
     55 /*
     56  * dynamic string that will increase in size on an
     57  * as needed basis.
     58  */
     59 typedef struct dynaclstr {
     60 	size_t d_bufsize;		/* current size of aclexport */
     61 	char *d_aclexport;
     62 	int d_pos;
     63 } dynaclstr_t;
     64 
     65 static int str_append(dynaclstr_t *, char *);
     66 static int aclent_perm_txt(dynaclstr_t *, o_mode_t);
     67 
     68 static void
     69 aclent_perms(int perm, char *txt_perms)
     70 {
     71 	if (perm & S_IROTH)
     72 		txt_perms[0] = 'r';
     73 	else
     74 		txt_perms[0] = '-';
     75 	if (perm & S_IWOTH)
     76 		txt_perms[1] = 'w';
     77 	else
     78 		txt_perms[1] = '-';
     79 	if (perm & S_IXOTH)
     80 		txt_perms[2] = 'x';
     81 	else
     82 		txt_perms[2] = '-';
     83 	txt_perms[3] = '\0';
     84 }
     85 
     86 static char *
     87 pruname(uid_t uid, char *uidp, size_t buflen, int noresolve)
     88 {
     89 	struct passwd	*passwdp = NULL;
     90 
     91 	if (noresolve == 0)
     92 		passwdp = getpwuid(uid);
     93 	if (passwdp == (struct passwd *)NULL) {
     94 		/* could not get passwd information: display uid instead */
     95 		(void) snprintf(uidp, buflen, "%u", uid);
     96 	} else {
     97 		(void) strlcpy(uidp, passwdp->pw_name, buflen);
     98 	}
     99 	return (uidp);
    100 }
    101 
    102 static char *
    103 prgname(gid_t gid, char *gidp, size_t buflen, int noresolve)
    104 {
    105 	struct group	*groupp = NULL;
    106 
    107 	if (noresolve == 0)
    108 		groupp = getgrgid(gid);
    109 	if (groupp == (struct group *)NULL) {
    110 		/* could not get group information: display gid instead */
    111 		(void) snprintf(gidp, buflen, "%u", gid);
    112 	} else {
    113 		(void) strlcpy(gidp, groupp->gr_name, buflen);
    114 	}
    115 	return (gidp);
    116 }
    117 
    118 static int
    119 getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve)
    120 {
    121 	idmap_handle_t *idmap_hdl = NULL;
    122 	idmap_get_handle_t *get_hdl = NULL;
    123 	idmap_stat status;
    124 	idmap_rid_t rid;
    125 	int error = IDMAP_ERR_NORESULT;
    126 	int len;
    127 	char *domain = NULL;
    128 	char *name = NULL;
    129 
    130 	*sidp = NULL;
    131 
    132 	/*
    133 	 * First try and get windows name
    134 	 */
    135 
    136 	if (!noresolve) {
    137 		if (user)
    138 			error = idmap_getwinnamebyuid(who,
    139 			    IDMAP_REQ_FLG_USE_CACHE, &name, &domain);
    140 		else
    141 			error = idmap_getwinnamebygid(who,
    142 			    IDMAP_REQ_FLG_USE_CACHE, &name, &domain);
    143 	}
    144 	if (error != IDMAP_SUCCESS) {
    145 		if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS &&
    146 		    idmap_get_create(idmap_hdl, &get_hdl) == IDMAP_SUCCESS) {
    147 			if (user)
    148 				error = idmap_get_sidbyuid(get_hdl, who,
    149 				    IDMAP_REQ_FLG_USE_CACHE, &domain, &rid,
    150 				    &status);
    151 			else
    152 				error = idmap_get_sidbygid(get_hdl, who,
    153 				    IDMAP_REQ_FLG_USE_CACHE, &domain, &rid,
    154 				    &status);
    155 			if (error == IDMAP_SUCCESS &&
    156 			    idmap_get_mappings(get_hdl) == 0) {
    157 				if (status == IDMAP_SUCCESS) {
    158 					len = snprintf(NULL, 0,
    159 					    "%s-%d", domain, rid);
    160 					if (*sidp = malloc(len + 1)) {
    161 						(void) snprintf(*sidp, len + 1,
    162 						    "%s-%d", domain, rid);
    163 					}
    164 				}
    165 			}
    166 		}
    167 		if (get_hdl)
    168 			idmap_get_destroy(get_hdl);
    169 		if (idmap_hdl)
    170 			(void) idmap_fini(idmap_hdl);
    171 	} else {
    172 		int len;
    173 
    174 		len = snprintf(NULL, 0, "%s@%s", name, domain);
    175 		if (*sidp = malloc(len + 1))
    176 			(void) snprintf(*sidp, len + 1, "%s@%s", name, domain);
    177 	}
    178 
    179 	if (name)
    180 		free(name);
    181 	if (domain)
    182 		free(domain);
    183 	return (*sidp ? 0 : 1);
    184 }
    185 
    186 static void
    187 aclent_printacl(acl_t *aclp)
    188 {
    189 	aclent_t *tp;
    190 	int aclcnt;
    191 	int mask;
    192 	int slot = 0;
    193 	char perm[4];
    194 	char uidp[ID_STR_MAX];
    195 	char gidp[ID_STR_MAX];
    196 
    197 	/* display ACL: assume it is sorted. */
    198 	aclcnt = aclp->acl_cnt;
    199 	for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) {
    200 		if (tp->a_type == CLASS_OBJ)
    201 			mask = tp->a_perm;
    202 	}
    203 	aclcnt = aclp->acl_cnt;
    204 	for (tp = aclp->acl_aclp; aclcnt--; tp++) {
    205 		(void) printf("     %d:", slot++);
    206 		switch (tp->a_type) {
    207 		case USER:
    208 			aclent_perms(tp->a_perm, perm);
    209 			(void) printf("user:%s:%s\t\t",
    210 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
    211 			aclent_perms((tp->a_perm & mask), perm);
    212 			(void) printf("#effective:%s\n", perm);
    213 			break;
    214 		case USER_OBJ:
    215 			/* no need to display uid */
    216 			aclent_perms(tp->a_perm, perm);
    217 			(void) printf("user::%s\n", perm);
    218 			break;
    219 		case GROUP:
    220 			aclent_perms(tp->a_perm, perm);
    221 			(void) printf("group:%s:%s\t\t",
    222 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
    223 			aclent_perms(tp->a_perm & mask, perm);
    224 			(void) printf("#effective:%s\n", perm);
    225 			break;
    226 		case GROUP_OBJ:
    227 			aclent_perms(tp->a_perm, perm);
    228 			(void) printf("group::%s\t\t", perm);
    229 			aclent_perms(tp->a_perm & mask, perm);
    230 			(void) printf("#effective:%s\n", perm);
    231 			break;
    232 		case CLASS_OBJ:
    233 			aclent_perms(tp->a_perm, perm);
    234 			(void) printf("mask:%s\n", perm);
    235 			break;
    236 		case OTHER_OBJ:
    237 			aclent_perms(tp->a_perm, perm);
    238 			(void) printf("other:%s\n", perm);
    239 			break;
    240 		case DEF_USER:
    241 			aclent_perms(tp->a_perm, perm);
    242 			(void) printf("default:user:%s:%s\n",
    243 			    pruname(tp->a_id, uidp, sizeof (uidp), 0), perm);
    244 			break;
    245 		case DEF_USER_OBJ:
    246 			aclent_perms(tp->a_perm, perm);
    247 			(void) printf("default:user::%s\n", perm);
    248 			break;
    249 		case DEF_GROUP:
    250 			aclent_perms(tp->a_perm, perm);
    251 			(void) printf("default:group:%s:%s\n",
    252 			    prgname(tp->a_id, gidp, sizeof (gidp), 0), perm);
    253 			break;
    254 		case DEF_GROUP_OBJ:
    255 			aclent_perms(tp->a_perm, perm);
    256 			(void) printf("default:group::%s\n", perm);
    257 			break;
    258 		case DEF_CLASS_OBJ:
    259 			aclent_perms(tp->a_perm, perm);
    260 			(void) printf("default:mask:%s\n", perm);
    261 			break;
    262 		case DEF_OTHER_OBJ:
    263 			aclent_perms(tp->a_perm, perm);
    264 			(void) printf("default:other:%s\n", perm);
    265 			break;
    266 		default:
    267 			(void) fprintf(stderr,
    268 			    dgettext(TEXT_DOMAIN, "unrecognized entry\n"));
    269 			break;
    270 		}
    271 	}
    272 }
    273 
    274 static void
    275 split_line(char *str, int cols)
    276 {
    277 	char *ptr;
    278 	int len;
    279 	int i;
    280 	int last_split;
    281 	char *pad = "";
    282 	int pad_len;
    283 
    284 	len = strlen(str);
    285 	ptr = str;
    286 	pad_len = 0;
    287 
    288 	ptr = str;
    289 	last_split = 0;
    290 	for (i = 0; i != len; i++) {
    291 		if ((i + pad_len + 4) >= cols) {
    292 			(void) printf("%s%.*s\n", pad, last_split, ptr);
    293 			ptr = &ptr[last_split];
    294 			len = strlen(ptr);
    295 			i = 0;
    296 			pad_len = 4;
    297 			pad = "         ";
    298 		} else {
    299 			if (ptr[i] == '/' || ptr[i] == ':') {
    300 				last_split = i;
    301 			}
    302 		}
    303 	}
    304 	if (i == len) {
    305 		(void) printf("%s%s\n", pad, ptr);
    306 	}
    307 }
    308 
    309 /*
    310  * compute entry type string, such as user:joe, group:staff,...
    311  */
    312 static int
    313 aclent_type_txt(dynaclstr_t *dstr, aclent_t *aclp, int flags)
    314 {
    315 	char idp[ID_STR_MAX];
    316 	int error;
    317 
    318 	switch (aclp->a_type) {
    319 	case DEF_USER_OBJ:
    320 	case USER_OBJ:
    321 		if (aclp->a_type == USER_OBJ)
    322 			error = str_append(dstr, "user::");
    323 		else
    324 			error = str_append(dstr, "defaultuser::");
    325 		break;
    326 
    327 	case DEF_USER:
    328 	case USER:
    329 		if (aclp->a_type == USER)
    330 			error = str_append(dstr, "user:");
    331 		else
    332 			error = str_append(dstr, "defaultuser:");
    333 		if (error)
    334 			break;
    335 		error = str_append(dstr, pruname(aclp->a_id, idp,
    336 		    sizeof (idp), flags & ACL_NORESOLVE));
    337 		if (error == 0)
    338 			error = str_append(dstr, ":");
    339 		break;
    340 
    341 	case DEF_GROUP_OBJ:
    342 	case GROUP_OBJ:
    343 		if (aclp->a_type == GROUP_OBJ)
    344 			error = str_append(dstr, "group::");
    345 		else
    346 			error = str_append(dstr, "defaultgroup::");
    347 		break;
    348 
    349 	case DEF_GROUP:
    350 	case GROUP:
    351 		if (aclp->a_type == GROUP)
    352 			error = str_append(dstr, "group:");
    353 		else
    354 			error = str_append(dstr, "defaultgroup:");
    355 		if (error)
    356 			break;
    357 		error = str_append(dstr, prgname(aclp->a_id, idp,
    358 		    sizeof (idp), flags & ACL_NORESOLVE));
    359 		if (error == 0)
    360 			error = str_append(dstr, ":");
    361 		break;
    362 
    363 	case DEF_CLASS_OBJ:
    364 	case CLASS_OBJ:
    365 		if (aclp->a_type == CLASS_OBJ)
    366 			error = str_append(dstr, "mask:");
    367 		else
    368 			error = str_append(dstr, "defaultmask:");
    369 		break;
    370 
    371 	case DEF_OTHER_OBJ:
    372 	case OTHER_OBJ:
    373 		if (aclp->a_type == OTHER_OBJ)
    374 			error = str_append(dstr, "other:");
    375 		else
    376 			error = str_append(dstr, "defaultother:");
    377 		break;
    378 
    379 	default:
    380 		error = 1;
    381 		break;
    382 	}
    383 
    384 	return (error);
    385 }
    386 
    387 /*
    388  * compute entry type string such as, owner@:, user:joe, group:staff,...
    389  */
    390 static int
    391 ace_type_txt(dynaclstr_t *dynstr, ace_t *acep, int flags)
    392 {
    393 	char idp[ID_STR_MAX];
    394 	int error;
    395 	char *sidp = NULL;
    396 
    397 	switch (acep->a_flags & ACE_TYPE_FLAGS) {
    398 	case ACE_OWNER:
    399 		error = str_append(dynstr, OWNERAT_TXT);
    400 		break;
    401 
    402 	case ACE_GROUP|ACE_IDENTIFIER_GROUP:
    403 		error = str_append(dynstr, GROUPAT_TXT);
    404 		break;
    405 
    406 	case ACE_IDENTIFIER_GROUP:
    407 		if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) {
    408 			if (error = str_append(dynstr,
    409 			    GROUPSID_TXT))
    410 				break;
    411 			if (error = getsidname(acep->a_who, B_FALSE,
    412 			    &sidp, flags & ACL_NORESOLVE))
    413 				break;
    414 			error = str_append(dynstr, sidp);
    415 		} else {
    416 			if (error = str_append(dynstr, GROUP_TXT))
    417 				break;
    418 			error = str_append(dynstr, prgname(acep->a_who, idp,
    419 			    sizeof (idp), flags & ACL_NORESOLVE));
    420 		}
    421 		if (error == 0)
    422 			error = str_append(dynstr, ":");
    423 		break;
    424 
    425 	case ACE_EVERYONE:
    426 		error = str_append(dynstr, EVERYONEAT_TXT);
    427 		break;
    428 
    429 	case 0:
    430 		if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) {
    431 			if (error = str_append(dynstr, USERSID_TXT))
    432 				break;
    433 			if (error = getsidname(acep->a_who, B_TRUE,
    434 			    &sidp, flags & ACL_NORESOLVE))
    435 				break;
    436 			error = str_append(dynstr, sidp);
    437 		} else {
    438 			if (error = str_append(dynstr, USER_TXT))
    439 				break;
    440 			error = str_append(dynstr, pruname(acep->a_who, idp,
    441 			    sizeof (idp), flags & ACL_NORESOLVE));
    442 		}
    443 		if (error == 0)
    444 			error = str_append(dynstr, ":");
    445 		break;
    446 	default:
    447 		error = 0;
    448 		break;
    449 	}
    450 
    451 	if (sidp)
    452 		free(sidp);
    453 	return (error);
    454 }
    455 
    456 /*
    457  * compute string of permissions, such as read_data/write_data or
    458  * rwxp,...
    459  * The format depends on the flags field which indicates whether the compact
    460  * or verbose format should be used.
    461  */
    462 static int
    463 ace_perm_txt(dynaclstr_t *dstr, uint32_t mask,
    464     uint32_t iflags, int isdir, int flags)
    465 {
    466 	int error = 0;
    467 
    468 	if (flags & ACL_COMPACT_FMT) {
    469 		char buf[16];
    470 
    471 		if (mask & ACE_READ_DATA)
    472 			buf[0] = 'r';
    473 		else
    474 			buf[0] = '-';
    475 		if (mask & ACE_WRITE_DATA)
    476 			buf[1] = 'w';
    477 		else
    478 			buf[1] = '-';
    479 		if (mask & ACE_EXECUTE)
    480 			buf[2] = 'x';
    481 		else
    482 			buf[2] = '-';
    483 		if (mask & ACE_APPEND_DATA)
    484 			buf[3] = 'p';
    485 		else
    486 			buf[3] = '-';
    487 		if (mask & ACE_DELETE)
    488 			buf[4] = 'd';
    489 		else
    490 			buf[4] = '-';
    491 		if (mask & ACE_DELETE_CHILD)
    492 			buf[5] = 'D';
    493 		else
    494 			buf[5] = '-';
    495 		if (mask & ACE_READ_ATTRIBUTES)
    496 			buf[6] = 'a';
    497 		else
    498 			buf[6] = '-';
    499 		if (mask & ACE_WRITE_ATTRIBUTES)
    500 			buf[7] = 'A';
    501 		else
    502 			buf[7] = '-';
    503 		if (mask & ACE_READ_NAMED_ATTRS)
    504 			buf[8] = 'R';
    505 		else
    506 			buf[8] = '-';
    507 		if (mask & ACE_WRITE_NAMED_ATTRS)
    508 			buf[9] = 'W';
    509 		else
    510 			buf[9] = '-';
    511 		if (mask & ACE_READ_ACL)
    512 			buf[10] = 'c';
    513 		else
    514 			buf[10] = '-';
    515 		if (mask & ACE_WRITE_ACL)
    516 			buf[11] = 'C';
    517 		else
    518 			buf[11] = '-';
    519 		if (mask & ACE_WRITE_OWNER)
    520 			buf[12] = 'o';
    521 		else
    522 			buf[12] = '-';
    523 		if (mask & ACE_SYNCHRONIZE)
    524 			buf[13] = 's';
    525 		else
    526 			buf[13] = '-';
    527 		buf[14] = ':';
    528 		buf[15] = '\0';
    529 		error = str_append(dstr, buf);
    530 	} else {
    531 		/*
    532 		 * If ACE is a directory, but inheritance indicates its
    533 		 * for a file then print permissions for file rather than
    534 		 * dir.
    535 		 */
    536 		if (isdir) {
    537 			if (mask & ACE_LIST_DIRECTORY) {
    538 				if (iflags == ACE_FILE_INHERIT_ACE) {
    539 					error = str_append(dstr,
    540 					    READ_DATA_TXT);
    541 				} else {
    542 					error =
    543 					    str_append(dstr, READ_DIR_TXT);
    544 				}
    545 			}
    546 			if (error == 0 && (mask & ACE_ADD_FILE)) {
    547 				if (iflags == ACE_FILE_INHERIT_ACE) {
    548 					error =
    549 					    str_append(dstr, WRITE_DATA_TXT);
    550 				} else {
    551 					error =
    552 					    str_append(dstr, ADD_FILE_TXT);
    553 				}
    554 			}
    555 			if (error == 0 && (mask & ACE_ADD_SUBDIRECTORY)) {
    556 				if (iflags == ACE_FILE_INHERIT_ACE) {
    557 					error = str_append(dstr,
    558 					    APPEND_DATA_TXT);
    559 				} else {
    560 					error = str_append(dstr,
    561 					    ADD_DIR_TXT);
    562 				}
    563 			}
    564 		} else {
    565 			if (mask & ACE_READ_DATA) {
    566 				error = str_append(dstr, READ_DATA_TXT);
    567 			}
    568 			if (error == 0 && (mask & ACE_WRITE_DATA)) {
    569 				error = str_append(dstr, WRITE_DATA_TXT);
    570 			}
    571 			if (error == 0 && (mask & ACE_APPEND_DATA)) {
    572 				error = str_append(dstr, APPEND_DATA_TXT);
    573 			}
    574 		}
    575 		if (error == 0 && (mask & ACE_READ_NAMED_ATTRS)) {
    576 			error = str_append(dstr, READ_XATTR_TXT);
    577 		}
    578 		if (error == 0 && (mask & ACE_WRITE_NAMED_ATTRS)) {
    579 			error = str_append(dstr, WRITE_XATTR_TXT);
    580 		}
    581 		if (error == 0 && (mask & ACE_EXECUTE)) {
    582 			error = str_append(dstr, EXECUTE_TXT);
    583 		}
    584 		if (error == 0 && (mask & ACE_DELETE_CHILD)) {
    585 			error = str_append(dstr, DELETE_CHILD_TXT);
    586 		}
    587 		if (error == 0 && (mask & ACE_READ_ATTRIBUTES)) {
    588 			error = str_append(dstr, READ_ATTRIBUTES_TXT);
    589 		}
    590 		if (error == 0 && (mask & ACE_WRITE_ATTRIBUTES)) {
    591 			error = str_append(dstr, WRITE_ATTRIBUTES_TXT);
    592 		}
    593 		if (error == 0 && (mask & ACE_DELETE)) {
    594 			error = str_append(dstr, DELETE_TXT);
    595 		}
    596 		if (error == 0 && (mask & ACE_READ_ACL)) {
    597 			error = str_append(dstr, READ_ACL_TXT);
    598 		}
    599 		if (error == 0 && (mask & ACE_WRITE_ACL)) {
    600 			error = str_append(dstr, WRITE_ACL_TXT);
    601 		}
    602 		if (error == 0 && (mask & ACE_WRITE_OWNER)) {
    603 			error = str_append(dstr, WRITE_OWNER_TXT);
    604 		}
    605 		if (error == 0 && (mask & ACE_SYNCHRONIZE)) {
    606 			error = str_append(dstr, SYNCHRONIZE_TXT);
    607 		}
    608 		if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') {
    609 			dstr->d_aclexport[--dstr->d_pos] = '\0';
    610 		}
    611 		if (error == 0)
    612 			error = str_append(dstr, ":");
    613 	}
    614 	return (error);
    615 }
    616 
    617 /*
    618  * compute string of access type, such as allow, deny, ...
    619  */
    620 static int
    621 ace_access_txt(dynaclstr_t *dstr, int type)
    622 {
    623 	int error;
    624 
    625 	if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
    626 		error = str_append(dstr, ALLOW_TXT);
    627 	else if (type == ACE_ACCESS_DENIED_ACE_TYPE)
    628 		error = str_append(dstr, DENY_TXT);
    629 	else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE)
    630 		error = str_append(dstr, AUDIT_TXT);
    631 	else if (type == ACE_SYSTEM_ALARM_ACE_TYPE)
    632 		error = str_append(dstr, ALARM_TXT);
    633 	else
    634 		error = str_append(dstr, UNKNOWN_TXT);
    635 
    636 	return (error);
    637 }
    638 
    639 static int
    640 ace_inherit_txt(dynaclstr_t *dstr, uint32_t iflags, int flags)
    641 {
    642 	int error = 0;
    643 
    644 	if (flags & ACL_COMPACT_FMT) {
    645 		char buf[9];
    646 
    647 		if (iflags & ACE_FILE_INHERIT_ACE)
    648 			buf[0] = 'f';
    649 		else
    650 			buf[0] = '-';
    651 		if (iflags & ACE_DIRECTORY_INHERIT_ACE)
    652 			buf[1] = 'd';
    653 		else
    654 			buf[1] = '-';
    655 		if (iflags & ACE_INHERIT_ONLY_ACE)
    656 			buf[2] = 'i';
    657 		else
    658 			buf[2] = '-';
    659 		if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)
    660 			buf[3] = 'n';
    661 		else
    662 			buf[3] = '-';
    663 		if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
    664 			buf[4] = 'S';
    665 		else
    666 			buf[4] = '-';
    667 		if (iflags & ACE_FAILED_ACCESS_ACE_FLAG)
    668 			buf[5] = 'F';
    669 		else
    670 			buf[5] = '-';
    671 		if (iflags & ACE_INHERITED_ACE)
    672 			buf[6] = 'I';
    673 		else
    674 			buf[6] = '-';
    675 		buf[7] = ':';
    676 		buf[8] = '\0';
    677 		error = str_append(dstr, buf);
    678 	} else {
    679 		if (iflags & ACE_FILE_INHERIT_ACE) {
    680 			error = str_append(dstr, FILE_INHERIT_TXT);
    681 		}
    682 		if (error == 0 && (iflags & ACE_DIRECTORY_INHERIT_ACE)) {
    683 			error = str_append(dstr, DIR_INHERIT_TXT);
    684 		}
    685 		if (error == 0 && (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) {
    686 			error = str_append(dstr, NO_PROPAGATE_TXT);
    687 		}
    688 		if (error == 0 && (iflags & ACE_INHERIT_ONLY_ACE)) {
    689 			error = str_append(dstr, INHERIT_ONLY_TXT);
    690 		}
    691 		if (error == 0 && (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)) {
    692 			error = str_append(dstr, SUCCESSFUL_ACCESS_TXT);
    693 		}
    694 		if (error == 0 && (iflags & ACE_FAILED_ACCESS_ACE_FLAG)) {
    695 			error = str_append(dstr, FAILED_ACCESS_TXT);
    696 		}
    697 		if (error == 0 && (iflags & ACE_INHERITED_ACE)) {
    698 			error = str_append(dstr, INHERITED_ACE_TXT);
    699 		}
    700 		if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') {
    701 			dstr->d_aclexport[--dstr->d_pos] = '\0';
    702 			error = str_append(dstr, ":");
    703 		}
    704 	}
    705 
    706 	return (error);
    707 }
    708 
    709 /*
    710  * Convert internal acl representation to external representation.
    711  *
    712  * The length of a non-owning user name or non-owning group name ie entries
    713  * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX.  We
    714  * thus check the length of these entries, and if greater than LOGNAME_MAX,
    715  * we realloc() via increase_length().
    716  *
    717  * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
    718  * adhered to.
    719  */
    720 
    721 /*
    722  * acltotext() converts each ACL entry to look like this:
    723  *
    724  *    entry_type:uid^gid^name:perms[:id]
    725  *
    726  * The maximum length of entry_type is 14 ("defaultgroup::" and
    727  * "defaultother::") hence ENTRYTYPELEN is set to 14.
    728  *
    729  * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
    730  * however the ID could be a number so we therefore use ID_STR_MAX
    731  *
    732  * The length of a perms entry is 4 to allow for the comma appended to each
    733  * to each acl entry.  Hence PERMS is set to 4.
    734  */
    735 
    736 #define	ENTRYTYPELEN	14
    737 #define	PERMS		4
    738 #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
    739 
    740 char *
    741 aclent_acltotext(aclent_t  *aclp, int aclcnt, int flags)
    742 {
    743 	dynaclstr_t 	*dstr;
    744 	char		*aclexport = NULL;
    745 	int		i;
    746 	int 		error = 0;
    747 
    748 	if (aclp == NULL)
    749 		return (NULL);
    750 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
    751 		return (NULL);
    752 	dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE;
    753 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
    754 		free(dstr);
    755 		return (NULL);
    756 	}
    757 	*dstr->d_aclexport = '\0';
    758 	dstr->d_pos = 0;
    759 
    760 	for (i = 0; i < aclcnt; i++, aclp++) {
    761 		if (error = aclent_type_txt(dstr, aclp, flags))
    762 			break;
    763 		if (error = aclent_perm_txt(dstr, aclp->a_perm))
    764 			break;
    765 
    766 		if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) ||
    767 		    (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) ||
    768 		    (aclp->a_type == DEF_GROUP))) {
    769 			char id[ID_STR_MAX], *idstr;
    770 
    771 			if (error = str_append(dstr, ":"))
    772 				break;
    773 			id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */
    774 			idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]);
    775 			if (error = str_append(dstr, idstr))
    776 				break;
    777 		}
    778 		if (i < aclcnt - 1)
    779 			if (error = str_append(dstr, ","))
    780 				break;
    781 	}
    782 	if (error) {
    783 		if (dstr->d_aclexport)
    784 			free(dstr->d_aclexport);
    785 	} else {
    786 		aclexport = dstr->d_aclexport;
    787 	}
    788 	free(dstr);
    789 	return (aclexport);
    790 }
    791 
    792 char *
    793 acltotext(aclent_t *aclp, int aclcnt)
    794 {
    795 	return (aclent_acltotext(aclp, aclcnt, 0));
    796 }
    797 
    798 
    799 aclent_t *
    800 aclfromtext(char *aclstr, int *aclcnt)
    801 {
    802 	acl_t *aclp;
    803 	aclent_t *aclentp;
    804 	int error;
    805 
    806 	error = acl_fromtext(aclstr, &aclp);
    807 	if (error)
    808 		return (NULL);
    809 
    810 	aclentp = aclp->acl_aclp;
    811 	aclp->acl_aclp = NULL;
    812 	*aclcnt = aclp->acl_cnt;
    813 
    814 	acl_free(aclp);
    815 	return (aclentp);
    816 }
    817 
    818 
    819 /*
    820  * Append string onto dynaclstr_t.
    821  *
    822  * Return 0 on success, 1 for failure.
    823  */
    824 static int
    825 str_append(dynaclstr_t *dstr, char *newstr)
    826 {
    827 	size_t len = strlen(newstr);
    828 
    829 	if ((len + dstr->d_pos) >= dstr->d_bufsize) {
    830 		dstr->d_aclexport = realloc(dstr->d_aclexport,
    831 		    dstr->d_bufsize + len + 1);
    832 		if (dstr->d_aclexport == NULL)
    833 			return (1);
    834 		dstr->d_bufsize += len;
    835 	}
    836 	(void) strcat(&dstr->d_aclexport[dstr->d_pos], newstr);
    837 	dstr->d_pos += len;
    838 	return (0);
    839 }
    840 
    841 static int
    842 aclent_perm_txt(dynaclstr_t *dstr, o_mode_t perm)
    843 {
    844 	char buf[4];
    845 
    846 	if (perm & S_IROTH)
    847 		buf[0] = 'r';
    848 	else
    849 		buf[0] = '-';
    850 	if (perm & S_IWOTH)
    851 		buf[1] = 'w';
    852 	else
    853 		buf[1] = '-';
    854 	if (perm & S_IXOTH)
    855 		buf[2] = 'x';
    856 	else
    857 		buf[2] = '-';
    858 	buf[3] = '\0';
    859 	return (str_append(dstr, buf));
    860 }
    861 
    862 /*
    863  * ace_acltotext() convert each ace formatted acl to look like this:
    864  *
    865  * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
    866  *
    867  * The maximum length of entry_type is 5 ("group")
    868  *
    869  * The max length of a uid^gid^name entry (in theory) is 8,
    870  * however id could be a number so we therefore use ID_STR_MAX
    871  *
    872  * The length of a perms entry is 144 i.e read_data/write_data...
    873  * to each acl entry.
    874  *
    875  * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access
    876  *         /failed_access
    877  *
    878  */
    879 
    880 #define	ACE_ENTRYTYPLEN		6
    881 #define	IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \
    882 	"successful_access/failed_access/inherited"
    883 #define	IFLAGS_SIZE		(sizeof (IFLAGS_STR) - 1)
    884 #define	ACCESS_TYPE_SIZE	7	/* if unknown */
    885 #define	COLON_CNT		3
    886 #define	PERMS_LEN		216
    887 #define	ACE_ENTRY_SIZE	(ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \
    888     ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
    889 
    890 static char *
    891 ace_acltotext(acl_t *aceaclp, int flags)
    892 {
    893 	ace_t		*aclp = aceaclp->acl_aclp;
    894 	int		aclcnt = aceaclp->acl_cnt;
    895 	int		i;
    896 	int		error = 0;
    897 	int		isdir = (aceaclp->acl_flags & ACL_IS_DIR);
    898 	dynaclstr_t 	*dstr;
    899 	char		*aclexport = NULL;
    900 	char		*rawsidp = NULL;
    901 
    902 	if (aclp == NULL)
    903 		return (NULL);
    904 
    905 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
    906 		return (NULL);
    907 	dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE;
    908 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
    909 		free(dstr);
    910 		return (NULL);
    911 	}
    912 	*dstr->d_aclexport = '\0';
    913 	dstr->d_pos = 0;
    914 
    915 	for (i = 0; i < aclcnt; i++, aclp++) {
    916 
    917 		if (error = ace_type_txt(dstr, aclp, flags))
    918 			break;
    919 		if (error = ace_perm_txt(dstr, aclp->a_access_mask,
    920 		    aclp->a_flags, isdir, flags))
    921 			break;
    922 		if (error = ace_inherit_txt(dstr, aclp->a_flags, flags))
    923 			break;
    924 		if (error = ace_access_txt(dstr, aclp->a_type))
    925 			break;
    926 
    927 		if ((flags & ACL_APPEND_ID) &&
    928 		    (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ||
    929 		    ((aclp->a_flags & ACE_TYPE_FLAGS) ==
    930 		    ACE_IDENTIFIER_GROUP))) {
    931 			char id[ID_STR_MAX], *idstr;
    932 
    933 			if (error = str_append(dstr, ":"))
    934 				break;
    935 
    936 			rawsidp = NULL;
    937 			id[ID_STR_MAX -1] = '\0'; /* null terminate */
    938 			if (aclp->a_who > MAXUID && (flags & ACL_SID_FMT)) {
    939 
    940 				error = getsidname(aclp->a_who,
    941 				    ((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ?
    942 				    B_TRUE : B_FALSE, &idstr, 1);
    943 				rawsidp = idstr;
    944 				if (error)
    945 					break;
    946 			} else if (aclp->a_who > MAXUID &&
    947 			    !(flags & ACL_NORESOLVE)) {
    948 				idstr = lltostr(UID_NOBODY,
    949 				    &id[ID_STR_MAX - 1]);
    950 			} else {
    951 				idstr = lltostr(aclp->a_who,
    952 				    &id[ID_STR_MAX - 1]);
    953 			}
    954 			if (error = str_append(dstr, idstr))
    955 				break;
    956 			if (rawsidp) {
    957 				free(rawsidp);
    958 				rawsidp = NULL;
    959 			}
    960 		}
    961 		if (i < aclcnt - 1) {
    962 			if (error = str_append(dstr, ","))
    963 				break;
    964 		}
    965 	}
    966 
    967 	if (rawsidp)
    968 		free(rawsidp);
    969 	if (error) {
    970 		if (dstr->d_aclexport)
    971 			free(dstr->d_aclexport);
    972 	} else {
    973 		aclexport = dstr->d_aclexport;
    974 	}
    975 	free(dstr);
    976 	return (aclexport);
    977 }
    978 
    979 char *
    980 acl_totext(acl_t *aclp, int flags)
    981 {
    982 	char *txtp;
    983 
    984 	if (aclp == NULL)
    985 		return (NULL);
    986 
    987 	switch (aclp->acl_type) {
    988 	case ACE_T:
    989 		txtp = ace_acltotext(aclp, flags);
    990 		break;
    991 	case ACLENT_T:
    992 		txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags);
    993 		break;
    994 	}
    995 
    996 	return (txtp);
    997 }
    998 
    999 int
   1000 acl_fromtext(const char *acltextp, acl_t **ret_aclp)
   1001 {
   1002 	int error;
   1003 	char *buf;
   1004 
   1005 	buf = malloc(strlen(acltextp) + 2);
   1006 	if (buf == NULL)
   1007 		return (EACL_MEM_ERROR);
   1008 	strcpy(buf, acltextp);
   1009 	strcat(buf, "\n");
   1010 	yybuf = buf;
   1011 	yyreset();
   1012 	error = yyparse();
   1013 	free(buf);
   1014 
   1015 	if (yyacl) {
   1016 		if (error == 0)
   1017 			*ret_aclp = yyacl;
   1018 		else {
   1019 			acl_free(yyacl);
   1020 		}
   1021 		yyacl = NULL;
   1022 	}
   1023 	return (error);
   1024 }
   1025 
   1026 int
   1027 acl_parse(const char *acltextp, acl_t **aclp)
   1028 {
   1029 	int error;
   1030 
   1031 	yyinteractive = 1;
   1032 	error = acl_fromtext(acltextp, aclp);
   1033 	yyinteractive = 0;
   1034 	return (error);
   1035 }
   1036 
   1037 static void
   1038 ace_compact_printacl(acl_t *aclp)
   1039 {
   1040 	int cnt;
   1041 	ace_t *acep;
   1042 	dynaclstr_t *dstr;
   1043 	int len;
   1044 
   1045 	if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL)
   1046 		return;
   1047 	dstr->d_bufsize = ACE_ENTRY_SIZE;
   1048 	if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) {
   1049 		free(dstr);
   1050 		return;
   1051 	}
   1052 	*dstr->d_aclexport = '\0';
   1053 
   1054 	dstr->d_pos = 0;
   1055 	for (cnt = 0, acep = aclp->acl_aclp;
   1056 	    cnt != aclp->acl_cnt; cnt++, acep++) {
   1057 		dstr->d_aclexport[0] = '\0';
   1058 		dstr->d_pos = 0;
   1059 
   1060 		if (ace_type_txt(dstr, acep, 0))
   1061 			break;
   1062 		len = strlen(&dstr->d_aclexport[0]);
   1063 		if (ace_perm_txt(dstr, acep->a_access_mask, acep->a_flags,
   1064 		    aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT))
   1065 			break;
   1066 		if (ace_inherit_txt(dstr, acep->a_flags, ACL_COMPACT_FMT))
   1067 			break;
   1068 		if (ace_access_txt(dstr, acep->a_type) == -1)
   1069 			break;
   1070 		(void) printf("    %20.*s%s\n", len, dstr->d_aclexport,
   1071 		    &dstr->d_aclexport[len]);
   1072 	}
   1073 
   1074 	if (dstr->d_aclexport)
   1075 		free(dstr->d_aclexport);
   1076 	free(dstr);
   1077 }
   1078 
   1079 static void
   1080 ace_printacl(acl_t *aclp, int cols, int compact)
   1081 {
   1082 	int  slot = 0;
   1083 	char *token;
   1084 	char *acltext;
   1085 
   1086 	if (compact) {
   1087 		ace_compact_printacl(aclp);
   1088 		return;
   1089 	}
   1090 
   1091 	acltext = acl_totext(aclp, 0);
   1092 
   1093 	if (acltext == NULL)
   1094 		return;
   1095 
   1096 	token = strtok(acltext, ",");
   1097 	if (token == NULL) {
   1098 		free(acltext);
   1099 		return;
   1100 	}
   1101 
   1102 	do {
   1103 		(void) printf("     %d:", slot++);
   1104 		split_line(token, cols - 5);
   1105 	} while (token = strtok(NULL, ","));
   1106 	free(acltext);
   1107 }
   1108 
   1109 /*
   1110  * pretty print an ACL.
   1111  * For aclent_t ACL's the format is
   1112  * similar to the old format used by getfacl,
   1113  * with the addition of adding a "slot" number
   1114  * before each entry.
   1115  *
   1116  * for ace_t ACL's the cols variable will break up
   1117  * the long lines into multiple lines and will also
   1118  * print a "slot" number.
   1119  */
   1120 void
   1121 acl_printacl(acl_t *aclp, int cols, int compact)
   1122 {
   1123 
   1124 	switch (aclp->acl_type) {
   1125 	case ACLENT_T:
   1126 		aclent_printacl(aclp);
   1127 		break;
   1128 	case ACE_T:
   1129 		ace_printacl(aclp, cols, compact);
   1130 		break;
   1131 	}
   1132 }
   1133 
   1134 typedef struct value_table {
   1135 	char		p_letter; /* perm letter such as 'r' */
   1136 	uint32_t	p_value; /* value for perm when pletter found */
   1137 } value_table_t;
   1138 
   1139 /*
   1140  * The permission tables are laid out in positional order
   1141  * a '-' character will indicate a permission at a given
   1142  * position is not specified.  The '-' is not part of the
   1143  * table, but will be checked for in the permission computation
   1144  * routine.
   1145  */
   1146 value_table_t ace_perm_table[] = {
   1147 	{ 'r', ACE_READ_DATA},
   1148 	{ 'w', ACE_WRITE_DATA},
   1149 	{ 'x', ACE_EXECUTE},
   1150 	{ 'p', ACE_APPEND_DATA},
   1151 	{ 'd', ACE_DELETE},
   1152 	{ 'D', ACE_DELETE_CHILD},
   1153 	{ 'a', ACE_READ_ATTRIBUTES},
   1154 	{ 'A', ACE_WRITE_ATTRIBUTES},
   1155 	{ 'R', ACE_READ_NAMED_ATTRS},
   1156 	{ 'W', ACE_WRITE_NAMED_ATTRS},
   1157 	{ 'c', ACE_READ_ACL},
   1158 	{ 'C', ACE_WRITE_ACL},
   1159 	{ 'o', ACE_WRITE_OWNER},
   1160 	{ 's', ACE_SYNCHRONIZE}
   1161 };
   1162 
   1163 #define	ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t))
   1164 
   1165 value_table_t aclent_perm_table[] = {
   1166 	{ 'r', S_IROTH},
   1167 	{ 'w', S_IWOTH},
   1168 	{ 'x', S_IXOTH}
   1169 };
   1170 
   1171 #define	ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t))
   1172 
   1173 value_table_t inherit_table[] = {
   1174 	{'f', ACE_FILE_INHERIT_ACE},
   1175 	{'d', ACE_DIRECTORY_INHERIT_ACE},
   1176 	{'i', ACE_INHERIT_ONLY_ACE},
   1177 	{'n', ACE_NO_PROPAGATE_INHERIT_ACE},
   1178 	{'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
   1179 	{'F', ACE_FAILED_ACCESS_ACE_FLAG},
   1180 	{'I', ACE_INHERITED_ACE}
   1181 };
   1182 
   1183 #define	IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t))
   1184 #define	IFLAG_COUNT_V1 6 /* Older version compatibility */
   1185 
   1186 /*
   1187  * compute value from a permission table or inheritance table
   1188  * based on string passed in.  If positional is set then
   1189  * string must match order in permtab, otherwise any order
   1190  * is allowed.
   1191  */
   1192 int
   1193 compute_values(value_table_t *permtab, int count,
   1194     char *permstr, int positional, uint32_t *mask)
   1195 {
   1196 	uint32_t perm_val = 0;
   1197 	char *pstr;
   1198 	int i, found;
   1199 
   1200 	if (count < 0)
   1201 		return (1);
   1202 
   1203 	if (positional) {
   1204 		for (i = 0, pstr = permstr; i != count && pstr &&
   1205 		    *pstr; i++, pstr++) {
   1206 			if (*pstr == permtab[i].p_letter) {
   1207 				perm_val |= permtab[i].p_value;
   1208 			} else if (*pstr != '-') {
   1209 				return (1);
   1210 			}
   1211 		}
   1212 	} else {  /* random order single letters with no '-' */
   1213 		for (pstr = permstr; pstr && *pstr; pstr++) {
   1214 			for (found = 0, i = 0; i != count; i++) {
   1215 				if (*pstr == permtab[i].p_letter) {
   1216 					perm_val |= permtab[i].p_value;
   1217 					found = 1;
   1218 					break;
   1219 				}
   1220 			}
   1221 			if (found == 0)
   1222 				return (1);
   1223 		}
   1224 	}
   1225 
   1226 	*mask = perm_val;
   1227 	return (0);
   1228 }
   1229 
   1230 
   1231 int
   1232 ace_inherit_helper(char *str, uint32_t *imask, int table_length)
   1233 {
   1234 	int rc = 0;
   1235 
   1236 	if (strlen(str) == table_length) {
   1237 		/*
   1238 		 * If the string == table_length then first check to see it's
   1239 		 * in positional format.  If that fails then see if it's in
   1240 		 * non-positional format.
   1241 		 */
   1242 		if (compute_values(inherit_table, table_length, str,
   1243 		    1, imask) && compute_values(inherit_table,
   1244 		    table_length, str, 0, imask)) {
   1245 			rc = 1;
   1246 		}
   1247 	} else {
   1248 		rc = compute_values(inherit_table, table_length, str, 0, imask);
   1249 	}
   1250 
   1251 	return (rc ? EACL_INHERIT_ERROR : 0);
   1252 }
   1253 
   1254 /*
   1255  * compute value for inheritance flags.
   1256  */
   1257 int
   1258 compute_ace_inherit(char *str, uint32_t *imask)
   1259 {
   1260 	int rc = 0;
   1261 
   1262 	rc = ace_inherit_helper(str, imask, IFLAG_COUNT);
   1263 
   1264 	if (rc && strlen(str) != IFLAG_COUNT) {
   1265 
   1266 		/* is it an old formatted inherit string? */
   1267 		rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1);
   1268 	}
   1269 
   1270 	return (rc);
   1271 }
   1272 
   1273 
   1274 /*
   1275  * compute value for ACE permissions.
   1276  */
   1277 int
   1278 compute_ace_perms(char *str, uint32_t *mask)
   1279 {
   1280 	int positional = 0;
   1281 	int error;
   1282 
   1283 	if (strlen(str) == ACE_PERM_COUNT)
   1284 		positional = 1;
   1285 
   1286 	error = compute_values(ace_perm_table, ACE_PERM_COUNT,
   1287 	    str, positional, mask);
   1288 
   1289 	if (error && positional) {
   1290 		/*
   1291 		 * If positional was set, then make sure permissions
   1292 		 * aren't actually valid in non positional case where
   1293 		 * all permissions are specified, just in random order.
   1294 		 */
   1295 		error = compute_values(ace_perm_table,
   1296 		    ACE_PERM_COUNT, str, 0, mask);
   1297 	}
   1298 	if (error)
   1299 		error = EACL_PERM_MASK_ERROR;
   1300 
   1301 	return (error);
   1302 }
   1303 
   1304 
   1305 
   1306 /*
   1307  * compute values for aclent permissions.
   1308  */
   1309 int
   1310 compute_aclent_perms(char *str, o_mode_t *mask)
   1311 {
   1312 	int error;
   1313 	uint32_t pmask;
   1314 
   1315 	if (strlen(str) != ACLENT_PERM_COUNT)
   1316 		return (EACL_PERM_MASK_ERROR);
   1317 
   1318 	*mask = 0;
   1319 	error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT,
   1320 	    str, 1, &pmask);
   1321 	if (error == 0) {
   1322 		*mask = (o_mode_t)pmask;
   1323 	} else
   1324 		error = EACL_PERM_MASK_ERROR;
   1325 	return (error);
   1326 }
   1327 
   1328 /*
   1329  * determine ACE permissions.
   1330  */
   1331 int
   1332 ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask)
   1333 {
   1334 	int error;
   1335 
   1336 	if (aclperm->perm_style == PERM_TYPE_EMPTY) {
   1337 		*mask = 0;
   1338 		return (0);
   1339 	}
   1340 
   1341 	if (aclperm->perm_style == PERM_TYPE_ACE) {
   1342 		*mask = aclperm->perm_val;
   1343 		return (0);
   1344 	}
   1345 
   1346 	error = compute_ace_perms(aclperm->perm_str, mask);
   1347 	if (error) {
   1348 		acl_error(dgettext(TEXT_DOMAIN,
   1349 		    "Invalid permission(s) '%s' specified\n"),
   1350 		    aclperm->perm_str);
   1351 		return (EACL_PERM_MASK_ERROR);
   1352 	}
   1353 
   1354 	return (0);
   1355 }
   1356