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