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