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 1187057Smarks static char * 1197057Smarks prsidname(uid_t who, boolean_t user, char **sidp, int 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; 1257057Smarks int error = 1; 1267057Smarks int len; 1277057Smarks char *domain; 1287057Smarks char *name; 1297057Smarks 1307057Smarks if (noresolve) { 1317057Smarks len = snprintf(NULL, 0, "%u", who); 1327057Smarks *sidp = malloc(len + 1); 1337057Smarks (void) snprintf(*sidp, len + 1, "%u", who); 1347057Smarks return (*sidp); 1357057Smarks } 1367057Smarks 1377057Smarks /* 1387057Smarks * First try and get windows name 1397057Smarks */ 1407057Smarks 1417057Smarks if (user) 142*7369SJulian.Pullen@Sun.COM error = idmap_getwinnamebyuid(who, IDMAP_REQ_FLG_USE_CACHE, 143*7369SJulian.Pullen@Sun.COM &name, &domain); 1447057Smarks else 145*7369SJulian.Pullen@Sun.COM error = idmap_getwinnamebygid(who, IDMAP_REQ_FLG_USE_CACHE, 146*7369SJulian.Pullen@Sun.COM &name, &domain); 1477057Smarks 1487057Smarks if (error) { 1497057Smarks if (idmap_init(&idmap_hdl) == 0 && 1507057Smarks idmap_get_create(idmap_hdl, &get_hdl) == 0) { 1517057Smarks if (user) 1527057Smarks error = idmap_get_sidbyuid(get_hdl, who, 153*7369SJulian.Pullen@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &domain, &rid, 154*7369SJulian.Pullen@Sun.COM &status); 1557057Smarks else 1567057Smarks error = idmap_get_sidbygid(get_hdl, who, 157*7369SJulian.Pullen@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &domain, &rid, 158*7369SJulian.Pullen@Sun.COM &status); 1597057Smarks if (error == 0) 1607057Smarks error = idmap_get_mappings(get_hdl); 1617057Smarks } 1627057Smarks if (error == 0) { 1637057Smarks len = snprintf(NULL, 0, "%s-%d", domain, rid); 1647057Smarks *sidp = malloc(len + 1); 1657057Smarks (void) snprintf(*sidp, len + 1, "%s-%d", domain, rid); 1667057Smarks } else { 1677057Smarks *sidp = NULL; 1687057Smarks } 1697057Smarks if (get_hdl) 1707057Smarks idmap_get_destroy(get_hdl); 1717057Smarks if (idmap_hdl) 1727057Smarks (void) idmap_fini(idmap_hdl); 1737057Smarks } else { 1747057Smarks int len; 1757057Smarks len = snprintf(NULL, 0, "%s@%d", name, domain); 1767057Smarks *sidp = malloc(len + 1); 1777057Smarks (void) snprintf(*sidp, len + 1, "%s@%s", name, domain); 1787057Smarks } 1797057Smarks return (*sidp); 1807057Smarks } 1817057Smarks 1821420Smarks static void 1831420Smarks aclent_printacl(acl_t *aclp) 184789Sahrens { 1851420Smarks aclent_t *tp; 1861420Smarks int aclcnt; 1871420Smarks int mask; 1881420Smarks int slot = 0; 1891420Smarks char perm[4]; 1901535Smarks char uidp[ID_STR_MAX]; 1911535Smarks char gidp[ID_STR_MAX]; 1921420Smarks 1931420Smarks /* display ACL: assume it is sorted. */ 1941420Smarks aclcnt = aclp->acl_cnt; 1951420Smarks for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) { 1961420Smarks if (tp->a_type == CLASS_OBJ) 1971420Smarks mask = tp->a_perm; 1981420Smarks } 1991420Smarks aclcnt = aclp->acl_cnt; 2001420Smarks for (tp = aclp->acl_aclp; aclcnt--; tp++) { 2011420Smarks (void) printf(" %d:", slot++); 2021420Smarks switch (tp->a_type) { 2031420Smarks case USER: 2041420Smarks aclent_perms(tp->a_perm, perm); 2051420Smarks (void) printf("user:%s:%s\t\t", 2061535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 2071420Smarks aclent_perms((tp->a_perm & mask), perm); 2081420Smarks (void) printf("#effective:%s\n", perm); 2091420Smarks break; 2101420Smarks case USER_OBJ: 2111420Smarks /* no need to display uid */ 2121420Smarks aclent_perms(tp->a_perm, perm); 2131420Smarks (void) printf("user::%s\n", perm); 2141420Smarks break; 2151420Smarks case GROUP: 2161420Smarks aclent_perms(tp->a_perm, perm); 2171420Smarks (void) printf("group:%s:%s\t\t", 2181535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 2191420Smarks aclent_perms(tp->a_perm & mask, perm); 2201420Smarks (void) printf("#effective:%s\n", perm); 2211420Smarks break; 2221420Smarks case GROUP_OBJ: 2231420Smarks aclent_perms(tp->a_perm, perm); 2241420Smarks (void) printf("group::%s\t\t", perm); 2251420Smarks aclent_perms(tp->a_perm & mask, perm); 2261420Smarks (void) printf("#effective:%s\n", perm); 2271420Smarks break; 2281420Smarks case CLASS_OBJ: 2291420Smarks aclent_perms(tp->a_perm, perm); 2301420Smarks (void) printf("mask:%s\n", perm); 2311420Smarks break; 2321420Smarks case OTHER_OBJ: 2331420Smarks aclent_perms(tp->a_perm, perm); 2341420Smarks (void) printf("other:%s\n", perm); 2351420Smarks break; 2361420Smarks case DEF_USER: 2371420Smarks aclent_perms(tp->a_perm, perm); 2381420Smarks (void) printf("default:user:%s:%s\n", 2391535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 2401420Smarks break; 2411420Smarks case DEF_USER_OBJ: 2421420Smarks aclent_perms(tp->a_perm, perm); 2431420Smarks (void) printf("default:user::%s\n", perm); 2441420Smarks break; 2451420Smarks case DEF_GROUP: 2461420Smarks aclent_perms(tp->a_perm, perm); 2471420Smarks (void) printf("default:group:%s:%s\n", 2481535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 2491420Smarks break; 2501420Smarks case DEF_GROUP_OBJ: 2511420Smarks aclent_perms(tp->a_perm, perm); 2521420Smarks (void) printf("default:group::%s\n", perm); 2531420Smarks break; 2541420Smarks case DEF_CLASS_OBJ: 2551420Smarks aclent_perms(tp->a_perm, perm); 2561420Smarks (void) printf("default:mask:%s\n", perm); 2571420Smarks break; 2581420Smarks case DEF_OTHER_OBJ: 2591420Smarks aclent_perms(tp->a_perm, perm); 2601420Smarks (void) printf("default:other:%s\n", perm); 2611420Smarks break; 2621420Smarks default: 2631420Smarks (void) fprintf(stderr, 2641567Smarks dgettext(TEXT_DOMAIN, "unrecognized entry\n")); 2651420Smarks break; 2661420Smarks } 2671420Smarks } 2681420Smarks } 2691420Smarks 2701420Smarks static void 2711420Smarks split_line(char *str, int cols) 2721420Smarks { 2731420Smarks char *ptr; 2741420Smarks int len; 2751420Smarks int i; 2761420Smarks int last_split; 2771420Smarks char *pad = ""; 2781420Smarks int pad_len; 2791420Smarks 2801420Smarks len = strlen(str); 2811420Smarks ptr = str; 2821420Smarks pad_len = 0; 2831420Smarks 2841420Smarks ptr = str; 2851420Smarks last_split = 0; 2861420Smarks for (i = 0; i != len; i++) { 2871420Smarks if ((i + pad_len + 4) >= cols) { 2881420Smarks (void) printf("%s%.*s\n", pad, last_split, ptr); 2891420Smarks ptr = &ptr[last_split]; 2901420Smarks len = strlen(ptr); 2911420Smarks i = 0; 2921420Smarks pad_len = 4; 2931420Smarks pad = " "; 2941420Smarks } else { 2951420Smarks if (ptr[i] == '/' || ptr[i] == ':') { 2961420Smarks last_split = i; 2971420Smarks } 2981420Smarks } 2991420Smarks } 3001420Smarks if (i == len) { 3011420Smarks (void) printf("%s%s\n", pad, ptr); 3021420Smarks } 3031420Smarks } 3041420Smarks 3057057Smarks /* 3067057Smarks * compute entry type string, such as user:joe, group:staff,... 3077057Smarks */ 3087057Smarks static int 3097057Smarks aclent_type_txt(dynaclstr_t *dstr, aclent_t *aclp, int flags) 3101420Smarks { 3117057Smarks char idp[ID_STR_MAX]; 3127057Smarks int error; 3137057Smarks 3147057Smarks switch (aclp->a_type) { 3157057Smarks case DEF_USER_OBJ: 3167057Smarks case USER_OBJ: 3177057Smarks if (aclp->a_type == USER_OBJ) 3187057Smarks error = str_append(dstr, "user::"); 3197057Smarks else 3207057Smarks error = str_append(dstr, "defaultuser::"); 3217057Smarks break; 3227057Smarks 3237057Smarks case DEF_USER: 3247057Smarks case USER: 3257057Smarks if (aclp->a_type == USER) 3267057Smarks error = str_append(dstr, "user:"); 3277057Smarks else 3287057Smarks error = str_append(dstr, "defaultuser:"); 3297057Smarks if (error) 3307057Smarks break; 3317057Smarks error = str_append(dstr, pruname(aclp->a_id, idp, 3327057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 3337057Smarks if (error == 0) 3347057Smarks error = str_append(dstr, ":"); 3357057Smarks break; 3367057Smarks 3377057Smarks case DEF_GROUP_OBJ: 3387057Smarks case GROUP_OBJ: 3397057Smarks if (aclp->a_type == GROUP_OBJ) 3407057Smarks error = str_append(dstr, "group::"); 3417057Smarks else 3427057Smarks error = str_append(dstr, "defaultgroup::"); 3437057Smarks break; 3441420Smarks 3457057Smarks case DEF_GROUP: 3467057Smarks case GROUP: 3477057Smarks if (aclp->a_type == GROUP) 3487057Smarks error = str_append(dstr, "group:"); 3497057Smarks else 3507057Smarks error = str_append(dstr, "defaultgroup:"); 3517057Smarks if (error) 3527057Smarks break; 3537057Smarks error = str_append(dstr, prgname(aclp->a_id, idp, 3547057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 3557057Smarks if (error == 0) 3567057Smarks error = str_append(dstr, ":"); 3577057Smarks break; 3587057Smarks 3597057Smarks case DEF_CLASS_OBJ: 3607057Smarks case CLASS_OBJ: 3617057Smarks if (aclp->a_type == CLASS_OBJ) 3627057Smarks error = str_append(dstr, "mask:"); 3637057Smarks else 3647057Smarks error = str_append(dstr, "defaultmask:"); 3657057Smarks break; 3661420Smarks 3677057Smarks case DEF_OTHER_OBJ: 3687057Smarks case OTHER_OBJ: 3697057Smarks if (aclp->a_type == OTHER_OBJ) 3707057Smarks error = str_append(dstr, "other:"); 3717057Smarks else 3727057Smarks error = str_append(dstr, "defaultother:"); 3737057Smarks break; 3747057Smarks 3757057Smarks default: 3767057Smarks error = 1; 3777057Smarks break; 3787057Smarks } 3797057Smarks 3807057Smarks return (error); 3817057Smarks } 3827057Smarks 3837057Smarks /* 3847057Smarks * compute entry type string such as, owner@:, user:joe, group:staff,... 3857057Smarks */ 3867057Smarks static int 3877057Smarks ace_type_txt(dynaclstr_t *dynstr, ace_t *acep, int flags) 3887057Smarks { 3897057Smarks char idp[ID_STR_MAX]; 3907057Smarks int error; 3917057Smarks char *sidp = NULL; 3921420Smarks 3931420Smarks switch (acep->a_flags & ACE_TYPE_FLAGS) { 3941420Smarks case ACE_OWNER: 3957057Smarks error = str_append(dynstr, OWNERAT_TXT); 3961420Smarks break; 3971420Smarks 3981420Smarks case ACE_GROUP|ACE_IDENTIFIER_GROUP: 3997057Smarks error = str_append(dynstr, GROUPAT_TXT); 4001420Smarks break; 4011420Smarks 4021420Smarks case ACE_IDENTIFIER_GROUP: 4037057Smarks if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) { 4047057Smarks if (error = str_append(dynstr, 4057057Smarks GROUPSID_TXT)) 4067057Smarks break; 4077057Smarks error = str_append(dynstr, prsidname(acep->a_who, 4087057Smarks B_FALSE, &sidp, flags & ACL_NORESOLVE)); 4097057Smarks } else { 4107057Smarks if (error = str_append(dynstr, GROUP_TXT)) 4117057Smarks break; 4127057Smarks error = str_append(dynstr, prgname(acep->a_who, idp, 4137057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 4147057Smarks } 4157057Smarks if (error == 0) 4167057Smarks error = str_append(dynstr, ":"); 4171420Smarks break; 4181420Smarks 4191420Smarks case ACE_EVERYONE: 4207057Smarks error = str_append(dynstr, EVERYONEAT_TXT); 4211420Smarks break; 4221420Smarks 4231420Smarks case 0: 4247057Smarks if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) { 4257057Smarks if (error = str_append(dynstr, USERSID_TXT)) 4267057Smarks break; 4277057Smarks error = str_append(dynstr, prsidname(acep->a_who, 4287057Smarks B_TRUE, &sidp, flags & ACL_NORESOLVE)); 4297057Smarks } else { 4307057Smarks if (error = str_append(dynstr, USER_TXT)) 4317057Smarks break; 4327057Smarks error = str_append(dynstr, pruname(acep->a_who, idp, 4337057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 4347057Smarks } 4357057Smarks if (error == 0) 4367057Smarks error = str_append(dynstr, ":"); 4377057Smarks break; 4387057Smarks default: 4397057Smarks error = 0; 4401420Smarks break; 4411420Smarks } 4421420Smarks 4437057Smarks if (sidp) 4447057Smarks free(sidp); 4457057Smarks return (error); 4461420Smarks } 4471420Smarks 4487057Smarks /* 4497057Smarks * compute string of permissions, such as read_data/write_data or 4507057Smarks * rwxp,... 4517057Smarks * The format depends on the flags field which indicates whether the compact 4527057Smarks * or verbose format should be used. 4537057Smarks */ 4547057Smarks static int 4557057Smarks ace_perm_txt(dynaclstr_t *dstr, uint32_t mask, 4561420Smarks uint32_t iflags, int isdir, int flags) 4571420Smarks { 4587057Smarks int error = 0; 4591420Smarks 4601420Smarks if (flags & ACL_COMPACT_FMT) { 4617057Smarks char buf[16]; 462789Sahrens 4631420Smarks if (mask & ACE_READ_DATA) 4641420Smarks buf[0] = 'r'; 4651420Smarks else 4661420Smarks buf[0] = '-'; 4671420Smarks if (mask & ACE_WRITE_DATA) 4681420Smarks buf[1] = 'w'; 4691420Smarks else 4701420Smarks buf[1] = '-'; 4711420Smarks if (mask & ACE_EXECUTE) 4721420Smarks buf[2] = 'x'; 4731420Smarks else 4741420Smarks buf[2] = '-'; 4751420Smarks if (mask & ACE_APPEND_DATA) 4761420Smarks buf[3] = 'p'; 4771420Smarks else 4781420Smarks buf[3] = '-'; 4791420Smarks if (mask & ACE_DELETE) 4801420Smarks buf[4] = 'd'; 4811420Smarks else 4821420Smarks buf[4] = '-'; 4831420Smarks if (mask & ACE_DELETE_CHILD) 4841420Smarks buf[5] = 'D'; 4851420Smarks else 4861420Smarks buf[5] = '-'; 4871420Smarks if (mask & ACE_READ_ATTRIBUTES) 4881420Smarks buf[6] = 'a'; 4891420Smarks else 4901420Smarks buf[6] = '-'; 4911420Smarks if (mask & ACE_WRITE_ATTRIBUTES) 4921420Smarks buf[7] = 'A'; 4931420Smarks else 4941420Smarks buf[7] = '-'; 4951420Smarks if (mask & ACE_READ_NAMED_ATTRS) 4961420Smarks buf[8] = 'R'; 4971420Smarks else 4981420Smarks buf[8] = '-'; 4991420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) 5001420Smarks buf[9] = 'W'; 5011420Smarks else 5021420Smarks buf[9] = '-'; 5031420Smarks if (mask & ACE_READ_ACL) 5041420Smarks buf[10] = 'c'; 5051420Smarks else 5061420Smarks buf[10] = '-'; 5071420Smarks if (mask & ACE_WRITE_ACL) 5081420Smarks buf[11] = 'C'; 5091420Smarks else 5101420Smarks buf[11] = '-'; 5111420Smarks if (mask & ACE_WRITE_OWNER) 5121420Smarks buf[12] = 'o'; 5131420Smarks else 5141420Smarks buf[12] = '-'; 5151420Smarks if (mask & ACE_SYNCHRONIZE) 5161420Smarks buf[13] = 's'; 5171420Smarks else 5181420Smarks buf[13] = '-'; 5197057Smarks buf[14] = ':'; 5207057Smarks buf[15] = '\0'; 5217057Smarks error = str_append(dstr, buf); 5221420Smarks } else { 5231420Smarks /* 5241420Smarks * If ACE is a directory, but inheritance indicates its 5251420Smarks * for a file then print permissions for file rather than 5261420Smarks * dir. 5271420Smarks */ 5281420Smarks if (isdir) { 5291420Smarks if (mask & ACE_LIST_DIRECTORY) { 5301420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5317057Smarks error = str_append(dstr, 5327057Smarks READ_DATA_TXT); 5331420Smarks } else { 5347057Smarks error = 5357057Smarks str_append(dstr, READ_DIR_TXT); 5361420Smarks } 5371420Smarks } 5387057Smarks if (error == 0 && (mask & ACE_ADD_FILE)) { 5391420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5407057Smarks error = 5417057Smarks str_append(dstr, WRITE_DATA_TXT); 5421420Smarks } else { 5437057Smarks error = 5447057Smarks str_append(dstr, ADD_FILE_TXT); 5451420Smarks } 5461420Smarks } 5477057Smarks if (error == 0 && (mask & ACE_ADD_SUBDIRECTORY)) { 5481420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5497057Smarks error = str_append(dstr, 5507057Smarks APPEND_DATA_TXT); 5511420Smarks } else { 5527057Smarks error = str_append(dstr, 5537057Smarks ADD_DIR_TXT); 5541420Smarks } 5551420Smarks } 5561420Smarks } else { 5571420Smarks if (mask & ACE_READ_DATA) { 5587057Smarks error = str_append(dstr, READ_DATA_TXT); 5591420Smarks } 5607057Smarks if (error == 0 && (mask & ACE_WRITE_DATA)) { 5617057Smarks error = str_append(dstr, WRITE_DATA_TXT); 5621420Smarks } 5637057Smarks if (error == 0 && (mask & ACE_APPEND_DATA)) { 5647057Smarks error = str_append(dstr, APPEND_DATA_TXT); 5651420Smarks } 5661420Smarks } 5677057Smarks if (error == 0 && (mask & ACE_READ_NAMED_ATTRS)) { 5687057Smarks error = str_append(dstr, READ_XATTR_TXT); 5691420Smarks } 5707057Smarks if (error == 0 && (mask & ACE_WRITE_NAMED_ATTRS)) { 5717057Smarks error = str_append(dstr, WRITE_XATTR_TXT); 5721420Smarks } 5737057Smarks if (error == 0 && (mask & ACE_EXECUTE)) { 5747057Smarks error = str_append(dstr, EXECUTE_TXT); 5751420Smarks } 5767057Smarks if (error == 0 && (mask & ACE_DELETE_CHILD)) { 5777057Smarks error = str_append(dstr, DELETE_CHILD_TXT); 5781420Smarks } 5797057Smarks if (error == 0 && (mask & ACE_READ_ATTRIBUTES)) { 5807057Smarks error = str_append(dstr, READ_ATTRIBUTES_TXT); 5811420Smarks } 5827057Smarks if (error == 0 && (mask & ACE_WRITE_ATTRIBUTES)) { 5837057Smarks error = str_append(dstr, WRITE_ATTRIBUTES_TXT); 5841420Smarks } 5857057Smarks if (error == 0 && (mask & ACE_DELETE)) { 5867057Smarks error = str_append(dstr, DELETE_TXT); 5871420Smarks } 5887057Smarks if (error == 0 && (mask & ACE_READ_ACL)) { 5897057Smarks error = str_append(dstr, READ_ACL_TXT); 5901420Smarks } 5917057Smarks if (error == 0 && (mask & ACE_WRITE_ACL)) { 5927057Smarks error = str_append(dstr, WRITE_ACL_TXT); 5931420Smarks } 5947057Smarks if (error == 0 && (mask & ACE_WRITE_OWNER)) { 5957057Smarks error = str_append(dstr, WRITE_OWNER_TXT); 5961420Smarks } 5977057Smarks if (error == 0 && (mask & ACE_SYNCHRONIZE)) { 5987057Smarks error = str_append(dstr, SYNCHRONIZE_TXT); 5991420Smarks } 6007057Smarks if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') { 6017057Smarks dstr->d_aclexport[--dstr->d_pos] = '\0'; 6027057Smarks } 6037057Smarks if (error == 0) 6047057Smarks error = str_append(dstr, ":"); 6051420Smarks } 6067057Smarks return (error); 6071420Smarks } 6081420Smarks 6097057Smarks /* 6107057Smarks * compute string of access type, such as allow, deny, ... 6117057Smarks */ 6127057Smarks static int 6137057Smarks ace_access_txt(dynaclstr_t *dstr, int type) 6141420Smarks { 6157057Smarks int error; 6161420Smarks 6177057Smarks if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) 6187057Smarks error = str_append(dstr, ALLOW_TXT); 6197057Smarks else if (type == ACE_ACCESS_DENIED_ACE_TYPE) 6207057Smarks error = str_append(dstr, DENY_TXT); 6217057Smarks else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) 6227057Smarks error = str_append(dstr, AUDIT_TXT); 6237057Smarks else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) 6247057Smarks error = str_append(dstr, ALARM_TXT); 6257057Smarks else 6267057Smarks error = str_append(dstr, UNKNOWN_TXT); 6271420Smarks 6287057Smarks return (error); 6291420Smarks } 6301420Smarks 6317057Smarks static int 6327057Smarks ace_inherit_txt(dynaclstr_t *dstr, uint32_t iflags, int flags) 6331420Smarks { 6347057Smarks int error = 0; 635789Sahrens 6361420Smarks if (flags & ACL_COMPACT_FMT) { 6377057Smarks char buf[9]; 6387057Smarks 6391420Smarks if (iflags & ACE_FILE_INHERIT_ACE) 6401420Smarks buf[0] = 'f'; 6411420Smarks else 6421420Smarks buf[0] = '-'; 6431420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) 6441420Smarks buf[1] = 'd'; 6451420Smarks else 6461420Smarks buf[1] = '-'; 6471420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) 6481420Smarks buf[2] = 'i'; 6491420Smarks else 6501420Smarks buf[2] = '-'; 6511420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) 6521420Smarks buf[3] = 'n'; 6531420Smarks else 6541420Smarks buf[3] = '-'; 6551420Smarks if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 6561420Smarks buf[4] = 'S'; 6571420Smarks else 6581420Smarks buf[4] = '-'; 6591420Smarks if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) 6601420Smarks buf[5] = 'F'; 6611420Smarks else 6621420Smarks buf[5] = '-'; 6635331Samw if (iflags & ACE_INHERITED_ACE) 6645331Samw buf[6] = 'I'; 6655331Samw else 6665331Samw buf[6] = '-'; 6677057Smarks buf[7] = ':'; 6687057Smarks buf[8] = '\0'; 6697057Smarks error = str_append(dstr, buf); 6701420Smarks } else { 6711420Smarks if (iflags & ACE_FILE_INHERIT_ACE) { 6727057Smarks error = str_append(dstr, FILE_INHERIT_TXT); 6731420Smarks } 6747057Smarks if (error == 0 && (iflags & ACE_DIRECTORY_INHERIT_ACE)) { 6757057Smarks error = str_append(dstr, DIR_INHERIT_TXT); 6761420Smarks } 6777057Smarks if (error == 0 && (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) { 6787057Smarks error = str_append(dstr, NO_PROPAGATE_TXT); 6791420Smarks } 6807057Smarks if (error == 0 && (iflags & ACE_INHERIT_ONLY_ACE)) { 6817057Smarks error = str_append(dstr, INHERIT_ONLY_TXT); 6821420Smarks } 6837057Smarks if (error == 0 && (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)) { 6847057Smarks error = str_append(dstr, SUCCESSFUL_ACCESS_TXT); 6855331Samw } 6867057Smarks if (error == 0 && (iflags & ACE_FAILED_ACCESS_ACE_FLAG)) { 6877057Smarks error = str_append(dstr, FAILED_ACCESS_TXT); 6885331Samw } 6897057Smarks if (error == 0 && (iflags & ACE_INHERITED_ACE)) { 6907057Smarks error = str_append(dstr, INHERITED_ACE_TXT); 6915331Samw } 6927057Smarks if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') { 6937057Smarks dstr->d_aclexport[--dstr->d_pos] = '\0'; 6947057Smarks error = str_append(dstr, ":"); 6957057Smarks } 6961420Smarks } 6971420Smarks 6987057Smarks return (error); 699789Sahrens } 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate /* 7020Sstevel@tonic-gate * Convert internal acl representation to external representation. 7030Sstevel@tonic-gate * 7040Sstevel@tonic-gate * The length of a non-owning user name or non-owning group name ie entries 7050Sstevel@tonic-gate * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We 7060Sstevel@tonic-gate * thus check the length of these entries, and if greater than LOGNAME_MAX, 7070Sstevel@tonic-gate * we realloc() via increase_length(). 7080Sstevel@tonic-gate * 7090Sstevel@tonic-gate * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always 7100Sstevel@tonic-gate * adhered to. 7110Sstevel@tonic-gate */ 7121420Smarks 7131420Smarks /* 7141420Smarks * acltotext() converts each ACL entry to look like this: 7151420Smarks * 7161420Smarks * entry_type:uid^gid^name:perms[:id] 7171420Smarks * 7181420Smarks * The maximum length of entry_type is 14 ("defaultgroup::" and 7191420Smarks * "defaultother::") hence ENTRYTYPELEN is set to 14. 7201420Smarks * 7211420Smarks * The max length of a uid^gid^name entry (in theory) is 8, hence we use, 7221420Smarks * however the ID could be a number so we therefore use ID_STR_MAX 7231420Smarks * 7241420Smarks * The length of a perms entry is 4 to allow for the comma appended to each 7251420Smarks * to each acl entry. Hence PERMS is set to 4. 7261420Smarks */ 7271420Smarks 7281420Smarks #define ENTRYTYPELEN 14 7291420Smarks #define PERMS 4 7301420Smarks #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX) 7311420Smarks 7320Sstevel@tonic-gate char * 7331420Smarks aclent_acltotext(aclent_t *aclp, int aclcnt, int flags) 7340Sstevel@tonic-gate { 7357057Smarks dynaclstr_t *dstr; 7360Sstevel@tonic-gate char *aclexport; 7377057Smarks int i; 7387057Smarks int error = 0; 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate if (aclp == NULL) 7410Sstevel@tonic-gate return (NULL); 7427057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 7430Sstevel@tonic-gate return (NULL); 7447057Smarks dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE; 7457057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 7460Sstevel@tonic-gate free(dstr); 7470Sstevel@tonic-gate return (NULL); 7480Sstevel@tonic-gate } 7497057Smarks *dstr->d_aclexport = '\0'; 7507057Smarks dstr->d_pos = 0; 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate for (i = 0; i < aclcnt; i++, aclp++) { 7537057Smarks if (error = aclent_type_txt(dstr, aclp, flags)) 7540Sstevel@tonic-gate break; 7557057Smarks if (error = aclent_perm_txt(dstr, aclp->a_perm)) 7560Sstevel@tonic-gate break; 7571420Smarks 7581420Smarks if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) || 7591420Smarks (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) || 7601420Smarks (aclp->a_type == DEF_GROUP))) { 7617057Smarks char id[ID_STR_MAX], *idstr; 7627057Smarks 7637057Smarks if (error = str_append(dstr, ":")) 7647057Smarks break; 7651420Smarks id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */ 7661420Smarks idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]); 7677057Smarks if (error = str_append(dstr, idstr)) 7687057Smarks break; 7691420Smarks } 7700Sstevel@tonic-gate if (i < aclcnt - 1) 7717057Smarks if (error = str_append(dstr, ",")) 7727057Smarks break; 7730Sstevel@tonic-gate } 7747057Smarks if (error) { 7757057Smarks if (dstr->d_aclexport) 7767057Smarks free(dstr->d_aclexport); 7777057Smarks } else { 7787057Smarks aclexport = dstr->d_aclexport; 7797057Smarks } 7800Sstevel@tonic-gate free(dstr); 7810Sstevel@tonic-gate return (aclexport); 7820Sstevel@tonic-gate } 7830Sstevel@tonic-gate 7841420Smarks char * 7851420Smarks acltotext(aclent_t *aclp, int aclcnt) 7860Sstevel@tonic-gate { 7871420Smarks return (aclent_acltotext(aclp, aclcnt, 0)); 7881420Smarks } 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate 791789Sahrens aclent_t * 792789Sahrens aclfromtext(char *aclstr, int *aclcnt) 793789Sahrens { 794789Sahrens acl_t *aclp; 795789Sahrens aclent_t *aclentp; 796789Sahrens int error; 797789Sahrens 7981420Smarks error = acl_fromtext(aclstr, &aclp); 799789Sahrens if (error) 800789Sahrens return (NULL); 801789Sahrens 802789Sahrens aclentp = aclp->acl_aclp; 803789Sahrens aclp->acl_aclp = NULL; 8041420Smarks *aclcnt = aclp->acl_cnt; 805789Sahrens 8061420Smarks acl_free(aclp); 807789Sahrens return (aclentp); 808789Sahrens } 809789Sahrens 810789Sahrens 8117057Smarks /* 8127057Smarks * returns a character position index of the start of the newly 8137057Smarks * appended string. Returns -1 if operation couldn't be completed. 8147057Smarks */ 8157057Smarks static int 8167057Smarks str_append(dynaclstr_t *dstr, char *newstr) 8170Sstevel@tonic-gate { 8187057Smarks size_t len = strlen(newstr); 8197057Smarks 8207057Smarks if ((len + dstr->d_pos) >= dstr->d_bufsize) { 8217057Smarks dstr->d_aclexport = realloc(dstr->d_aclexport, 8227057Smarks dstr->d_bufsize + len + 1); 8237057Smarks if (dstr->d_aclexport == NULL) 8247057Smarks return (1); 8257057Smarks dstr->d_bufsize += len; 8267057Smarks } 8277057Smarks (void) strcat(&dstr->d_aclexport[dstr->d_pos], newstr); 8287057Smarks dstr->d_pos += len; 8297057Smarks return (0); 8300Sstevel@tonic-gate } 8310Sstevel@tonic-gate 8327057Smarks static int 8337057Smarks aclent_perm_txt(dynaclstr_t *dstr, o_mode_t perm) 8340Sstevel@tonic-gate { 8357057Smarks char buf[4]; 8360Sstevel@tonic-gate 8377057Smarks if (perm & S_IROTH) 8387057Smarks buf[0] = 'r'; 8397057Smarks else 8407057Smarks buf[0] = '-'; 8417057Smarks if (perm & S_IWOTH) 8427057Smarks buf[1] = 'w'; 8437057Smarks else 8447057Smarks buf[1] = '-'; 8457057Smarks if (perm & S_IXOTH) 8467057Smarks buf[2] = 'x'; 8477057Smarks else 8487057Smarks buf[2] = '-'; 8497057Smarks buf[3] = '\0'; 8507057Smarks return (str_append(dstr, buf)); 8510Sstevel@tonic-gate } 852789Sahrens 853789Sahrens /* 8541420Smarks * ace_acltotext() convert each ace formatted acl to look like this: 855789Sahrens * 8561420Smarks * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,] 857789Sahrens * 858789Sahrens * The maximum length of entry_type is 5 ("group") 859789Sahrens * 8601420Smarks * The max length of a uid^gid^name entry (in theory) is 8, 8611420Smarks * however id could be a number so we therefore use ID_STR_MAX 862789Sahrens * 863789Sahrens * The length of a perms entry is 144 i.e read_data/write_data... 864789Sahrens * to each acl entry. 865789Sahrens * 8665331Samw * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access 8675331Samw * /failed_access 868789Sahrens * 869789Sahrens */ 870789Sahrens 871789Sahrens #define ACE_ENTRYTYPLEN 6 8725331Samw #define IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \ 8735331Samw "successful_access/failed_access/inherited" 8745331Samw #define IFLAGS_SIZE (sizeof (IFLAGS_STR) - 1) 8751420Smarks #define ACCESS_TYPE_SIZE 7 /* if unknown */ 876789Sahrens #define COLON_CNT 3 877789Sahrens #define PERMS_LEN 216 8785331Samw #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \ 8791420Smarks ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX) 880789Sahrens 881789Sahrens static char * 8821420Smarks ace_acltotext(acl_t *aceaclp, int flags) 883789Sahrens { 884789Sahrens ace_t *aclp = aceaclp->acl_aclp; 885789Sahrens int aclcnt = aceaclp->acl_cnt; 8867057Smarks int i; 8877057Smarks int error = 0; 8887057Smarks int isdir = (aceaclp->acl_flags & ACL_IS_DIR); 8897057Smarks dynaclstr_t *dstr; 890789Sahrens char *aclexport; 891789Sahrens 892789Sahrens if (aclp == NULL) 893789Sahrens return (NULL); 894789Sahrens 8957057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 8967057Smarks return (NULL); 8977057Smarks dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE; 8987057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 8997057Smarks free(dstr); 9007057Smarks return (NULL); 9017057Smarks } 9027057Smarks *dstr->d_aclexport = '\0'; 9037057Smarks dstr->d_pos = 0; 9047057Smarks 905789Sahrens for (i = 0; i < aclcnt; i++, aclp++) { 9061420Smarks 9077057Smarks if (error = ace_type_txt(dstr, aclp, flags)) 9087057Smarks break; 9097057Smarks if (error = ace_perm_txt(dstr, aclp->a_access_mask, 9107057Smarks aclp->a_flags, isdir, flags)) 9117057Smarks break; 9127057Smarks if (error = ace_inherit_txt(dstr, aclp->a_flags, flags)) 9137057Smarks break; 9147057Smarks if (error = ace_access_txt(dstr, aclp->a_type)) 9157057Smarks break; 916789Sahrens 9171420Smarks if ((flags & ACL_APPEND_ID) && 9181420Smarks (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) || 9191420Smarks ((aclp->a_flags & ACE_TYPE_FLAGS) == 9201420Smarks ACE_IDENTIFIER_GROUP))) { 9217057Smarks char id[ID_STR_MAX], *idstr; 9227057Smarks 9237057Smarks if (error = str_append(dstr, ":")) 9247057Smarks break; 9251420Smarks id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */ 9267057Smarks idstr = lltostr((aclp->a_who > MAXUID && 9277057Smarks !(flags & ACL_NORESOLVE)) ? UID_NOBODY : 9287057Smarks aclp->a_who, &id[ID_STR_MAX - 1]); 9297057Smarks if (error = str_append(dstr, idstr)) 9307057Smarks break; 931789Sahrens } 9321420Smarks if (i < aclcnt - 1) { 9337057Smarks if (error = str_append(dstr, ",")) 9347057Smarks break; 935789Sahrens } 936789Sahrens } 9377057Smarks if (error) { 9387057Smarks if (dstr->d_aclexport) 9397057Smarks free(dstr->d_aclexport); 9407057Smarks } else { 9417057Smarks aclexport = dstr->d_aclexport; 9427057Smarks } 9437057Smarks free(dstr); 944789Sahrens return (aclexport); 945789Sahrens } 946789Sahrens 9471420Smarks char * 9481420Smarks acl_totext(acl_t *aclp, int flags) 949789Sahrens { 9501420Smarks char *txtp; 951789Sahrens 952789Sahrens if (aclp == NULL) 953789Sahrens return (NULL); 954789Sahrens 955789Sahrens switch (aclp->acl_type) { 956789Sahrens case ACE_T: 9571420Smarks txtp = ace_acltotext(aclp, flags); 9581420Smarks break; 959789Sahrens case ACLENT_T: 9601420Smarks txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags); 9611420Smarks break; 962789Sahrens } 9631420Smarks 9641420Smarks return (txtp); 965789Sahrens } 966789Sahrens 967789Sahrens int 968789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp) 969789Sahrens { 9701420Smarks int error; 9711420Smarks char *buf; 9721420Smarks 9731420Smarks buf = malloc(strlen(acltextp) + 2); 9741420Smarks if (buf == NULL) 9751420Smarks return (EACL_MEM_ERROR); 9761420Smarks strcpy(buf, acltextp); 9771420Smarks strcat(buf, "\n"); 9781420Smarks yybuf = buf; 9791420Smarks yyreset(); 9801420Smarks error = yyparse(); 9811420Smarks free(buf); 9821420Smarks 9831420Smarks if (yyacl) { 9841420Smarks if (error == 0) 9851420Smarks *ret_aclp = yyacl; 9861420Smarks else { 9871420Smarks acl_free(yyacl); 9881420Smarks } 9891420Smarks yyacl = NULL; 9901420Smarks } 9911420Smarks return (error); 9921420Smarks } 9931420Smarks 9941420Smarks int 9951420Smarks acl_parse(const char *acltextp, acl_t **aclp) 9961420Smarks { 997789Sahrens int error; 998789Sahrens 9991420Smarks yyinteractive = 1; 10001420Smarks error = acl_fromtext(acltextp, aclp); 10011420Smarks yyinteractive = 0; 10021420Smarks return (error); 10031420Smarks } 10041420Smarks 10051420Smarks static void 10061420Smarks ace_compact_printacl(acl_t *aclp) 10071420Smarks { 10081420Smarks int cnt; 10091420Smarks ace_t *acep; 10107057Smarks dynaclstr_t *dstr; 10117057Smarks int len; 1012789Sahrens 10137057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 10147057Smarks return; 10157057Smarks dstr->d_bufsize = ACE_ENTRY_SIZE; 10167057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 10177057Smarks free(dstr); 10187057Smarks return; 10197057Smarks } 10207057Smarks *dstr->d_aclexport = '\0'; 10217057Smarks 10227057Smarks dstr->d_pos = 0; 10231420Smarks for (cnt = 0, acep = aclp->acl_aclp; 10241420Smarks cnt != aclp->acl_cnt; cnt++, acep++) { 10257057Smarks dstr->d_aclexport[0] = '\0'; 10267057Smarks dstr->d_pos = 0; 10277057Smarks 10287057Smarks if (ace_type_txt(dstr, acep, 0)) 10297057Smarks break; 10307057Smarks len = strlen(&dstr->d_aclexport[0]); 10317057Smarks if (ace_perm_txt(dstr, acep->a_access_mask, acep->a_flags, 10327057Smarks aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT)) 10337057Smarks break; 10347057Smarks if (ace_inherit_txt(dstr, acep->a_flags, ACL_COMPACT_FMT)) 10357057Smarks break; 10367057Smarks if (ace_access_txt(dstr, acep->a_type) == -1) 10377057Smarks break; 10387057Smarks (void) printf(" %20.*s%s\n", len, dstr->d_aclexport, 10397057Smarks &dstr->d_aclexport[len]); 10401420Smarks } 10417057Smarks 10427057Smarks if (dstr->d_aclexport) 10437057Smarks free(dstr->d_aclexport); 10447057Smarks free(dstr); 10451420Smarks } 1046789Sahrens 10471420Smarks static void 10481420Smarks ace_printacl(acl_t *aclp, int cols, int compact) 10491420Smarks { 10501420Smarks int slot = 0; 10511420Smarks char *token; 10521420Smarks char *acltext; 10531420Smarks 10541420Smarks if (compact) { 10551420Smarks ace_compact_printacl(aclp); 10561420Smarks return; 1057789Sahrens } 1058789Sahrens 10591420Smarks acltext = acl_totext(aclp, 0); 10601420Smarks 10611420Smarks if (acltext == NULL) 10621420Smarks return; 10631420Smarks 10641420Smarks token = strtok(acltext, ","); 10651420Smarks if (token == NULL) { 10661420Smarks free(acltext); 10671420Smarks return; 1068789Sahrens } 1069789Sahrens 10701420Smarks do { 10711420Smarks (void) printf(" %d:", slot++); 10721420Smarks split_line(token, cols - 5); 10731420Smarks } while (token = strtok(NULL, ",")); 10741420Smarks free(acltext); 10751420Smarks } 10761420Smarks 10771420Smarks /* 10781420Smarks * pretty print an ACL. 10791420Smarks * For aclent_t ACL's the format is 10801420Smarks * similar to the old format used by getfacl, 10811420Smarks * with the addition of adding a "slot" number 10821420Smarks * before each entry. 10831420Smarks * 10841420Smarks * for ace_t ACL's the cols variable will break up 10851420Smarks * the long lines into multiple lines and will also 10861420Smarks * print a "slot" number. 10871420Smarks */ 10881420Smarks void 10891420Smarks acl_printacl(acl_t *aclp, int cols, int compact) 10901420Smarks { 10911420Smarks 10921420Smarks switch (aclp->acl_type) { 10931420Smarks case ACLENT_T: 10941420Smarks aclent_printacl(aclp); 10951420Smarks break; 10961420Smarks case ACE_T: 10971420Smarks ace_printacl(aclp, cols, compact); 10981420Smarks break; 10991420Smarks } 11001420Smarks } 11011420Smarks 11021420Smarks typedef struct value_table { 11031420Smarks char p_letter; /* perm letter such as 'r' */ 11041420Smarks uint32_t p_value; /* value for perm when pletter found */ 11051420Smarks } value_table_t; 11061420Smarks 11071420Smarks /* 11085331Samw * The permission tables are laid out in positional order 11091420Smarks * a '-' character will indicate a permission at a given 11101420Smarks * position is not specified. The '-' is not part of the 11111420Smarks * table, but will be checked for in the permission computation 11121420Smarks * routine. 11131420Smarks */ 11145331Samw value_table_t ace_perm_table[] = { 11151420Smarks { 'r', ACE_READ_DATA}, 11161420Smarks { 'w', ACE_WRITE_DATA}, 11171420Smarks { 'x', ACE_EXECUTE}, 11181420Smarks { 'p', ACE_APPEND_DATA}, 11191420Smarks { 'd', ACE_DELETE}, 11201420Smarks { 'D', ACE_DELETE_CHILD}, 11211420Smarks { 'a', ACE_READ_ATTRIBUTES}, 11221420Smarks { 'A', ACE_WRITE_ATTRIBUTES}, 11231420Smarks { 'R', ACE_READ_NAMED_ATTRS}, 11241420Smarks { 'W', ACE_WRITE_NAMED_ATTRS}, 11251420Smarks { 'c', ACE_READ_ACL}, 11261420Smarks { 'C', ACE_WRITE_ACL}, 11271420Smarks { 'o', ACE_WRITE_OWNER}, 11281420Smarks { 's', ACE_SYNCHRONIZE} 11291420Smarks }; 11301420Smarks 11315331Samw #define ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t)) 11321420Smarks 11335331Samw value_table_t aclent_perm_table[] = { 11341420Smarks { 'r', S_IROTH}, 11351420Smarks { 'w', S_IWOTH}, 11361420Smarks { 'x', S_IXOTH} 11371420Smarks }; 11381420Smarks 11395331Samw #define ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t)) 11405331Samw 11415331Samw value_table_t inherit_table[] = { 11421420Smarks {'f', ACE_FILE_INHERIT_ACE}, 11431420Smarks {'d', ACE_DIRECTORY_INHERIT_ACE}, 11441420Smarks {'i', ACE_INHERIT_ONLY_ACE}, 11451420Smarks {'n', ACE_NO_PROPAGATE_INHERIT_ACE}, 11461420Smarks {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 11475331Samw {'F', ACE_FAILED_ACCESS_ACE_FLAG}, 11485331Samw {'I', ACE_INHERITED_ACE} 11491420Smarks }; 11501420Smarks 11515331Samw #define IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t)) 11526269Smarks #define IFLAG_COUNT_V1 6 /* Older version compatibility */ 11535331Samw 11541420Smarks /* 11551420Smarks * compute value from a permission table or inheritance table 11561420Smarks * based on string passed in. If positional is set then 11571420Smarks * string must match order in permtab, otherwise any order 11581420Smarks * is allowed. 11591420Smarks */ 11601420Smarks int 11611420Smarks compute_values(value_table_t *permtab, int count, 11621420Smarks char *permstr, int positional, uint32_t *mask) 11631420Smarks { 11641420Smarks uint32_t perm_val = 0; 11651420Smarks char *pstr; 11661420Smarks int i, found; 11671420Smarks 11681420Smarks if (count < 0) 11691420Smarks return (1); 11701420Smarks 11711420Smarks if (positional) { 11721420Smarks for (i = 0, pstr = permstr; i != count && pstr && 11731420Smarks *pstr; i++, pstr++) { 11741420Smarks if (*pstr == permtab[i].p_letter) { 11751420Smarks perm_val |= permtab[i].p_value; 11761420Smarks } else if (*pstr != '-') { 11771420Smarks return (1); 11781420Smarks } 1179789Sahrens } 11801420Smarks } else { /* random order single letters with no '-' */ 11811420Smarks for (pstr = permstr; pstr && *pstr; pstr++) { 11821420Smarks for (found = 0, i = 0; i != count; i++) { 11831420Smarks if (*pstr == permtab[i].p_letter) { 11841420Smarks perm_val |= permtab[i].p_value; 11851420Smarks found = 1; 11861420Smarks break; 11871420Smarks } 11881420Smarks } 11891420Smarks if (found == 0) 11901420Smarks return (1); 11911420Smarks } 1192789Sahrens } 1193789Sahrens 11941420Smarks *mask = perm_val; 11951420Smarks return (0); 11961420Smarks } 1197789Sahrens 11986269Smarks 11996269Smarks int 12006269Smarks ace_inherit_helper(char *str, uint32_t *imask, int table_length) 12016269Smarks { 12026269Smarks int rc = 0; 12036269Smarks 12046269Smarks if (strlen(str) == table_length) { 12056269Smarks /* 12066269Smarks * If the string == table_length then first check to see it's 12076269Smarks * in positional format. If that fails then see if it's in 12086269Smarks * non-positional format. 12096269Smarks */ 12106269Smarks if (compute_values(inherit_table, table_length, str, 12116269Smarks 1, imask) && compute_values(inherit_table, 12126269Smarks table_length, str, 0, imask)) { 12136269Smarks rc = 1; 12146269Smarks } 12156269Smarks } else { 12166269Smarks rc = compute_values(inherit_table, table_length, str, 0, imask); 12176269Smarks } 12186269Smarks 12196269Smarks return (rc ? EACL_INHERIT_ERROR : 0); 12206269Smarks } 12216269Smarks 12221420Smarks /* 12231420Smarks * compute value for inheritance flags. 12241420Smarks */ 12251420Smarks int 12261420Smarks compute_ace_inherit(char *str, uint32_t *imask) 12271420Smarks { 12286269Smarks int rc = 0; 1229789Sahrens 12306269Smarks rc = ace_inherit_helper(str, imask, IFLAG_COUNT); 12316269Smarks 12326269Smarks if (rc && strlen(str) != IFLAG_COUNT) { 12331420Smarks 12346269Smarks /* is it an old formatted inherit string? */ 12356269Smarks rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1); 12366269Smarks } 12371420Smarks 12386269Smarks return (rc); 1239789Sahrens } 12401420Smarks 12411420Smarks 12421420Smarks /* 12431420Smarks * compute value for ACE permissions. 12441420Smarks */ 12451420Smarks int 12461420Smarks compute_ace_perms(char *str, uint32_t *mask) 12471420Smarks { 12481420Smarks int positional = 0; 12491420Smarks int error; 12501420Smarks 12511420Smarks if (strlen(str) == ACE_PERM_COUNT) 12521420Smarks positional = 1; 12531420Smarks 12541420Smarks error = compute_values(ace_perm_table, ACE_PERM_COUNT, 12551420Smarks str, positional, mask); 12561420Smarks 12571420Smarks if (error && positional) { 12581420Smarks /* 12591420Smarks * If positional was set, then make sure permissions 12601420Smarks * aren't actually valid in non positional case where 12611420Smarks * all permissions are specified, just in random order. 12621420Smarks */ 12631420Smarks error = compute_values(ace_perm_table, 12641420Smarks ACE_PERM_COUNT, str, 0, mask); 12651420Smarks } 12661420Smarks if (error) 12671420Smarks error = EACL_PERM_MASK_ERROR; 12681420Smarks 12691420Smarks return (error); 12701420Smarks } 12711420Smarks 12721420Smarks 12731420Smarks 12741420Smarks /* 12751420Smarks * compute values for aclent permissions. 12761420Smarks */ 12771420Smarks int 12781420Smarks compute_aclent_perms(char *str, o_mode_t *mask) 12791420Smarks { 12801420Smarks int error; 12811420Smarks uint32_t pmask; 12821420Smarks 12831420Smarks if (strlen(str) != ACLENT_PERM_COUNT) 12841420Smarks return (EACL_PERM_MASK_ERROR); 12851420Smarks 12861420Smarks *mask = 0; 12871420Smarks error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT, 12881420Smarks str, 1, &pmask); 12891420Smarks if (error == 0) { 12901420Smarks *mask = (o_mode_t)pmask; 12911420Smarks } else 12921420Smarks error = EACL_PERM_MASK_ERROR; 12931420Smarks return (error); 12941420Smarks } 12951420Smarks 12961420Smarks /* 12971420Smarks * determine ACE permissions. 12981420Smarks */ 12991420Smarks int 13001420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask) 13011420Smarks { 13021420Smarks int error; 13031420Smarks 13041420Smarks if (aclperm->perm_style == PERM_TYPE_EMPTY) { 13051420Smarks *mask = 0; 13061420Smarks return (0); 13071420Smarks } 13081420Smarks 13091420Smarks if (aclperm->perm_style == PERM_TYPE_ACE) { 13101420Smarks *mask = aclperm->perm_val; 13111420Smarks return (0); 13121420Smarks } 13131420Smarks 13141420Smarks error = compute_ace_perms(aclperm->perm_str, mask); 13151420Smarks if (error) { 13161567Smarks acl_error(dgettext(TEXT_DOMAIN, 13171567Smarks "Invalid permission(s) '%s' specified\n"), 13181420Smarks aclperm->perm_str); 13191420Smarks return (EACL_PERM_MASK_ERROR); 13201420Smarks } 13211420Smarks 13221420Smarks return (0); 13231420Smarks } 1324