10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51507Sgjelinek * Common Development and Distribution License (the "License"). 61507Sgjelinek * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 226269Smarks * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /*LINTLIBRARY*/ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <grp.h> 290Sstevel@tonic-gate #include <pwd.h> 300Sstevel@tonic-gate #include <string.h> 310Sstevel@tonic-gate #include <limits.h> 320Sstevel@tonic-gate #include <stdlib.h> 33789Sahrens #include <errno.h> 340Sstevel@tonic-gate #include <sys/param.h> 350Sstevel@tonic-gate #include <sys/types.h> 361420Smarks #include <sys/stat.h> 370Sstevel@tonic-gate #include <sys/acl.h> 38789Sahrens #include <aclutils.h> 397057Smarks #include <idmap.h> 401420Smarks 411420Smarks #define ID_STR_MAX 20 /* digits in LONG_MAX */ 42789Sahrens 431420Smarks #define APPENDED_ID_MAX ID_STR_MAX + 1 /* id + colon */ 441420Smarks /* 451420Smarks * yyinteractive controls whether yyparse should print out 461420Smarks * error messages to stderr, and whether or not id's should be 471420Smarks * allowed from acl_fromtext(). 481420Smarks */ 491420Smarks int yyinteractive; 501420Smarks acl_t *yyacl; 511420Smarks char *yybuf; 52789Sahrens 53789Sahrens extern acl_t *acl_alloc(enum acl_type); 540Sstevel@tonic-gate 557057Smarks /* 567057Smarks * dynamic string that will increase in size on an 577057Smarks * as needed basis. 587057Smarks */ 597057Smarks typedef struct dynaclstr { 607057Smarks size_t d_bufsize; /* current size of aclexport */ 617057Smarks char *d_aclexport; 627057Smarks int d_pos; 637057Smarks } dynaclstr_t; 64922Shm123892 657057Smarks static int str_append(dynaclstr_t *, char *); 667057Smarks static int aclent_perm_txt(dynaclstr_t *, o_mode_t); 670Sstevel@tonic-gate 681420Smarks static void 691420Smarks aclent_perms(int perm, char *txt_perms) 701420Smarks { 711420Smarks if (perm & S_IROTH) 721420Smarks txt_perms[0] = 'r'; 731420Smarks else 741420Smarks txt_perms[0] = '-'; 751420Smarks if (perm & S_IWOTH) 761420Smarks txt_perms[1] = 'w'; 771420Smarks else 781420Smarks txt_perms[1] = '-'; 791420Smarks if (perm & S_IXOTH) 801420Smarks txt_perms[2] = 'x'; 811420Smarks else 821420Smarks txt_perms[2] = '-'; 831420Smarks txt_perms[3] = '\0'; 841420Smarks } 851420Smarks 861420Smarks static char * 871535Smarks pruname(uid_t uid, char *uidp, size_t buflen, int noresolve) 881420Smarks { 891515Sgjelinek struct passwd *passwdp = NULL; 901420Smarks 911515Sgjelinek if (noresolve == 0) 921515Sgjelinek passwdp = getpwuid(uid); 931420Smarks if (passwdp == (struct passwd *)NULL) { 941420Smarks /* could not get passwd information: display uid instead */ 954321Scasper (void) snprintf(uidp, buflen, "%u", uid); 961535Smarks } else { 971535Smarks (void) strlcpy(uidp, passwdp->pw_name, buflen); 981535Smarks } 991535Smarks return (uidp); 1001420Smarks } 1011420Smarks 1021420Smarks static char * 1031535Smarks prgname(gid_t gid, char *gidp, size_t buflen, int noresolve) 1041420Smarks { 1051515Sgjelinek struct group *groupp = NULL; 1061420Smarks 1071515Sgjelinek if (noresolve == 0) 1081515Sgjelinek groupp = getgrgid(gid); 1091420Smarks if (groupp == (struct group *)NULL) { 1101420Smarks /* could not get group information: display gid instead */ 1114321Scasper (void) snprintf(gidp, buflen, "%u", gid); 1121535Smarks } else { 1131535Smarks (void) strlcpy(gidp, groupp->gr_name, buflen); 1141535Smarks } 1151535Smarks return (gidp); 1161420Smarks } 1177057Smarks 1187680SMark.Shellenbaum@Sun.COM static int 1197680SMark.Shellenbaum@Sun.COM getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve) 1207057Smarks { 1217057Smarks idmap_handle_t *idmap_hdl = NULL; 1227057Smarks idmap_get_handle_t *get_hdl = NULL; 1237057Smarks idmap_stat status; 1247057Smarks idmap_rid_t rid; 1257680SMark.Shellenbaum@Sun.COM int error = IDMAP_ERR_NORESULT; 1267057Smarks int len; 1277057Smarks char *domain; 1287057Smarks char *name; 1297057Smarks 1307680SMark.Shellenbaum@Sun.COM *sidp = NULL; 1317057Smarks 1327057Smarks /* 1337057Smarks * First try and get windows name 1347057Smarks */ 1357057Smarks 1367680SMark.Shellenbaum@Sun.COM if (!noresolve) { 1377680SMark.Shellenbaum@Sun.COM if (user) 1387680SMark.Shellenbaum@Sun.COM error = idmap_getwinnamebyuid(who, 1397680SMark.Shellenbaum@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &name, &domain); 1407680SMark.Shellenbaum@Sun.COM else 1417680SMark.Shellenbaum@Sun.COM error = idmap_getwinnamebygid(who, 1427680SMark.Shellenbaum@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &name, &domain); 1437680SMark.Shellenbaum@Sun.COM } 1447680SMark.Shellenbaum@Sun.COM if (error != IDMAP_SUCCESS) { 1457680SMark.Shellenbaum@Sun.COM if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS && 1467680SMark.Shellenbaum@Sun.COM idmap_get_create(idmap_hdl, &get_hdl) == IDMAP_SUCCESS) { 1477057Smarks if (user) 1487057Smarks error = idmap_get_sidbyuid(get_hdl, who, 1497369SJulian.Pullen@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &domain, &rid, 1507369SJulian.Pullen@Sun.COM &status); 1517057Smarks else 1527057Smarks error = idmap_get_sidbygid(get_hdl, who, 1537369SJulian.Pullen@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &domain, &rid, 1547369SJulian.Pullen@Sun.COM &status); 1557680SMark.Shellenbaum@Sun.COM if (error == IDMAP_SUCCESS && 1567680SMark.Shellenbaum@Sun.COM idmap_get_mappings(get_hdl) == 0) { 1577680SMark.Shellenbaum@Sun.COM if (status == IDMAP_SUCCESS) { 1587680SMark.Shellenbaum@Sun.COM len = snprintf(NULL, 0, 1597680SMark.Shellenbaum@Sun.COM "%s-%d", domain, rid); 1607680SMark.Shellenbaum@Sun.COM if (*sidp = malloc(len + 1)) { 1617680SMark.Shellenbaum@Sun.COM (void) snprintf(*sidp, len + 1, 1627680SMark.Shellenbaum@Sun.COM "%s-%d", domain, rid); 1637680SMark.Shellenbaum@Sun.COM } 1647680SMark.Shellenbaum@Sun.COM } 1657680SMark.Shellenbaum@Sun.COM } 1667057Smarks } 1677057Smarks if (get_hdl) 1687057Smarks idmap_get_destroy(get_hdl); 1697057Smarks if (idmap_hdl) 1707057Smarks (void) idmap_fini(idmap_hdl); 1717057Smarks } else { 1727057Smarks int len; 1737680SMark.Shellenbaum@Sun.COM 174*8268SMark.Shellenbaum@Sun.COM len = snprintf(NULL, 0, "%s@%s", name, domain); 1757680SMark.Shellenbaum@Sun.COM if (*sidp = malloc(len + 1)) 1767680SMark.Shellenbaum@Sun.COM (void) snprintf(*sidp, len + 1, "%s@%s", name, domain); 177*8268SMark.Shellenbaum@Sun.COM free(name); 178*8268SMark.Shellenbaum@Sun.COM free(domain); 1797057Smarks } 1807680SMark.Shellenbaum@Sun.COM return (*sidp ? 0 : 1); 1817057Smarks } 1827057Smarks 1831420Smarks static void 1841420Smarks aclent_printacl(acl_t *aclp) 185789Sahrens { 1861420Smarks aclent_t *tp; 1871420Smarks int aclcnt; 1881420Smarks int mask; 1891420Smarks int slot = 0; 1901420Smarks char perm[4]; 1911535Smarks char uidp[ID_STR_MAX]; 1921535Smarks char gidp[ID_STR_MAX]; 1931420Smarks 1941420Smarks /* display ACL: assume it is sorted. */ 1951420Smarks aclcnt = aclp->acl_cnt; 1961420Smarks for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) { 1971420Smarks if (tp->a_type == CLASS_OBJ) 1981420Smarks mask = tp->a_perm; 1991420Smarks } 2001420Smarks aclcnt = aclp->acl_cnt; 2011420Smarks for (tp = aclp->acl_aclp; aclcnt--; tp++) { 2021420Smarks (void) printf(" %d:", slot++); 2031420Smarks switch (tp->a_type) { 2041420Smarks case USER: 2051420Smarks aclent_perms(tp->a_perm, perm); 2061420Smarks (void) printf("user:%s:%s\t\t", 2071535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 2081420Smarks aclent_perms((tp->a_perm & mask), perm); 2091420Smarks (void) printf("#effective:%s\n", perm); 2101420Smarks break; 2111420Smarks case USER_OBJ: 2121420Smarks /* no need to display uid */ 2131420Smarks aclent_perms(tp->a_perm, perm); 2141420Smarks (void) printf("user::%s\n", perm); 2151420Smarks break; 2161420Smarks case GROUP: 2171420Smarks aclent_perms(tp->a_perm, perm); 2181420Smarks (void) printf("group:%s:%s\t\t", 2191535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 2201420Smarks aclent_perms(tp->a_perm & mask, perm); 2211420Smarks (void) printf("#effective:%s\n", perm); 2221420Smarks break; 2231420Smarks case GROUP_OBJ: 2241420Smarks aclent_perms(tp->a_perm, perm); 2251420Smarks (void) printf("group::%s\t\t", perm); 2261420Smarks aclent_perms(tp->a_perm & mask, perm); 2271420Smarks (void) printf("#effective:%s\n", perm); 2281420Smarks break; 2291420Smarks case CLASS_OBJ: 2301420Smarks aclent_perms(tp->a_perm, perm); 2311420Smarks (void) printf("mask:%s\n", perm); 2321420Smarks break; 2331420Smarks case OTHER_OBJ: 2341420Smarks aclent_perms(tp->a_perm, perm); 2351420Smarks (void) printf("other:%s\n", perm); 2361420Smarks break; 2371420Smarks case DEF_USER: 2381420Smarks aclent_perms(tp->a_perm, perm); 2391420Smarks (void) printf("default:user:%s:%s\n", 2401535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 2411420Smarks break; 2421420Smarks case DEF_USER_OBJ: 2431420Smarks aclent_perms(tp->a_perm, perm); 2441420Smarks (void) printf("default:user::%s\n", perm); 2451420Smarks break; 2461420Smarks case DEF_GROUP: 2471420Smarks aclent_perms(tp->a_perm, perm); 2481420Smarks (void) printf("default:group:%s:%s\n", 2491535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 2501420Smarks break; 2511420Smarks case DEF_GROUP_OBJ: 2521420Smarks aclent_perms(tp->a_perm, perm); 2531420Smarks (void) printf("default:group::%s\n", perm); 2541420Smarks break; 2551420Smarks case DEF_CLASS_OBJ: 2561420Smarks aclent_perms(tp->a_perm, perm); 2571420Smarks (void) printf("default:mask:%s\n", perm); 2581420Smarks break; 2591420Smarks case DEF_OTHER_OBJ: 2601420Smarks aclent_perms(tp->a_perm, perm); 2611420Smarks (void) printf("default:other:%s\n", perm); 2621420Smarks break; 2631420Smarks default: 2641420Smarks (void) fprintf(stderr, 2651567Smarks dgettext(TEXT_DOMAIN, "unrecognized entry\n")); 2661420Smarks break; 2671420Smarks } 2681420Smarks } 2691420Smarks } 2701420Smarks 2711420Smarks static void 2721420Smarks split_line(char *str, int cols) 2731420Smarks { 2741420Smarks char *ptr; 2751420Smarks int len; 2761420Smarks int i; 2771420Smarks int last_split; 2781420Smarks char *pad = ""; 2791420Smarks int pad_len; 2801420Smarks 2811420Smarks len = strlen(str); 2821420Smarks ptr = str; 2831420Smarks pad_len = 0; 2841420Smarks 2851420Smarks ptr = str; 2861420Smarks last_split = 0; 2871420Smarks for (i = 0; i != len; i++) { 2881420Smarks if ((i + pad_len + 4) >= cols) { 2891420Smarks (void) printf("%s%.*s\n", pad, last_split, ptr); 2901420Smarks ptr = &ptr[last_split]; 2911420Smarks len = strlen(ptr); 2921420Smarks i = 0; 2931420Smarks pad_len = 4; 2941420Smarks pad = " "; 2951420Smarks } else { 2961420Smarks if (ptr[i] == '/' || ptr[i] == ':') { 2971420Smarks last_split = i; 2981420Smarks } 2991420Smarks } 3001420Smarks } 3011420Smarks if (i == len) { 3021420Smarks (void) printf("%s%s\n", pad, ptr); 3031420Smarks } 3041420Smarks } 3051420Smarks 3067057Smarks /* 3077057Smarks * compute entry type string, such as user:joe, group:staff,... 3087057Smarks */ 3097057Smarks static int 3107057Smarks aclent_type_txt(dynaclstr_t *dstr, aclent_t *aclp, int flags) 3111420Smarks { 3127057Smarks char idp[ID_STR_MAX]; 3137057Smarks int error; 3147057Smarks 3157057Smarks switch (aclp->a_type) { 3167057Smarks case DEF_USER_OBJ: 3177057Smarks case USER_OBJ: 3187057Smarks if (aclp->a_type == USER_OBJ) 3197057Smarks error = str_append(dstr, "user::"); 3207057Smarks else 3217057Smarks error = str_append(dstr, "defaultuser::"); 3227057Smarks break; 3237057Smarks 3247057Smarks case DEF_USER: 3257057Smarks case USER: 3267057Smarks if (aclp->a_type == USER) 3277057Smarks error = str_append(dstr, "user:"); 3287057Smarks else 3297057Smarks error = str_append(dstr, "defaultuser:"); 3307057Smarks if (error) 3317057Smarks break; 3327057Smarks error = str_append(dstr, pruname(aclp->a_id, idp, 3337057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 3347057Smarks if (error == 0) 3357057Smarks error = str_append(dstr, ":"); 3367057Smarks break; 3377057Smarks 3387057Smarks case DEF_GROUP_OBJ: 3397057Smarks case GROUP_OBJ: 3407057Smarks if (aclp->a_type == GROUP_OBJ) 3417057Smarks error = str_append(dstr, "group::"); 3427057Smarks else 3437057Smarks error = str_append(dstr, "defaultgroup::"); 3447057Smarks break; 3451420Smarks 3467057Smarks case DEF_GROUP: 3477057Smarks case GROUP: 3487057Smarks if (aclp->a_type == GROUP) 3497057Smarks error = str_append(dstr, "group:"); 3507057Smarks else 3517057Smarks error = str_append(dstr, "defaultgroup:"); 3527057Smarks if (error) 3537057Smarks break; 3547057Smarks error = str_append(dstr, prgname(aclp->a_id, idp, 3557057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 3567057Smarks if (error == 0) 3577057Smarks error = str_append(dstr, ":"); 3587057Smarks break; 3597057Smarks 3607057Smarks case DEF_CLASS_OBJ: 3617057Smarks case CLASS_OBJ: 3627057Smarks if (aclp->a_type == CLASS_OBJ) 3637057Smarks error = str_append(dstr, "mask:"); 3647057Smarks else 3657057Smarks error = str_append(dstr, "defaultmask:"); 3667057Smarks break; 3671420Smarks 3687057Smarks case DEF_OTHER_OBJ: 3697057Smarks case OTHER_OBJ: 3707057Smarks if (aclp->a_type == OTHER_OBJ) 3717057Smarks error = str_append(dstr, "other:"); 3727057Smarks else 3737057Smarks error = str_append(dstr, "defaultother:"); 3747057Smarks break; 3757057Smarks 3767057Smarks default: 3777057Smarks error = 1; 3787057Smarks break; 3797057Smarks } 3807057Smarks 3817057Smarks return (error); 3827057Smarks } 3837057Smarks 3847057Smarks /* 3857057Smarks * compute entry type string such as, owner@:, user:joe, group:staff,... 3867057Smarks */ 3877057Smarks static int 3887057Smarks ace_type_txt(dynaclstr_t *dynstr, ace_t *acep, int flags) 3897057Smarks { 3907057Smarks char idp[ID_STR_MAX]; 3917057Smarks int error; 3927057Smarks char *sidp = NULL; 3931420Smarks 3941420Smarks switch (acep->a_flags & ACE_TYPE_FLAGS) { 3951420Smarks case ACE_OWNER: 3967057Smarks error = str_append(dynstr, OWNERAT_TXT); 3971420Smarks break; 3981420Smarks 3991420Smarks case ACE_GROUP|ACE_IDENTIFIER_GROUP: 4007057Smarks error = str_append(dynstr, GROUPAT_TXT); 4011420Smarks break; 4021420Smarks 4031420Smarks case ACE_IDENTIFIER_GROUP: 4047057Smarks if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) { 4057057Smarks if (error = str_append(dynstr, 4067057Smarks GROUPSID_TXT)) 4077057Smarks break; 4087680SMark.Shellenbaum@Sun.COM if (error = getsidname(acep->a_who, B_FALSE, 4097680SMark.Shellenbaum@Sun.COM &sidp, flags & ACL_NORESOLVE)) 4107680SMark.Shellenbaum@Sun.COM break; 4117680SMark.Shellenbaum@Sun.COM error = str_append(dynstr, sidp); 4127057Smarks } else { 4137057Smarks if (error = str_append(dynstr, GROUP_TXT)) 4147057Smarks break; 4157057Smarks error = str_append(dynstr, prgname(acep->a_who, idp, 4167057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 4177057Smarks } 4187057Smarks if (error == 0) 4197057Smarks error = str_append(dynstr, ":"); 4201420Smarks break; 4211420Smarks 4221420Smarks case ACE_EVERYONE: 4237057Smarks error = str_append(dynstr, EVERYONEAT_TXT); 4241420Smarks break; 4251420Smarks 4261420Smarks case 0: 4277057Smarks if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) { 4287057Smarks if (error = str_append(dynstr, USERSID_TXT)) 4297057Smarks break; 4307680SMark.Shellenbaum@Sun.COM if (error = getsidname(acep->a_who, B_TRUE, 4317680SMark.Shellenbaum@Sun.COM &sidp, flags & ACL_NORESOLVE)) 4327680SMark.Shellenbaum@Sun.COM break; 4337680SMark.Shellenbaum@Sun.COM error = str_append(dynstr, sidp); 4347057Smarks } else { 4357057Smarks if (error = str_append(dynstr, USER_TXT)) 4367057Smarks break; 4377057Smarks error = str_append(dynstr, pruname(acep->a_who, idp, 4387057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 4397057Smarks } 4407057Smarks if (error == 0) 4417057Smarks error = str_append(dynstr, ":"); 4427057Smarks break; 4437057Smarks default: 4447057Smarks error = 0; 4451420Smarks break; 4461420Smarks } 4471420Smarks 4487057Smarks if (sidp) 4497057Smarks free(sidp); 4507057Smarks return (error); 4511420Smarks } 4521420Smarks 4537057Smarks /* 4547057Smarks * compute string of permissions, such as read_data/write_data or 4557057Smarks * rwxp,... 4567057Smarks * The format depends on the flags field which indicates whether the compact 4577057Smarks * or verbose format should be used. 4587057Smarks */ 4597057Smarks static int 4607057Smarks ace_perm_txt(dynaclstr_t *dstr, uint32_t mask, 4611420Smarks uint32_t iflags, int isdir, int flags) 4621420Smarks { 4637057Smarks int error = 0; 4641420Smarks 4651420Smarks if (flags & ACL_COMPACT_FMT) { 4667057Smarks char buf[16]; 467789Sahrens 4681420Smarks if (mask & ACE_READ_DATA) 4691420Smarks buf[0] = 'r'; 4701420Smarks else 4711420Smarks buf[0] = '-'; 4721420Smarks if (mask & ACE_WRITE_DATA) 4731420Smarks buf[1] = 'w'; 4741420Smarks else 4751420Smarks buf[1] = '-'; 4761420Smarks if (mask & ACE_EXECUTE) 4771420Smarks buf[2] = 'x'; 4781420Smarks else 4791420Smarks buf[2] = '-'; 4801420Smarks if (mask & ACE_APPEND_DATA) 4811420Smarks buf[3] = 'p'; 4821420Smarks else 4831420Smarks buf[3] = '-'; 4841420Smarks if (mask & ACE_DELETE) 4851420Smarks buf[4] = 'd'; 4861420Smarks else 4871420Smarks buf[4] = '-'; 4881420Smarks if (mask & ACE_DELETE_CHILD) 4891420Smarks buf[5] = 'D'; 4901420Smarks else 4911420Smarks buf[5] = '-'; 4921420Smarks if (mask & ACE_READ_ATTRIBUTES) 4931420Smarks buf[6] = 'a'; 4941420Smarks else 4951420Smarks buf[6] = '-'; 4961420Smarks if (mask & ACE_WRITE_ATTRIBUTES) 4971420Smarks buf[7] = 'A'; 4981420Smarks else 4991420Smarks buf[7] = '-'; 5001420Smarks if (mask & ACE_READ_NAMED_ATTRS) 5011420Smarks buf[8] = 'R'; 5021420Smarks else 5031420Smarks buf[8] = '-'; 5041420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) 5051420Smarks buf[9] = 'W'; 5061420Smarks else 5071420Smarks buf[9] = '-'; 5081420Smarks if (mask & ACE_READ_ACL) 5091420Smarks buf[10] = 'c'; 5101420Smarks else 5111420Smarks buf[10] = '-'; 5121420Smarks if (mask & ACE_WRITE_ACL) 5131420Smarks buf[11] = 'C'; 5141420Smarks else 5151420Smarks buf[11] = '-'; 5161420Smarks if (mask & ACE_WRITE_OWNER) 5171420Smarks buf[12] = 'o'; 5181420Smarks else 5191420Smarks buf[12] = '-'; 5201420Smarks if (mask & ACE_SYNCHRONIZE) 5211420Smarks buf[13] = 's'; 5221420Smarks else 5231420Smarks buf[13] = '-'; 5247057Smarks buf[14] = ':'; 5257057Smarks buf[15] = '\0'; 5267057Smarks error = str_append(dstr, buf); 5271420Smarks } else { 5281420Smarks /* 5291420Smarks * If ACE is a directory, but inheritance indicates its 5301420Smarks * for a file then print permissions for file rather than 5311420Smarks * dir. 5321420Smarks */ 5331420Smarks if (isdir) { 5341420Smarks if (mask & ACE_LIST_DIRECTORY) { 5351420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5367057Smarks error = str_append(dstr, 5377057Smarks READ_DATA_TXT); 5381420Smarks } else { 5397057Smarks error = 5407057Smarks str_append(dstr, READ_DIR_TXT); 5411420Smarks } 5421420Smarks } 5437057Smarks if (error == 0 && (mask & ACE_ADD_FILE)) { 5441420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5457057Smarks error = 5467057Smarks str_append(dstr, WRITE_DATA_TXT); 5471420Smarks } else { 5487057Smarks error = 5497057Smarks str_append(dstr, ADD_FILE_TXT); 5501420Smarks } 5511420Smarks } 5527057Smarks if (error == 0 && (mask & ACE_ADD_SUBDIRECTORY)) { 5531420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5547057Smarks error = str_append(dstr, 5557057Smarks APPEND_DATA_TXT); 5561420Smarks } else { 5577057Smarks error = str_append(dstr, 5587057Smarks ADD_DIR_TXT); 5591420Smarks } 5601420Smarks } 5611420Smarks } else { 5621420Smarks if (mask & ACE_READ_DATA) { 5637057Smarks error = str_append(dstr, READ_DATA_TXT); 5641420Smarks } 5657057Smarks if (error == 0 && (mask & ACE_WRITE_DATA)) { 5667057Smarks error = str_append(dstr, WRITE_DATA_TXT); 5671420Smarks } 5687057Smarks if (error == 0 && (mask & ACE_APPEND_DATA)) { 5697057Smarks error = str_append(dstr, APPEND_DATA_TXT); 5701420Smarks } 5711420Smarks } 5727057Smarks if (error == 0 && (mask & ACE_READ_NAMED_ATTRS)) { 5737057Smarks error = str_append(dstr, READ_XATTR_TXT); 5741420Smarks } 5757057Smarks if (error == 0 && (mask & ACE_WRITE_NAMED_ATTRS)) { 5767057Smarks error = str_append(dstr, WRITE_XATTR_TXT); 5771420Smarks } 5787057Smarks if (error == 0 && (mask & ACE_EXECUTE)) { 5797057Smarks error = str_append(dstr, EXECUTE_TXT); 5801420Smarks } 5817057Smarks if (error == 0 && (mask & ACE_DELETE_CHILD)) { 5827057Smarks error = str_append(dstr, DELETE_CHILD_TXT); 5831420Smarks } 5847057Smarks if (error == 0 && (mask & ACE_READ_ATTRIBUTES)) { 5857057Smarks error = str_append(dstr, READ_ATTRIBUTES_TXT); 5861420Smarks } 5877057Smarks if (error == 0 && (mask & ACE_WRITE_ATTRIBUTES)) { 5887057Smarks error = str_append(dstr, WRITE_ATTRIBUTES_TXT); 5891420Smarks } 5907057Smarks if (error == 0 && (mask & ACE_DELETE)) { 5917057Smarks error = str_append(dstr, DELETE_TXT); 5921420Smarks } 5937057Smarks if (error == 0 && (mask & ACE_READ_ACL)) { 5947057Smarks error = str_append(dstr, READ_ACL_TXT); 5951420Smarks } 5967057Smarks if (error == 0 && (mask & ACE_WRITE_ACL)) { 5977057Smarks error = str_append(dstr, WRITE_ACL_TXT); 5981420Smarks } 5997057Smarks if (error == 0 && (mask & ACE_WRITE_OWNER)) { 6007057Smarks error = str_append(dstr, WRITE_OWNER_TXT); 6011420Smarks } 6027057Smarks if (error == 0 && (mask & ACE_SYNCHRONIZE)) { 6037057Smarks error = str_append(dstr, SYNCHRONIZE_TXT); 6041420Smarks } 6057057Smarks if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') { 6067057Smarks dstr->d_aclexport[--dstr->d_pos] = '\0'; 6077057Smarks } 6087057Smarks if (error == 0) 6097057Smarks error = str_append(dstr, ":"); 6101420Smarks } 6117057Smarks return (error); 6121420Smarks } 6131420Smarks 6147057Smarks /* 6157057Smarks * compute string of access type, such as allow, deny, ... 6167057Smarks */ 6177057Smarks static int 6187057Smarks ace_access_txt(dynaclstr_t *dstr, int type) 6191420Smarks { 6207057Smarks int error; 6211420Smarks 6227057Smarks if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) 6237057Smarks error = str_append(dstr, ALLOW_TXT); 6247057Smarks else if (type == ACE_ACCESS_DENIED_ACE_TYPE) 6257057Smarks error = str_append(dstr, DENY_TXT); 6267057Smarks else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) 6277057Smarks error = str_append(dstr, AUDIT_TXT); 6287057Smarks else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) 6297057Smarks error = str_append(dstr, ALARM_TXT); 6307057Smarks else 6317057Smarks error = str_append(dstr, UNKNOWN_TXT); 6321420Smarks 6337057Smarks return (error); 6341420Smarks } 6351420Smarks 6367057Smarks static int 6377057Smarks ace_inherit_txt(dynaclstr_t *dstr, uint32_t iflags, int flags) 6381420Smarks { 6397057Smarks int error = 0; 640789Sahrens 6411420Smarks if (flags & ACL_COMPACT_FMT) { 6427057Smarks char buf[9]; 6437057Smarks 6441420Smarks if (iflags & ACE_FILE_INHERIT_ACE) 6451420Smarks buf[0] = 'f'; 6461420Smarks else 6471420Smarks buf[0] = '-'; 6481420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) 6491420Smarks buf[1] = 'd'; 6501420Smarks else 6511420Smarks buf[1] = '-'; 6521420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) 6531420Smarks buf[2] = 'i'; 6541420Smarks else 6551420Smarks buf[2] = '-'; 6561420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) 6571420Smarks buf[3] = 'n'; 6581420Smarks else 6591420Smarks buf[3] = '-'; 6601420Smarks if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 6611420Smarks buf[4] = 'S'; 6621420Smarks else 6631420Smarks buf[4] = '-'; 6641420Smarks if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) 6651420Smarks buf[5] = 'F'; 6661420Smarks else 6671420Smarks buf[5] = '-'; 6685331Samw if (iflags & ACE_INHERITED_ACE) 6695331Samw buf[6] = 'I'; 6705331Samw else 6715331Samw buf[6] = '-'; 6727057Smarks buf[7] = ':'; 6737057Smarks buf[8] = '\0'; 6747057Smarks error = str_append(dstr, buf); 6751420Smarks } else { 6761420Smarks if (iflags & ACE_FILE_INHERIT_ACE) { 6777057Smarks error = str_append(dstr, FILE_INHERIT_TXT); 6781420Smarks } 6797057Smarks if (error == 0 && (iflags & ACE_DIRECTORY_INHERIT_ACE)) { 6807057Smarks error = str_append(dstr, DIR_INHERIT_TXT); 6811420Smarks } 6827057Smarks if (error == 0 && (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) { 6837057Smarks error = str_append(dstr, NO_PROPAGATE_TXT); 6841420Smarks } 6857057Smarks if (error == 0 && (iflags & ACE_INHERIT_ONLY_ACE)) { 6867057Smarks error = str_append(dstr, INHERIT_ONLY_TXT); 6871420Smarks } 6887057Smarks if (error == 0 && (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)) { 6897057Smarks error = str_append(dstr, SUCCESSFUL_ACCESS_TXT); 6905331Samw } 6917057Smarks if (error == 0 && (iflags & ACE_FAILED_ACCESS_ACE_FLAG)) { 6927057Smarks error = str_append(dstr, FAILED_ACCESS_TXT); 6935331Samw } 6947057Smarks if (error == 0 && (iflags & ACE_INHERITED_ACE)) { 6957057Smarks error = str_append(dstr, INHERITED_ACE_TXT); 6965331Samw } 6977057Smarks if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') { 6987057Smarks dstr->d_aclexport[--dstr->d_pos] = '\0'; 6997057Smarks error = str_append(dstr, ":"); 7007057Smarks } 7011420Smarks } 7021420Smarks 7037057Smarks return (error); 704789Sahrens } 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate /* 7070Sstevel@tonic-gate * Convert internal acl representation to external representation. 7080Sstevel@tonic-gate * 7090Sstevel@tonic-gate * The length of a non-owning user name or non-owning group name ie entries 7100Sstevel@tonic-gate * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We 7110Sstevel@tonic-gate * thus check the length of these entries, and if greater than LOGNAME_MAX, 7120Sstevel@tonic-gate * we realloc() via increase_length(). 7130Sstevel@tonic-gate * 7140Sstevel@tonic-gate * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always 7150Sstevel@tonic-gate * adhered to. 7160Sstevel@tonic-gate */ 7171420Smarks 7181420Smarks /* 7191420Smarks * acltotext() converts each ACL entry to look like this: 7201420Smarks * 7211420Smarks * entry_type:uid^gid^name:perms[:id] 7221420Smarks * 7231420Smarks * The maximum length of entry_type is 14 ("defaultgroup::" and 7241420Smarks * "defaultother::") hence ENTRYTYPELEN is set to 14. 7251420Smarks * 7261420Smarks * The max length of a uid^gid^name entry (in theory) is 8, hence we use, 7271420Smarks * however the ID could be a number so we therefore use ID_STR_MAX 7281420Smarks * 7291420Smarks * The length of a perms entry is 4 to allow for the comma appended to each 7301420Smarks * to each acl entry. Hence PERMS is set to 4. 7311420Smarks */ 7321420Smarks 7331420Smarks #define ENTRYTYPELEN 14 7341420Smarks #define PERMS 4 7351420Smarks #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX) 7361420Smarks 7370Sstevel@tonic-gate char * 7381420Smarks aclent_acltotext(aclent_t *aclp, int aclcnt, int flags) 7390Sstevel@tonic-gate { 7407057Smarks dynaclstr_t *dstr; 7417680SMark.Shellenbaum@Sun.COM char *aclexport = NULL; 7427057Smarks int i; 7437057Smarks int error = 0; 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate if (aclp == NULL) 7460Sstevel@tonic-gate return (NULL); 7477057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 7480Sstevel@tonic-gate return (NULL); 7497057Smarks dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE; 7507057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 7510Sstevel@tonic-gate free(dstr); 7520Sstevel@tonic-gate return (NULL); 7530Sstevel@tonic-gate } 7547057Smarks *dstr->d_aclexport = '\0'; 7557057Smarks dstr->d_pos = 0; 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate for (i = 0; i < aclcnt; i++, aclp++) { 7587057Smarks if (error = aclent_type_txt(dstr, aclp, flags)) 7590Sstevel@tonic-gate break; 7607057Smarks if (error = aclent_perm_txt(dstr, aclp->a_perm)) 7610Sstevel@tonic-gate break; 7621420Smarks 7631420Smarks if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) || 7641420Smarks (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) || 7651420Smarks (aclp->a_type == DEF_GROUP))) { 7667057Smarks char id[ID_STR_MAX], *idstr; 7677057Smarks 7687057Smarks if (error = str_append(dstr, ":")) 7697057Smarks break; 7701420Smarks id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */ 7711420Smarks idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]); 7727057Smarks if (error = str_append(dstr, idstr)) 7737057Smarks break; 7741420Smarks } 7750Sstevel@tonic-gate if (i < aclcnt - 1) 7767057Smarks if (error = str_append(dstr, ",")) 7777057Smarks break; 7780Sstevel@tonic-gate } 7797057Smarks if (error) { 7807057Smarks if (dstr->d_aclexport) 7817057Smarks free(dstr->d_aclexport); 7827057Smarks } else { 7837057Smarks aclexport = dstr->d_aclexport; 7847057Smarks } 7850Sstevel@tonic-gate free(dstr); 7860Sstevel@tonic-gate return (aclexport); 7870Sstevel@tonic-gate } 7880Sstevel@tonic-gate 7891420Smarks char * 7901420Smarks acltotext(aclent_t *aclp, int aclcnt) 7910Sstevel@tonic-gate { 7921420Smarks return (aclent_acltotext(aclp, aclcnt, 0)); 7931420Smarks } 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate 796789Sahrens aclent_t * 797789Sahrens aclfromtext(char *aclstr, int *aclcnt) 798789Sahrens { 799789Sahrens acl_t *aclp; 800789Sahrens aclent_t *aclentp; 801789Sahrens int error; 802789Sahrens 8031420Smarks error = acl_fromtext(aclstr, &aclp); 804789Sahrens if (error) 805789Sahrens return (NULL); 806789Sahrens 807789Sahrens aclentp = aclp->acl_aclp; 808789Sahrens aclp->acl_aclp = NULL; 8091420Smarks *aclcnt = aclp->acl_cnt; 810789Sahrens 8111420Smarks acl_free(aclp); 812789Sahrens return (aclentp); 813789Sahrens } 814789Sahrens 815789Sahrens 8167057Smarks /* 8177680SMark.Shellenbaum@Sun.COM * Append string onto dynaclstr_t. 8187680SMark.Shellenbaum@Sun.COM * 8197680SMark.Shellenbaum@Sun.COM * Return 0 on success, 1 for failure. 8207057Smarks */ 8217057Smarks static int 8227057Smarks str_append(dynaclstr_t *dstr, char *newstr) 8230Sstevel@tonic-gate { 8247057Smarks size_t len = strlen(newstr); 8257057Smarks 8267057Smarks if ((len + dstr->d_pos) >= dstr->d_bufsize) { 8277057Smarks dstr->d_aclexport = realloc(dstr->d_aclexport, 8287057Smarks dstr->d_bufsize + len + 1); 8297057Smarks if (dstr->d_aclexport == NULL) 8307057Smarks return (1); 8317057Smarks dstr->d_bufsize += len; 8327057Smarks } 8337057Smarks (void) strcat(&dstr->d_aclexport[dstr->d_pos], newstr); 8347057Smarks dstr->d_pos += len; 8357057Smarks return (0); 8360Sstevel@tonic-gate } 8370Sstevel@tonic-gate 8387057Smarks static int 8397057Smarks aclent_perm_txt(dynaclstr_t *dstr, o_mode_t perm) 8400Sstevel@tonic-gate { 8417057Smarks char buf[4]; 8420Sstevel@tonic-gate 8437057Smarks if (perm & S_IROTH) 8447057Smarks buf[0] = 'r'; 8457057Smarks else 8467057Smarks buf[0] = '-'; 8477057Smarks if (perm & S_IWOTH) 8487057Smarks buf[1] = 'w'; 8497057Smarks else 8507057Smarks buf[1] = '-'; 8517057Smarks if (perm & S_IXOTH) 8527057Smarks buf[2] = 'x'; 8537057Smarks else 8547057Smarks buf[2] = '-'; 8557057Smarks buf[3] = '\0'; 8567057Smarks return (str_append(dstr, buf)); 8570Sstevel@tonic-gate } 858789Sahrens 859789Sahrens /* 8601420Smarks * ace_acltotext() convert each ace formatted acl to look like this: 861789Sahrens * 8621420Smarks * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,] 863789Sahrens * 864789Sahrens * The maximum length of entry_type is 5 ("group") 865789Sahrens * 8661420Smarks * The max length of a uid^gid^name entry (in theory) is 8, 8671420Smarks * however id could be a number so we therefore use ID_STR_MAX 868789Sahrens * 869789Sahrens * The length of a perms entry is 144 i.e read_data/write_data... 870789Sahrens * to each acl entry. 871789Sahrens * 8725331Samw * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access 8735331Samw * /failed_access 874789Sahrens * 875789Sahrens */ 876789Sahrens 877789Sahrens #define ACE_ENTRYTYPLEN 6 8785331Samw #define IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \ 8795331Samw "successful_access/failed_access/inherited" 8805331Samw #define IFLAGS_SIZE (sizeof (IFLAGS_STR) - 1) 8811420Smarks #define ACCESS_TYPE_SIZE 7 /* if unknown */ 882789Sahrens #define COLON_CNT 3 883789Sahrens #define PERMS_LEN 216 8845331Samw #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \ 8851420Smarks ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX) 886789Sahrens 887789Sahrens static char * 8881420Smarks ace_acltotext(acl_t *aceaclp, int flags) 889789Sahrens { 890789Sahrens ace_t *aclp = aceaclp->acl_aclp; 891789Sahrens int aclcnt = aceaclp->acl_cnt; 8927057Smarks int i; 8937057Smarks int error = 0; 8947057Smarks int isdir = (aceaclp->acl_flags & ACL_IS_DIR); 8957057Smarks dynaclstr_t *dstr; 8967680SMark.Shellenbaum@Sun.COM char *aclexport = NULL; 897789Sahrens 898789Sahrens if (aclp == NULL) 899789Sahrens return (NULL); 900789Sahrens 9017057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 9027057Smarks return (NULL); 9037057Smarks dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE; 9047057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 9057057Smarks free(dstr); 9067057Smarks return (NULL); 9077057Smarks } 9087057Smarks *dstr->d_aclexport = '\0'; 9097057Smarks dstr->d_pos = 0; 9107057Smarks 911789Sahrens for (i = 0; i < aclcnt; i++, aclp++) { 9121420Smarks 9137057Smarks if (error = ace_type_txt(dstr, aclp, flags)) 9147057Smarks break; 9157057Smarks if (error = ace_perm_txt(dstr, aclp->a_access_mask, 9167057Smarks aclp->a_flags, isdir, flags)) 9177057Smarks break; 9187057Smarks if (error = ace_inherit_txt(dstr, aclp->a_flags, flags)) 9197057Smarks break; 9207057Smarks if (error = ace_access_txt(dstr, aclp->a_type)) 9217057Smarks break; 922789Sahrens 9231420Smarks if ((flags & ACL_APPEND_ID) && 9241420Smarks (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) || 9251420Smarks ((aclp->a_flags & ACE_TYPE_FLAGS) == 9261420Smarks ACE_IDENTIFIER_GROUP))) { 9277057Smarks char id[ID_STR_MAX], *idstr; 928*8268SMark.Shellenbaum@Sun.COM char *rawsidp; 9297057Smarks 9307057Smarks if (error = str_append(dstr, ":")) 9317057Smarks break; 932*8268SMark.Shellenbaum@Sun.COM 933*8268SMark.Shellenbaum@Sun.COM rawsidp = NULL; 934*8268SMark.Shellenbaum@Sun.COM id[ID_STR_MAX -1] = '\0'; /* null terminate */ 935*8268SMark.Shellenbaum@Sun.COM if (aclp->a_who > MAXUID && (flags & ACL_SID_FMT)) { 936*8268SMark.Shellenbaum@Sun.COM 937*8268SMark.Shellenbaum@Sun.COM error = getsidname(aclp->a_who, 938*8268SMark.Shellenbaum@Sun.COM ((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ? 939*8268SMark.Shellenbaum@Sun.COM B_TRUE : B_FALSE, &idstr, 1); 940*8268SMark.Shellenbaum@Sun.COM if (error) 941*8268SMark.Shellenbaum@Sun.COM break; 942*8268SMark.Shellenbaum@Sun.COM rawsidp = idstr; 943*8268SMark.Shellenbaum@Sun.COM } else if (aclp->a_who > MAXUID && 944*8268SMark.Shellenbaum@Sun.COM !(flags & ACL_NORESOLVE)) { 945*8268SMark.Shellenbaum@Sun.COM idstr = lltostr(UID_NOBODY, 946*8268SMark.Shellenbaum@Sun.COM &id[ID_STR_MAX - 1]); 947*8268SMark.Shellenbaum@Sun.COM } else { 948*8268SMark.Shellenbaum@Sun.COM idstr = lltostr(aclp->a_who, 949*8268SMark.Shellenbaum@Sun.COM &id[ID_STR_MAX - 1]); 950*8268SMark.Shellenbaum@Sun.COM } 9517057Smarks if (error = str_append(dstr, idstr)) 9527057Smarks break; 953*8268SMark.Shellenbaum@Sun.COM if (rawsidp) 954*8268SMark.Shellenbaum@Sun.COM free(rawsidp); 955789Sahrens } 9561420Smarks if (i < aclcnt - 1) { 9577057Smarks if (error = str_append(dstr, ",")) 9587057Smarks break; 959789Sahrens } 960789Sahrens } 9617057Smarks if (error) { 9627057Smarks if (dstr->d_aclexport) 9637057Smarks free(dstr->d_aclexport); 9647057Smarks } else { 9657057Smarks aclexport = dstr->d_aclexport; 9667057Smarks } 9677057Smarks free(dstr); 968789Sahrens return (aclexport); 969789Sahrens } 970789Sahrens 9711420Smarks char * 9721420Smarks acl_totext(acl_t *aclp, int flags) 973789Sahrens { 9741420Smarks char *txtp; 975789Sahrens 976789Sahrens if (aclp == NULL) 977789Sahrens return (NULL); 978789Sahrens 979789Sahrens switch (aclp->acl_type) { 980789Sahrens case ACE_T: 9811420Smarks txtp = ace_acltotext(aclp, flags); 9821420Smarks break; 983789Sahrens case ACLENT_T: 9841420Smarks txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags); 9851420Smarks break; 986789Sahrens } 9871420Smarks 9881420Smarks return (txtp); 989789Sahrens } 990789Sahrens 991789Sahrens int 992789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp) 993789Sahrens { 9941420Smarks int error; 9951420Smarks char *buf; 9961420Smarks 9971420Smarks buf = malloc(strlen(acltextp) + 2); 9981420Smarks if (buf == NULL) 9991420Smarks return (EACL_MEM_ERROR); 10001420Smarks strcpy(buf, acltextp); 10011420Smarks strcat(buf, "\n"); 10021420Smarks yybuf = buf; 10031420Smarks yyreset(); 10041420Smarks error = yyparse(); 10051420Smarks free(buf); 10061420Smarks 10071420Smarks if (yyacl) { 10081420Smarks if (error == 0) 10091420Smarks *ret_aclp = yyacl; 10101420Smarks else { 10111420Smarks acl_free(yyacl); 10121420Smarks } 10131420Smarks yyacl = NULL; 10141420Smarks } 10151420Smarks return (error); 10161420Smarks } 10171420Smarks 10181420Smarks int 10191420Smarks acl_parse(const char *acltextp, acl_t **aclp) 10201420Smarks { 1021789Sahrens int error; 1022789Sahrens 10231420Smarks yyinteractive = 1; 10241420Smarks error = acl_fromtext(acltextp, aclp); 10251420Smarks yyinteractive = 0; 10261420Smarks return (error); 10271420Smarks } 10281420Smarks 10291420Smarks static void 10301420Smarks ace_compact_printacl(acl_t *aclp) 10311420Smarks { 10321420Smarks int cnt; 10331420Smarks ace_t *acep; 10347057Smarks dynaclstr_t *dstr; 10357057Smarks int len; 1036789Sahrens 10377057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 10387057Smarks return; 10397057Smarks dstr->d_bufsize = ACE_ENTRY_SIZE; 10407057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 10417057Smarks free(dstr); 10427057Smarks return; 10437057Smarks } 10447057Smarks *dstr->d_aclexport = '\0'; 10457057Smarks 10467057Smarks dstr->d_pos = 0; 10471420Smarks for (cnt = 0, acep = aclp->acl_aclp; 10481420Smarks cnt != aclp->acl_cnt; cnt++, acep++) { 10497057Smarks dstr->d_aclexport[0] = '\0'; 10507057Smarks dstr->d_pos = 0; 10517057Smarks 10527057Smarks if (ace_type_txt(dstr, acep, 0)) 10537057Smarks break; 10547057Smarks len = strlen(&dstr->d_aclexport[0]); 10557057Smarks if (ace_perm_txt(dstr, acep->a_access_mask, acep->a_flags, 10567057Smarks aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT)) 10577057Smarks break; 10587057Smarks if (ace_inherit_txt(dstr, acep->a_flags, ACL_COMPACT_FMT)) 10597057Smarks break; 10607057Smarks if (ace_access_txt(dstr, acep->a_type) == -1) 10617057Smarks break; 10627057Smarks (void) printf(" %20.*s%s\n", len, dstr->d_aclexport, 10637057Smarks &dstr->d_aclexport[len]); 10641420Smarks } 10657057Smarks 10667057Smarks if (dstr->d_aclexport) 10677057Smarks free(dstr->d_aclexport); 10687057Smarks free(dstr); 10691420Smarks } 1070789Sahrens 10711420Smarks static void 10721420Smarks ace_printacl(acl_t *aclp, int cols, int compact) 10731420Smarks { 10741420Smarks int slot = 0; 10751420Smarks char *token; 10761420Smarks char *acltext; 10771420Smarks 10781420Smarks if (compact) { 10791420Smarks ace_compact_printacl(aclp); 10801420Smarks return; 1081789Sahrens } 1082789Sahrens 10831420Smarks acltext = acl_totext(aclp, 0); 10841420Smarks 10851420Smarks if (acltext == NULL) 10861420Smarks return; 10871420Smarks 10881420Smarks token = strtok(acltext, ","); 10891420Smarks if (token == NULL) { 10901420Smarks free(acltext); 10911420Smarks return; 1092789Sahrens } 1093789Sahrens 10941420Smarks do { 10951420Smarks (void) printf(" %d:", slot++); 10961420Smarks split_line(token, cols - 5); 10971420Smarks } while (token = strtok(NULL, ",")); 10981420Smarks free(acltext); 10991420Smarks } 11001420Smarks 11011420Smarks /* 11021420Smarks * pretty print an ACL. 11031420Smarks * For aclent_t ACL's the format is 11041420Smarks * similar to the old format used by getfacl, 11051420Smarks * with the addition of adding a "slot" number 11061420Smarks * before each entry. 11071420Smarks * 11081420Smarks * for ace_t ACL's the cols variable will break up 11091420Smarks * the long lines into multiple lines and will also 11101420Smarks * print a "slot" number. 11111420Smarks */ 11121420Smarks void 11131420Smarks acl_printacl(acl_t *aclp, int cols, int compact) 11141420Smarks { 11151420Smarks 11161420Smarks switch (aclp->acl_type) { 11171420Smarks case ACLENT_T: 11181420Smarks aclent_printacl(aclp); 11191420Smarks break; 11201420Smarks case ACE_T: 11211420Smarks ace_printacl(aclp, cols, compact); 11221420Smarks break; 11231420Smarks } 11241420Smarks } 11251420Smarks 11261420Smarks typedef struct value_table { 11271420Smarks char p_letter; /* perm letter such as 'r' */ 11281420Smarks uint32_t p_value; /* value for perm when pletter found */ 11291420Smarks } value_table_t; 11301420Smarks 11311420Smarks /* 11325331Samw * The permission tables are laid out in positional order 11331420Smarks * a '-' character will indicate a permission at a given 11341420Smarks * position is not specified. The '-' is not part of the 11351420Smarks * table, but will be checked for in the permission computation 11361420Smarks * routine. 11371420Smarks */ 11385331Samw value_table_t ace_perm_table[] = { 11391420Smarks { 'r', ACE_READ_DATA}, 11401420Smarks { 'w', ACE_WRITE_DATA}, 11411420Smarks { 'x', ACE_EXECUTE}, 11421420Smarks { 'p', ACE_APPEND_DATA}, 11431420Smarks { 'd', ACE_DELETE}, 11441420Smarks { 'D', ACE_DELETE_CHILD}, 11451420Smarks { 'a', ACE_READ_ATTRIBUTES}, 11461420Smarks { 'A', ACE_WRITE_ATTRIBUTES}, 11471420Smarks { 'R', ACE_READ_NAMED_ATTRS}, 11481420Smarks { 'W', ACE_WRITE_NAMED_ATTRS}, 11491420Smarks { 'c', ACE_READ_ACL}, 11501420Smarks { 'C', ACE_WRITE_ACL}, 11511420Smarks { 'o', ACE_WRITE_OWNER}, 11521420Smarks { 's', ACE_SYNCHRONIZE} 11531420Smarks }; 11541420Smarks 11555331Samw #define ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t)) 11561420Smarks 11575331Samw value_table_t aclent_perm_table[] = { 11581420Smarks { 'r', S_IROTH}, 11591420Smarks { 'w', S_IWOTH}, 11601420Smarks { 'x', S_IXOTH} 11611420Smarks }; 11621420Smarks 11635331Samw #define ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t)) 11645331Samw 11655331Samw value_table_t inherit_table[] = { 11661420Smarks {'f', ACE_FILE_INHERIT_ACE}, 11671420Smarks {'d', ACE_DIRECTORY_INHERIT_ACE}, 11681420Smarks {'i', ACE_INHERIT_ONLY_ACE}, 11691420Smarks {'n', ACE_NO_PROPAGATE_INHERIT_ACE}, 11701420Smarks {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 11715331Samw {'F', ACE_FAILED_ACCESS_ACE_FLAG}, 11725331Samw {'I', ACE_INHERITED_ACE} 11731420Smarks }; 11741420Smarks 11755331Samw #define IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t)) 11766269Smarks #define IFLAG_COUNT_V1 6 /* Older version compatibility */ 11775331Samw 11781420Smarks /* 11791420Smarks * compute value from a permission table or inheritance table 11801420Smarks * based on string passed in. If positional is set then 11811420Smarks * string must match order in permtab, otherwise any order 11821420Smarks * is allowed. 11831420Smarks */ 11841420Smarks int 11851420Smarks compute_values(value_table_t *permtab, int count, 11861420Smarks char *permstr, int positional, uint32_t *mask) 11871420Smarks { 11881420Smarks uint32_t perm_val = 0; 11891420Smarks char *pstr; 11901420Smarks int i, found; 11911420Smarks 11921420Smarks if (count < 0) 11931420Smarks return (1); 11941420Smarks 11951420Smarks if (positional) { 11961420Smarks for (i = 0, pstr = permstr; i != count && pstr && 11971420Smarks *pstr; i++, pstr++) { 11981420Smarks if (*pstr == permtab[i].p_letter) { 11991420Smarks perm_val |= permtab[i].p_value; 12001420Smarks } else if (*pstr != '-') { 12011420Smarks return (1); 12021420Smarks } 1203789Sahrens } 12041420Smarks } else { /* random order single letters with no '-' */ 12051420Smarks for (pstr = permstr; pstr && *pstr; pstr++) { 12061420Smarks for (found = 0, i = 0; i != count; i++) { 12071420Smarks if (*pstr == permtab[i].p_letter) { 12081420Smarks perm_val |= permtab[i].p_value; 12091420Smarks found = 1; 12101420Smarks break; 12111420Smarks } 12121420Smarks } 12131420Smarks if (found == 0) 12141420Smarks return (1); 12151420Smarks } 1216789Sahrens } 1217789Sahrens 12181420Smarks *mask = perm_val; 12191420Smarks return (0); 12201420Smarks } 1221789Sahrens 12226269Smarks 12236269Smarks int 12246269Smarks ace_inherit_helper(char *str, uint32_t *imask, int table_length) 12256269Smarks { 12266269Smarks int rc = 0; 12276269Smarks 12286269Smarks if (strlen(str) == table_length) { 12296269Smarks /* 12306269Smarks * If the string == table_length then first check to see it's 12316269Smarks * in positional format. If that fails then see if it's in 12326269Smarks * non-positional format. 12336269Smarks */ 12346269Smarks if (compute_values(inherit_table, table_length, str, 12356269Smarks 1, imask) && compute_values(inherit_table, 12366269Smarks table_length, str, 0, imask)) { 12376269Smarks rc = 1; 12386269Smarks } 12396269Smarks } else { 12406269Smarks rc = compute_values(inherit_table, table_length, str, 0, imask); 12416269Smarks } 12426269Smarks 12436269Smarks return (rc ? EACL_INHERIT_ERROR : 0); 12446269Smarks } 12456269Smarks 12461420Smarks /* 12471420Smarks * compute value for inheritance flags. 12481420Smarks */ 12491420Smarks int 12501420Smarks compute_ace_inherit(char *str, uint32_t *imask) 12511420Smarks { 12526269Smarks int rc = 0; 1253789Sahrens 12546269Smarks rc = ace_inherit_helper(str, imask, IFLAG_COUNT); 12556269Smarks 12566269Smarks if (rc && strlen(str) != IFLAG_COUNT) { 12571420Smarks 12586269Smarks /* is it an old formatted inherit string? */ 12596269Smarks rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1); 12606269Smarks } 12611420Smarks 12626269Smarks return (rc); 1263789Sahrens } 12641420Smarks 12651420Smarks 12661420Smarks /* 12671420Smarks * compute value for ACE permissions. 12681420Smarks */ 12691420Smarks int 12701420Smarks compute_ace_perms(char *str, uint32_t *mask) 12711420Smarks { 12721420Smarks int positional = 0; 12731420Smarks int error; 12741420Smarks 12751420Smarks if (strlen(str) == ACE_PERM_COUNT) 12761420Smarks positional = 1; 12771420Smarks 12781420Smarks error = compute_values(ace_perm_table, ACE_PERM_COUNT, 12791420Smarks str, positional, mask); 12801420Smarks 12811420Smarks if (error && positional) { 12821420Smarks /* 12831420Smarks * If positional was set, then make sure permissions 12841420Smarks * aren't actually valid in non positional case where 12851420Smarks * all permissions are specified, just in random order. 12861420Smarks */ 12871420Smarks error = compute_values(ace_perm_table, 12881420Smarks ACE_PERM_COUNT, str, 0, mask); 12891420Smarks } 12901420Smarks if (error) 12911420Smarks error = EACL_PERM_MASK_ERROR; 12921420Smarks 12931420Smarks return (error); 12941420Smarks } 12951420Smarks 12961420Smarks 12971420Smarks 12981420Smarks /* 12991420Smarks * compute values for aclent permissions. 13001420Smarks */ 13011420Smarks int 13021420Smarks compute_aclent_perms(char *str, o_mode_t *mask) 13031420Smarks { 13041420Smarks int error; 13051420Smarks uint32_t pmask; 13061420Smarks 13071420Smarks if (strlen(str) != ACLENT_PERM_COUNT) 13081420Smarks return (EACL_PERM_MASK_ERROR); 13091420Smarks 13101420Smarks *mask = 0; 13111420Smarks error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT, 13121420Smarks str, 1, &pmask); 13131420Smarks if (error == 0) { 13141420Smarks *mask = (o_mode_t)pmask; 13151420Smarks } else 13161420Smarks error = EACL_PERM_MASK_ERROR; 13171420Smarks return (error); 13181420Smarks } 13191420Smarks 13201420Smarks /* 13211420Smarks * determine ACE permissions. 13221420Smarks */ 13231420Smarks int 13241420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask) 13251420Smarks { 13261420Smarks int error; 13271420Smarks 13281420Smarks if (aclperm->perm_style == PERM_TYPE_EMPTY) { 13291420Smarks *mask = 0; 13301420Smarks return (0); 13311420Smarks } 13321420Smarks 13331420Smarks if (aclperm->perm_style == PERM_TYPE_ACE) { 13341420Smarks *mask = aclperm->perm_val; 13351420Smarks return (0); 13361420Smarks } 13371420Smarks 13381420Smarks error = compute_ace_perms(aclperm->perm_str, mask); 13391420Smarks if (error) { 13401567Smarks acl_error(dgettext(TEXT_DOMAIN, 13411567Smarks "Invalid permission(s) '%s' specified\n"), 13421420Smarks aclperm->perm_str); 13431420Smarks return (EACL_PERM_MASK_ERROR); 13441420Smarks } 13451420Smarks 13461420Smarks return (0); 13471420Smarks } 1348