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 /* 2211605SGowtham.Thommandra@Sun.COM * Copyright 2010 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> 40*11963SAfshin.Ardakani@Sun.COM #include <synch.h> 411420Smarks 421420Smarks #define ID_STR_MAX 20 /* digits in LONG_MAX */ 43789Sahrens 441420Smarks #define APPENDED_ID_MAX ID_STR_MAX + 1 /* id + colon */ 451420Smarks /* 461420Smarks * yyinteractive controls whether yyparse should print out 471420Smarks * error messages to stderr, and whether or not id's should be 481420Smarks * allowed from acl_fromtext(). 491420Smarks */ 501420Smarks int yyinteractive; 511420Smarks acl_t *yyacl; 521420Smarks char *yybuf; 53*11963SAfshin.Ardakani@Sun.COM mutex_t yymutex; 54789Sahrens 55789Sahrens extern acl_t *acl_alloc(enum acl_type); 560Sstevel@tonic-gate 577057Smarks /* 587057Smarks * dynamic string that will increase in size on an 597057Smarks * as needed basis. 607057Smarks */ 617057Smarks typedef struct dynaclstr { 627057Smarks size_t d_bufsize; /* current size of aclexport */ 637057Smarks char *d_aclexport; 647057Smarks int d_pos; 657057Smarks } dynaclstr_t; 66922Shm123892 677057Smarks static int str_append(dynaclstr_t *, char *); 687057Smarks static int aclent_perm_txt(dynaclstr_t *, o_mode_t); 690Sstevel@tonic-gate 701420Smarks static void 711420Smarks aclent_perms(int perm, char *txt_perms) 721420Smarks { 731420Smarks if (perm & S_IROTH) 741420Smarks txt_perms[0] = 'r'; 751420Smarks else 761420Smarks txt_perms[0] = '-'; 771420Smarks if (perm & S_IWOTH) 781420Smarks txt_perms[1] = 'w'; 791420Smarks else 801420Smarks txt_perms[1] = '-'; 811420Smarks if (perm & S_IXOTH) 821420Smarks txt_perms[2] = 'x'; 831420Smarks else 841420Smarks txt_perms[2] = '-'; 851420Smarks txt_perms[3] = '\0'; 861420Smarks } 871420Smarks 881420Smarks static char * 891535Smarks pruname(uid_t uid, char *uidp, size_t buflen, int noresolve) 901420Smarks { 911515Sgjelinek struct passwd *passwdp = NULL; 921420Smarks 931515Sgjelinek if (noresolve == 0) 941515Sgjelinek passwdp = getpwuid(uid); 951420Smarks if (passwdp == (struct passwd *)NULL) { 961420Smarks /* could not get passwd information: display uid instead */ 974321Scasper (void) snprintf(uidp, buflen, "%u", uid); 981535Smarks } else { 991535Smarks (void) strlcpy(uidp, passwdp->pw_name, buflen); 1001535Smarks } 1011535Smarks return (uidp); 1021420Smarks } 1031420Smarks 1041420Smarks static char * 1051535Smarks prgname(gid_t gid, char *gidp, size_t buflen, int noresolve) 1061420Smarks { 1071515Sgjelinek struct group *groupp = NULL; 1081420Smarks 1091515Sgjelinek if (noresolve == 0) 1101515Sgjelinek groupp = getgrgid(gid); 1111420Smarks if (groupp == (struct group *)NULL) { 1121420Smarks /* could not get group information: display gid instead */ 1134321Scasper (void) snprintf(gidp, buflen, "%u", gid); 1141535Smarks } else { 1151535Smarks (void) strlcpy(gidp, groupp->gr_name, buflen); 1161535Smarks } 1171535Smarks return (gidp); 1181420Smarks } 1197057Smarks 1207680SMark.Shellenbaum@Sun.COM static int 1217680SMark.Shellenbaum@Sun.COM getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve) 1227057Smarks { 1237057Smarks idmap_handle_t *idmap_hdl = NULL; 1247057Smarks idmap_get_handle_t *get_hdl = NULL; 1257057Smarks idmap_stat status; 1267057Smarks idmap_rid_t rid; 1277680SMark.Shellenbaum@Sun.COM int error = IDMAP_ERR_NORESULT; 1287057Smarks int len; 12911605SGowtham.Thommandra@Sun.COM char *domain = NULL; 13011605SGowtham.Thommandra@Sun.COM char *name = NULL; 1317057Smarks 1327680SMark.Shellenbaum@Sun.COM *sidp = NULL; 1337057Smarks 1347057Smarks /* 1357057Smarks * First try and get windows name 1367057Smarks */ 1377057Smarks 1387680SMark.Shellenbaum@Sun.COM if (!noresolve) { 1397680SMark.Shellenbaum@Sun.COM if (user) 1407680SMark.Shellenbaum@Sun.COM error = idmap_getwinnamebyuid(who, 1417680SMark.Shellenbaum@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &name, &domain); 1427680SMark.Shellenbaum@Sun.COM else 1437680SMark.Shellenbaum@Sun.COM error = idmap_getwinnamebygid(who, 1447680SMark.Shellenbaum@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &name, &domain); 1457680SMark.Shellenbaum@Sun.COM } 1467680SMark.Shellenbaum@Sun.COM if (error != IDMAP_SUCCESS) { 1477680SMark.Shellenbaum@Sun.COM if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS && 1487680SMark.Shellenbaum@Sun.COM idmap_get_create(idmap_hdl, &get_hdl) == IDMAP_SUCCESS) { 1497057Smarks if (user) 1507057Smarks error = idmap_get_sidbyuid(get_hdl, who, 1517369SJulian.Pullen@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &domain, &rid, 1527369SJulian.Pullen@Sun.COM &status); 1537057Smarks else 1547057Smarks error = idmap_get_sidbygid(get_hdl, who, 1557369SJulian.Pullen@Sun.COM IDMAP_REQ_FLG_USE_CACHE, &domain, &rid, 1567369SJulian.Pullen@Sun.COM &status); 1577680SMark.Shellenbaum@Sun.COM if (error == IDMAP_SUCCESS && 1587680SMark.Shellenbaum@Sun.COM idmap_get_mappings(get_hdl) == 0) { 1597680SMark.Shellenbaum@Sun.COM if (status == IDMAP_SUCCESS) { 1607680SMark.Shellenbaum@Sun.COM len = snprintf(NULL, 0, 1617680SMark.Shellenbaum@Sun.COM "%s-%d", domain, rid); 1627680SMark.Shellenbaum@Sun.COM if (*sidp = malloc(len + 1)) { 1637680SMark.Shellenbaum@Sun.COM (void) snprintf(*sidp, len + 1, 1647680SMark.Shellenbaum@Sun.COM "%s-%d", domain, rid); 1657680SMark.Shellenbaum@Sun.COM } 1667680SMark.Shellenbaum@Sun.COM } 1677680SMark.Shellenbaum@Sun.COM } 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; 1757680SMark.Shellenbaum@Sun.COM 1768268SMark.Shellenbaum@Sun.COM len = snprintf(NULL, 0, "%s@%s", name, domain); 1777680SMark.Shellenbaum@Sun.COM if (*sidp = malloc(len + 1)) 1787680SMark.Shellenbaum@Sun.COM (void) snprintf(*sidp, len + 1, "%s@%s", name, domain); 17911605SGowtham.Thommandra@Sun.COM } 18011605SGowtham.Thommandra@Sun.COM 18111605SGowtham.Thommandra@Sun.COM if (name) 1828268SMark.Shellenbaum@Sun.COM free(name); 18311605SGowtham.Thommandra@Sun.COM if (domain) 1848268SMark.Shellenbaum@Sun.COM free(domain); 1857680SMark.Shellenbaum@Sun.COM return (*sidp ? 0 : 1); 1867057Smarks } 1877057Smarks 1881420Smarks static void 1891420Smarks aclent_printacl(acl_t *aclp) 190789Sahrens { 1911420Smarks aclent_t *tp; 1921420Smarks int aclcnt; 1931420Smarks int mask; 1941420Smarks int slot = 0; 1951420Smarks char perm[4]; 1961535Smarks char uidp[ID_STR_MAX]; 1971535Smarks char gidp[ID_STR_MAX]; 1981420Smarks 1991420Smarks /* display ACL: assume it is sorted. */ 2001420Smarks aclcnt = aclp->acl_cnt; 2011420Smarks for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) { 2021420Smarks if (tp->a_type == CLASS_OBJ) 2031420Smarks mask = tp->a_perm; 2041420Smarks } 2051420Smarks aclcnt = aclp->acl_cnt; 2061420Smarks for (tp = aclp->acl_aclp; aclcnt--; tp++) { 2071420Smarks (void) printf(" %d:", slot++); 2081420Smarks switch (tp->a_type) { 2091420Smarks case USER: 2101420Smarks aclent_perms(tp->a_perm, perm); 2111420Smarks (void) printf("user:%s:%s\t\t", 2121535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 2131420Smarks aclent_perms((tp->a_perm & mask), perm); 2141420Smarks (void) printf("#effective:%s\n", perm); 2151420Smarks break; 2161420Smarks case USER_OBJ: 2171420Smarks /* no need to display uid */ 2181420Smarks aclent_perms(tp->a_perm, perm); 2191420Smarks (void) printf("user::%s\n", perm); 2201420Smarks break; 2211420Smarks case GROUP: 2221420Smarks aclent_perms(tp->a_perm, perm); 2231420Smarks (void) printf("group:%s:%s\t\t", 2241535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 2251420Smarks aclent_perms(tp->a_perm & mask, perm); 2261420Smarks (void) printf("#effective:%s\n", perm); 2271420Smarks break; 2281420Smarks case GROUP_OBJ: 2291420Smarks aclent_perms(tp->a_perm, perm); 2301420Smarks (void) printf("group::%s\t\t", perm); 2311420Smarks aclent_perms(tp->a_perm & mask, perm); 2321420Smarks (void) printf("#effective:%s\n", perm); 2331420Smarks break; 2341420Smarks case CLASS_OBJ: 2351420Smarks aclent_perms(tp->a_perm, perm); 2361420Smarks (void) printf("mask:%s\n", perm); 2371420Smarks break; 2381420Smarks case OTHER_OBJ: 2391420Smarks aclent_perms(tp->a_perm, perm); 2401420Smarks (void) printf("other:%s\n", perm); 2411420Smarks break; 2421420Smarks case DEF_USER: 2431420Smarks aclent_perms(tp->a_perm, perm); 2441420Smarks (void) printf("default:user:%s:%s\n", 2451535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 2461420Smarks break; 2471420Smarks case DEF_USER_OBJ: 2481420Smarks aclent_perms(tp->a_perm, perm); 2491420Smarks (void) printf("default:user::%s\n", perm); 2501420Smarks break; 2511420Smarks case DEF_GROUP: 2521420Smarks aclent_perms(tp->a_perm, perm); 2531420Smarks (void) printf("default:group:%s:%s\n", 2541535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 2551420Smarks break; 2561420Smarks case DEF_GROUP_OBJ: 2571420Smarks aclent_perms(tp->a_perm, perm); 2581420Smarks (void) printf("default:group::%s\n", perm); 2591420Smarks break; 2601420Smarks case DEF_CLASS_OBJ: 2611420Smarks aclent_perms(tp->a_perm, perm); 2621420Smarks (void) printf("default:mask:%s\n", perm); 2631420Smarks break; 2641420Smarks case DEF_OTHER_OBJ: 2651420Smarks aclent_perms(tp->a_perm, perm); 2661420Smarks (void) printf("default:other:%s\n", perm); 2671420Smarks break; 2681420Smarks default: 2691420Smarks (void) fprintf(stderr, 2701567Smarks dgettext(TEXT_DOMAIN, "unrecognized entry\n")); 2711420Smarks break; 2721420Smarks } 2731420Smarks } 2741420Smarks } 2751420Smarks 2761420Smarks static void 2771420Smarks split_line(char *str, int cols) 2781420Smarks { 2791420Smarks char *ptr; 2801420Smarks int len; 2811420Smarks int i; 2821420Smarks int last_split; 2831420Smarks char *pad = ""; 2841420Smarks int pad_len; 2851420Smarks 2861420Smarks len = strlen(str); 2871420Smarks ptr = str; 2881420Smarks pad_len = 0; 2891420Smarks 2901420Smarks ptr = str; 2911420Smarks last_split = 0; 2921420Smarks for (i = 0; i != len; i++) { 2931420Smarks if ((i + pad_len + 4) >= cols) { 2941420Smarks (void) printf("%s%.*s\n", pad, last_split, ptr); 2951420Smarks ptr = &ptr[last_split]; 2961420Smarks len = strlen(ptr); 2971420Smarks i = 0; 2981420Smarks pad_len = 4; 2991420Smarks pad = " "; 3001420Smarks } else { 3011420Smarks if (ptr[i] == '/' || ptr[i] == ':') { 3021420Smarks last_split = i; 3031420Smarks } 3041420Smarks } 3051420Smarks } 3061420Smarks if (i == len) { 3071420Smarks (void) printf("%s%s\n", pad, ptr); 3081420Smarks } 3091420Smarks } 3101420Smarks 3117057Smarks /* 3127057Smarks * compute entry type string, such as user:joe, group:staff,... 3137057Smarks */ 3147057Smarks static int 3157057Smarks aclent_type_txt(dynaclstr_t *dstr, aclent_t *aclp, int flags) 3161420Smarks { 3177057Smarks char idp[ID_STR_MAX]; 3187057Smarks int error; 3197057Smarks 3207057Smarks switch (aclp->a_type) { 3217057Smarks case DEF_USER_OBJ: 3227057Smarks case USER_OBJ: 3237057Smarks if (aclp->a_type == USER_OBJ) 3247057Smarks error = str_append(dstr, "user::"); 3257057Smarks else 3267057Smarks error = str_append(dstr, "defaultuser::"); 3277057Smarks break; 3287057Smarks 3297057Smarks case DEF_USER: 3307057Smarks case USER: 3317057Smarks if (aclp->a_type == USER) 3327057Smarks error = str_append(dstr, "user:"); 3337057Smarks else 3347057Smarks error = str_append(dstr, "defaultuser:"); 3357057Smarks if (error) 3367057Smarks break; 3377057Smarks error = str_append(dstr, pruname(aclp->a_id, idp, 3387057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 3397057Smarks if (error == 0) 3407057Smarks error = str_append(dstr, ":"); 3417057Smarks break; 3427057Smarks 3437057Smarks case DEF_GROUP_OBJ: 3447057Smarks case GROUP_OBJ: 3457057Smarks if (aclp->a_type == GROUP_OBJ) 3467057Smarks error = str_append(dstr, "group::"); 3477057Smarks else 3487057Smarks error = str_append(dstr, "defaultgroup::"); 3497057Smarks break; 3501420Smarks 3517057Smarks case DEF_GROUP: 3527057Smarks case GROUP: 3537057Smarks if (aclp->a_type == GROUP) 3547057Smarks error = str_append(dstr, "group:"); 3557057Smarks else 3567057Smarks error = str_append(dstr, "defaultgroup:"); 3577057Smarks if (error) 3587057Smarks break; 3597057Smarks error = str_append(dstr, prgname(aclp->a_id, idp, 3607057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 3617057Smarks if (error == 0) 3627057Smarks error = str_append(dstr, ":"); 3637057Smarks break; 3647057Smarks 3657057Smarks case DEF_CLASS_OBJ: 3667057Smarks case CLASS_OBJ: 3677057Smarks if (aclp->a_type == CLASS_OBJ) 3687057Smarks error = str_append(dstr, "mask:"); 3697057Smarks else 3707057Smarks error = str_append(dstr, "defaultmask:"); 3717057Smarks break; 3721420Smarks 3737057Smarks case DEF_OTHER_OBJ: 3747057Smarks case OTHER_OBJ: 3757057Smarks if (aclp->a_type == OTHER_OBJ) 3767057Smarks error = str_append(dstr, "other:"); 3777057Smarks else 3787057Smarks error = str_append(dstr, "defaultother:"); 3797057Smarks break; 3807057Smarks 3817057Smarks default: 3827057Smarks error = 1; 3837057Smarks break; 3847057Smarks } 3857057Smarks 3867057Smarks return (error); 3877057Smarks } 3887057Smarks 3897057Smarks /* 3907057Smarks * compute entry type string such as, owner@:, user:joe, group:staff,... 3917057Smarks */ 3927057Smarks static int 3937057Smarks ace_type_txt(dynaclstr_t *dynstr, ace_t *acep, int flags) 3947057Smarks { 3957057Smarks char idp[ID_STR_MAX]; 3967057Smarks int error; 3977057Smarks char *sidp = NULL; 3981420Smarks 3991420Smarks switch (acep->a_flags & ACE_TYPE_FLAGS) { 4001420Smarks case ACE_OWNER: 4017057Smarks error = str_append(dynstr, OWNERAT_TXT); 4021420Smarks break; 4031420Smarks 4041420Smarks case ACE_GROUP|ACE_IDENTIFIER_GROUP: 4057057Smarks error = str_append(dynstr, GROUPAT_TXT); 4061420Smarks break; 4071420Smarks 4081420Smarks case ACE_IDENTIFIER_GROUP: 4097057Smarks if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) { 4107057Smarks if (error = str_append(dynstr, 4117057Smarks GROUPSID_TXT)) 4127057Smarks break; 4137680SMark.Shellenbaum@Sun.COM if (error = getsidname(acep->a_who, B_FALSE, 4147680SMark.Shellenbaum@Sun.COM &sidp, flags & ACL_NORESOLVE)) 4157680SMark.Shellenbaum@Sun.COM break; 4167680SMark.Shellenbaum@Sun.COM error = str_append(dynstr, sidp); 4177057Smarks } else { 4187057Smarks if (error = str_append(dynstr, GROUP_TXT)) 4197057Smarks break; 4207057Smarks error = str_append(dynstr, prgname(acep->a_who, idp, 4217057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 4227057Smarks } 4237057Smarks if (error == 0) 4247057Smarks error = str_append(dynstr, ":"); 4251420Smarks break; 4261420Smarks 4271420Smarks case ACE_EVERYONE: 4287057Smarks error = str_append(dynstr, EVERYONEAT_TXT); 4291420Smarks break; 4301420Smarks 4311420Smarks case 0: 4327057Smarks if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) { 4337057Smarks if (error = str_append(dynstr, USERSID_TXT)) 4347057Smarks break; 4357680SMark.Shellenbaum@Sun.COM if (error = getsidname(acep->a_who, B_TRUE, 4367680SMark.Shellenbaum@Sun.COM &sidp, flags & ACL_NORESOLVE)) 4377680SMark.Shellenbaum@Sun.COM break; 4387680SMark.Shellenbaum@Sun.COM error = str_append(dynstr, sidp); 4397057Smarks } else { 4407057Smarks if (error = str_append(dynstr, USER_TXT)) 4417057Smarks break; 4427057Smarks error = str_append(dynstr, pruname(acep->a_who, idp, 4437057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 4447057Smarks } 4457057Smarks if (error == 0) 4467057Smarks error = str_append(dynstr, ":"); 4477057Smarks break; 4487057Smarks default: 4497057Smarks error = 0; 4501420Smarks break; 4511420Smarks } 4521420Smarks 4537057Smarks if (sidp) 4547057Smarks free(sidp); 4557057Smarks return (error); 4561420Smarks } 4571420Smarks 4587057Smarks /* 4597057Smarks * compute string of permissions, such as read_data/write_data or 4607057Smarks * rwxp,... 4617057Smarks * The format depends on the flags field which indicates whether the compact 4627057Smarks * or verbose format should be used. 4637057Smarks */ 4647057Smarks static int 4657057Smarks ace_perm_txt(dynaclstr_t *dstr, uint32_t mask, 4661420Smarks uint32_t iflags, int isdir, int flags) 4671420Smarks { 4687057Smarks int error = 0; 4691420Smarks 4701420Smarks if (flags & ACL_COMPACT_FMT) { 4717057Smarks char buf[16]; 472789Sahrens 4731420Smarks if (mask & ACE_READ_DATA) 4741420Smarks buf[0] = 'r'; 4751420Smarks else 4761420Smarks buf[0] = '-'; 4771420Smarks if (mask & ACE_WRITE_DATA) 4781420Smarks buf[1] = 'w'; 4791420Smarks else 4801420Smarks buf[1] = '-'; 4811420Smarks if (mask & ACE_EXECUTE) 4821420Smarks buf[2] = 'x'; 4831420Smarks else 4841420Smarks buf[2] = '-'; 4851420Smarks if (mask & ACE_APPEND_DATA) 4861420Smarks buf[3] = 'p'; 4871420Smarks else 4881420Smarks buf[3] = '-'; 4891420Smarks if (mask & ACE_DELETE) 4901420Smarks buf[4] = 'd'; 4911420Smarks else 4921420Smarks buf[4] = '-'; 4931420Smarks if (mask & ACE_DELETE_CHILD) 4941420Smarks buf[5] = 'D'; 4951420Smarks else 4961420Smarks buf[5] = '-'; 4971420Smarks if (mask & ACE_READ_ATTRIBUTES) 4981420Smarks buf[6] = 'a'; 4991420Smarks else 5001420Smarks buf[6] = '-'; 5011420Smarks if (mask & ACE_WRITE_ATTRIBUTES) 5021420Smarks buf[7] = 'A'; 5031420Smarks else 5041420Smarks buf[7] = '-'; 5051420Smarks if (mask & ACE_READ_NAMED_ATTRS) 5061420Smarks buf[8] = 'R'; 5071420Smarks else 5081420Smarks buf[8] = '-'; 5091420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) 5101420Smarks buf[9] = 'W'; 5111420Smarks else 5121420Smarks buf[9] = '-'; 5131420Smarks if (mask & ACE_READ_ACL) 5141420Smarks buf[10] = 'c'; 5151420Smarks else 5161420Smarks buf[10] = '-'; 5171420Smarks if (mask & ACE_WRITE_ACL) 5181420Smarks buf[11] = 'C'; 5191420Smarks else 5201420Smarks buf[11] = '-'; 5211420Smarks if (mask & ACE_WRITE_OWNER) 5221420Smarks buf[12] = 'o'; 5231420Smarks else 5241420Smarks buf[12] = '-'; 5251420Smarks if (mask & ACE_SYNCHRONIZE) 5261420Smarks buf[13] = 's'; 5271420Smarks else 5281420Smarks buf[13] = '-'; 5297057Smarks buf[14] = ':'; 5307057Smarks buf[15] = '\0'; 5317057Smarks error = str_append(dstr, buf); 5321420Smarks } else { 5331420Smarks /* 5341420Smarks * If ACE is a directory, but inheritance indicates its 5351420Smarks * for a file then print permissions for file rather than 5361420Smarks * dir. 5371420Smarks */ 5381420Smarks if (isdir) { 5391420Smarks if (mask & ACE_LIST_DIRECTORY) { 5401420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5417057Smarks error = str_append(dstr, 5427057Smarks READ_DATA_TXT); 5431420Smarks } else { 5447057Smarks error = 5457057Smarks str_append(dstr, READ_DIR_TXT); 5461420Smarks } 5471420Smarks } 5487057Smarks if (error == 0 && (mask & ACE_ADD_FILE)) { 5491420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5507057Smarks error = 5517057Smarks str_append(dstr, WRITE_DATA_TXT); 5521420Smarks } else { 5537057Smarks error = 5547057Smarks str_append(dstr, ADD_FILE_TXT); 5551420Smarks } 5561420Smarks } 5577057Smarks if (error == 0 && (mask & ACE_ADD_SUBDIRECTORY)) { 5581420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 5597057Smarks error = str_append(dstr, 5607057Smarks APPEND_DATA_TXT); 5611420Smarks } else { 5627057Smarks error = str_append(dstr, 5637057Smarks ADD_DIR_TXT); 5641420Smarks } 5651420Smarks } 5661420Smarks } else { 5671420Smarks if (mask & ACE_READ_DATA) { 5687057Smarks error = str_append(dstr, READ_DATA_TXT); 5691420Smarks } 5707057Smarks if (error == 0 && (mask & ACE_WRITE_DATA)) { 5717057Smarks error = str_append(dstr, WRITE_DATA_TXT); 5721420Smarks } 5737057Smarks if (error == 0 && (mask & ACE_APPEND_DATA)) { 5747057Smarks error = str_append(dstr, APPEND_DATA_TXT); 5751420Smarks } 5761420Smarks } 5777057Smarks if (error == 0 && (mask & ACE_READ_NAMED_ATTRS)) { 5787057Smarks error = str_append(dstr, READ_XATTR_TXT); 5791420Smarks } 5807057Smarks if (error == 0 && (mask & ACE_WRITE_NAMED_ATTRS)) { 5817057Smarks error = str_append(dstr, WRITE_XATTR_TXT); 5821420Smarks } 5837057Smarks if (error == 0 && (mask & ACE_EXECUTE)) { 5847057Smarks error = str_append(dstr, EXECUTE_TXT); 5851420Smarks } 5867057Smarks if (error == 0 && (mask & ACE_DELETE_CHILD)) { 5877057Smarks error = str_append(dstr, DELETE_CHILD_TXT); 5881420Smarks } 5897057Smarks if (error == 0 && (mask & ACE_READ_ATTRIBUTES)) { 5907057Smarks error = str_append(dstr, READ_ATTRIBUTES_TXT); 5911420Smarks } 5927057Smarks if (error == 0 && (mask & ACE_WRITE_ATTRIBUTES)) { 5937057Smarks error = str_append(dstr, WRITE_ATTRIBUTES_TXT); 5941420Smarks } 5957057Smarks if (error == 0 && (mask & ACE_DELETE)) { 5967057Smarks error = str_append(dstr, DELETE_TXT); 5971420Smarks } 5987057Smarks if (error == 0 && (mask & ACE_READ_ACL)) { 5997057Smarks error = str_append(dstr, READ_ACL_TXT); 6001420Smarks } 6017057Smarks if (error == 0 && (mask & ACE_WRITE_ACL)) { 6027057Smarks error = str_append(dstr, WRITE_ACL_TXT); 6031420Smarks } 6047057Smarks if (error == 0 && (mask & ACE_WRITE_OWNER)) { 6057057Smarks error = str_append(dstr, WRITE_OWNER_TXT); 6061420Smarks } 6077057Smarks if (error == 0 && (mask & ACE_SYNCHRONIZE)) { 6087057Smarks error = str_append(dstr, SYNCHRONIZE_TXT); 6091420Smarks } 6107057Smarks if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') { 6117057Smarks dstr->d_aclexport[--dstr->d_pos] = '\0'; 6127057Smarks } 6137057Smarks if (error == 0) 6147057Smarks error = str_append(dstr, ":"); 6151420Smarks } 6167057Smarks return (error); 6171420Smarks } 6181420Smarks 6197057Smarks /* 6207057Smarks * compute string of access type, such as allow, deny, ... 6217057Smarks */ 6227057Smarks static int 6237057Smarks ace_access_txt(dynaclstr_t *dstr, int type) 6241420Smarks { 6257057Smarks int error; 6261420Smarks 6277057Smarks if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) 6287057Smarks error = str_append(dstr, ALLOW_TXT); 6297057Smarks else if (type == ACE_ACCESS_DENIED_ACE_TYPE) 6307057Smarks error = str_append(dstr, DENY_TXT); 6317057Smarks else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) 6327057Smarks error = str_append(dstr, AUDIT_TXT); 6337057Smarks else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) 6347057Smarks error = str_append(dstr, ALARM_TXT); 6357057Smarks else 6367057Smarks error = str_append(dstr, UNKNOWN_TXT); 6371420Smarks 6387057Smarks return (error); 6391420Smarks } 6401420Smarks 6417057Smarks static int 6427057Smarks ace_inherit_txt(dynaclstr_t *dstr, uint32_t iflags, int flags) 6431420Smarks { 6447057Smarks int error = 0; 645789Sahrens 6461420Smarks if (flags & ACL_COMPACT_FMT) { 6477057Smarks char buf[9]; 6487057Smarks 6491420Smarks if (iflags & ACE_FILE_INHERIT_ACE) 6501420Smarks buf[0] = 'f'; 6511420Smarks else 6521420Smarks buf[0] = '-'; 6531420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) 6541420Smarks buf[1] = 'd'; 6551420Smarks else 6561420Smarks buf[1] = '-'; 6571420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) 6581420Smarks buf[2] = 'i'; 6591420Smarks else 6601420Smarks buf[2] = '-'; 6611420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) 6621420Smarks buf[3] = 'n'; 6631420Smarks else 6641420Smarks buf[3] = '-'; 6651420Smarks if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 6661420Smarks buf[4] = 'S'; 6671420Smarks else 6681420Smarks buf[4] = '-'; 6691420Smarks if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) 6701420Smarks buf[5] = 'F'; 6711420Smarks else 6721420Smarks buf[5] = '-'; 6735331Samw if (iflags & ACE_INHERITED_ACE) 6745331Samw buf[6] = 'I'; 6755331Samw else 6765331Samw buf[6] = '-'; 6777057Smarks buf[7] = ':'; 6787057Smarks buf[8] = '\0'; 6797057Smarks error = str_append(dstr, buf); 6801420Smarks } else { 6811420Smarks if (iflags & ACE_FILE_INHERIT_ACE) { 6827057Smarks error = str_append(dstr, FILE_INHERIT_TXT); 6831420Smarks } 6847057Smarks if (error == 0 && (iflags & ACE_DIRECTORY_INHERIT_ACE)) { 6857057Smarks error = str_append(dstr, DIR_INHERIT_TXT); 6861420Smarks } 6877057Smarks if (error == 0 && (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) { 6887057Smarks error = str_append(dstr, NO_PROPAGATE_TXT); 6891420Smarks } 6907057Smarks if (error == 0 && (iflags & ACE_INHERIT_ONLY_ACE)) { 6917057Smarks error = str_append(dstr, INHERIT_ONLY_TXT); 6921420Smarks } 6937057Smarks if (error == 0 && (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)) { 6947057Smarks error = str_append(dstr, SUCCESSFUL_ACCESS_TXT); 6955331Samw } 6967057Smarks if (error == 0 && (iflags & ACE_FAILED_ACCESS_ACE_FLAG)) { 6977057Smarks error = str_append(dstr, FAILED_ACCESS_TXT); 6985331Samw } 6997057Smarks if (error == 0 && (iflags & ACE_INHERITED_ACE)) { 7007057Smarks error = str_append(dstr, INHERITED_ACE_TXT); 7015331Samw } 7027057Smarks if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') { 7037057Smarks dstr->d_aclexport[--dstr->d_pos] = '\0'; 7047057Smarks error = str_append(dstr, ":"); 7057057Smarks } 7061420Smarks } 7071420Smarks 7087057Smarks return (error); 709789Sahrens } 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate /* 7120Sstevel@tonic-gate * Convert internal acl representation to external representation. 7130Sstevel@tonic-gate * 7140Sstevel@tonic-gate * The length of a non-owning user name or non-owning group name ie entries 7150Sstevel@tonic-gate * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We 7160Sstevel@tonic-gate * thus check the length of these entries, and if greater than LOGNAME_MAX, 7170Sstevel@tonic-gate * we realloc() via increase_length(). 7180Sstevel@tonic-gate * 7190Sstevel@tonic-gate * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always 7200Sstevel@tonic-gate * adhered to. 7210Sstevel@tonic-gate */ 7221420Smarks 7231420Smarks /* 7241420Smarks * acltotext() converts each ACL entry to look like this: 7251420Smarks * 7261420Smarks * entry_type:uid^gid^name:perms[:id] 7271420Smarks * 7281420Smarks * The maximum length of entry_type is 14 ("defaultgroup::" and 7291420Smarks * "defaultother::") hence ENTRYTYPELEN is set to 14. 7301420Smarks * 7311420Smarks * The max length of a uid^gid^name entry (in theory) is 8, hence we use, 7321420Smarks * however the ID could be a number so we therefore use ID_STR_MAX 7331420Smarks * 7341420Smarks * The length of a perms entry is 4 to allow for the comma appended to each 7351420Smarks * to each acl entry. Hence PERMS is set to 4. 7361420Smarks */ 7371420Smarks 7381420Smarks #define ENTRYTYPELEN 14 7391420Smarks #define PERMS 4 7401420Smarks #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX) 7411420Smarks 7420Sstevel@tonic-gate char * 7431420Smarks aclent_acltotext(aclent_t *aclp, int aclcnt, int flags) 7440Sstevel@tonic-gate { 7457057Smarks dynaclstr_t *dstr; 7467680SMark.Shellenbaum@Sun.COM char *aclexport = NULL; 7477057Smarks int i; 7487057Smarks int error = 0; 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate if (aclp == NULL) 7510Sstevel@tonic-gate return (NULL); 7527057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 7530Sstevel@tonic-gate return (NULL); 7547057Smarks dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE; 7557057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 7560Sstevel@tonic-gate free(dstr); 7570Sstevel@tonic-gate return (NULL); 7580Sstevel@tonic-gate } 7597057Smarks *dstr->d_aclexport = '\0'; 7607057Smarks dstr->d_pos = 0; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate for (i = 0; i < aclcnt; i++, aclp++) { 7637057Smarks if (error = aclent_type_txt(dstr, aclp, flags)) 7640Sstevel@tonic-gate break; 7657057Smarks if (error = aclent_perm_txt(dstr, aclp->a_perm)) 7660Sstevel@tonic-gate break; 7671420Smarks 7681420Smarks if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) || 7691420Smarks (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) || 7701420Smarks (aclp->a_type == DEF_GROUP))) { 7717057Smarks char id[ID_STR_MAX], *idstr; 7727057Smarks 7737057Smarks if (error = str_append(dstr, ":")) 7747057Smarks break; 7751420Smarks id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */ 7761420Smarks idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]); 7777057Smarks if (error = str_append(dstr, idstr)) 7787057Smarks break; 7791420Smarks } 7800Sstevel@tonic-gate if (i < aclcnt - 1) 7817057Smarks if (error = str_append(dstr, ",")) 7827057Smarks break; 7830Sstevel@tonic-gate } 7847057Smarks if (error) { 7857057Smarks if (dstr->d_aclexport) 7867057Smarks free(dstr->d_aclexport); 7877057Smarks } else { 7887057Smarks aclexport = dstr->d_aclexport; 7897057Smarks } 7900Sstevel@tonic-gate free(dstr); 7910Sstevel@tonic-gate return (aclexport); 7920Sstevel@tonic-gate } 7930Sstevel@tonic-gate 7941420Smarks char * 7951420Smarks acltotext(aclent_t *aclp, int aclcnt) 7960Sstevel@tonic-gate { 7971420Smarks return (aclent_acltotext(aclp, aclcnt, 0)); 7981420Smarks } 7990Sstevel@tonic-gate 8000Sstevel@tonic-gate 801789Sahrens aclent_t * 802789Sahrens aclfromtext(char *aclstr, int *aclcnt) 803789Sahrens { 804789Sahrens acl_t *aclp; 805789Sahrens aclent_t *aclentp; 806789Sahrens int error; 807789Sahrens 8081420Smarks error = acl_fromtext(aclstr, &aclp); 809789Sahrens if (error) 810789Sahrens return (NULL); 811789Sahrens 812789Sahrens aclentp = aclp->acl_aclp; 813789Sahrens aclp->acl_aclp = NULL; 8141420Smarks *aclcnt = aclp->acl_cnt; 815789Sahrens 8161420Smarks acl_free(aclp); 817789Sahrens return (aclentp); 818789Sahrens } 819789Sahrens 820789Sahrens 8217057Smarks /* 8227680SMark.Shellenbaum@Sun.COM * Append string onto dynaclstr_t. 8237680SMark.Shellenbaum@Sun.COM * 8247680SMark.Shellenbaum@Sun.COM * Return 0 on success, 1 for failure. 8257057Smarks */ 8267057Smarks static int 8277057Smarks str_append(dynaclstr_t *dstr, char *newstr) 8280Sstevel@tonic-gate { 8297057Smarks size_t len = strlen(newstr); 8307057Smarks 8317057Smarks if ((len + dstr->d_pos) >= dstr->d_bufsize) { 8327057Smarks dstr->d_aclexport = realloc(dstr->d_aclexport, 8337057Smarks dstr->d_bufsize + len + 1); 8347057Smarks if (dstr->d_aclexport == NULL) 8357057Smarks return (1); 8367057Smarks dstr->d_bufsize += len; 8377057Smarks } 8387057Smarks (void) strcat(&dstr->d_aclexport[dstr->d_pos], newstr); 8397057Smarks dstr->d_pos += len; 8407057Smarks return (0); 8410Sstevel@tonic-gate } 8420Sstevel@tonic-gate 8437057Smarks static int 8447057Smarks aclent_perm_txt(dynaclstr_t *dstr, o_mode_t perm) 8450Sstevel@tonic-gate { 8467057Smarks char buf[4]; 8470Sstevel@tonic-gate 8487057Smarks if (perm & S_IROTH) 8497057Smarks buf[0] = 'r'; 8507057Smarks else 8517057Smarks buf[0] = '-'; 8527057Smarks if (perm & S_IWOTH) 8537057Smarks buf[1] = 'w'; 8547057Smarks else 8557057Smarks buf[1] = '-'; 8567057Smarks if (perm & S_IXOTH) 8577057Smarks buf[2] = 'x'; 8587057Smarks else 8597057Smarks buf[2] = '-'; 8607057Smarks buf[3] = '\0'; 8617057Smarks return (str_append(dstr, buf)); 8620Sstevel@tonic-gate } 863789Sahrens 864789Sahrens /* 8651420Smarks * ace_acltotext() convert each ace formatted acl to look like this: 866789Sahrens * 8671420Smarks * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,] 868789Sahrens * 869789Sahrens * The maximum length of entry_type is 5 ("group") 870789Sahrens * 8711420Smarks * The max length of a uid^gid^name entry (in theory) is 8, 8721420Smarks * however id could be a number so we therefore use ID_STR_MAX 873789Sahrens * 874789Sahrens * The length of a perms entry is 144 i.e read_data/write_data... 875789Sahrens * to each acl entry. 876789Sahrens * 8775331Samw * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access 8785331Samw * /failed_access 879789Sahrens * 880789Sahrens */ 881789Sahrens 882789Sahrens #define ACE_ENTRYTYPLEN 6 8835331Samw #define IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \ 8845331Samw "successful_access/failed_access/inherited" 8855331Samw #define IFLAGS_SIZE (sizeof (IFLAGS_STR) - 1) 8861420Smarks #define ACCESS_TYPE_SIZE 7 /* if unknown */ 887789Sahrens #define COLON_CNT 3 888789Sahrens #define PERMS_LEN 216 8895331Samw #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \ 8901420Smarks ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX) 891789Sahrens 892789Sahrens static char * 8931420Smarks ace_acltotext(acl_t *aceaclp, int flags) 894789Sahrens { 895789Sahrens ace_t *aclp = aceaclp->acl_aclp; 896789Sahrens int aclcnt = aceaclp->acl_cnt; 8977057Smarks int i; 8987057Smarks int error = 0; 8997057Smarks int isdir = (aceaclp->acl_flags & ACL_IS_DIR); 9007057Smarks dynaclstr_t *dstr; 9017680SMark.Shellenbaum@Sun.COM char *aclexport = NULL; 90211605SGowtham.Thommandra@Sun.COM char *rawsidp = NULL; 903789Sahrens 904789Sahrens if (aclp == NULL) 905789Sahrens return (NULL); 906789Sahrens 9077057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 9087057Smarks return (NULL); 9097057Smarks dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE; 9107057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 9117057Smarks free(dstr); 9127057Smarks return (NULL); 9137057Smarks } 9147057Smarks *dstr->d_aclexport = '\0'; 9157057Smarks dstr->d_pos = 0; 9167057Smarks 917789Sahrens for (i = 0; i < aclcnt; i++, aclp++) { 9181420Smarks 9197057Smarks if (error = ace_type_txt(dstr, aclp, flags)) 9207057Smarks break; 9217057Smarks if (error = ace_perm_txt(dstr, aclp->a_access_mask, 9227057Smarks aclp->a_flags, isdir, flags)) 9237057Smarks break; 9247057Smarks if (error = ace_inherit_txt(dstr, aclp->a_flags, flags)) 9257057Smarks break; 9267057Smarks if (error = ace_access_txt(dstr, aclp->a_type)) 9277057Smarks break; 928789Sahrens 9291420Smarks if ((flags & ACL_APPEND_ID) && 9301420Smarks (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) || 9311420Smarks ((aclp->a_flags & ACE_TYPE_FLAGS) == 9321420Smarks ACE_IDENTIFIER_GROUP))) { 9337057Smarks char id[ID_STR_MAX], *idstr; 9347057Smarks 9357057Smarks if (error = str_append(dstr, ":")) 9367057Smarks break; 9378268SMark.Shellenbaum@Sun.COM 9388268SMark.Shellenbaum@Sun.COM rawsidp = NULL; 9398268SMark.Shellenbaum@Sun.COM id[ID_STR_MAX -1] = '\0'; /* null terminate */ 9408268SMark.Shellenbaum@Sun.COM if (aclp->a_who > MAXUID && (flags & ACL_SID_FMT)) { 9418268SMark.Shellenbaum@Sun.COM 9428268SMark.Shellenbaum@Sun.COM error = getsidname(aclp->a_who, 9438268SMark.Shellenbaum@Sun.COM ((aclp->a_flags & ACE_TYPE_FLAGS) == 0) ? 9448268SMark.Shellenbaum@Sun.COM B_TRUE : B_FALSE, &idstr, 1); 94511605SGowtham.Thommandra@Sun.COM rawsidp = idstr; 9468268SMark.Shellenbaum@Sun.COM if (error) 9478268SMark.Shellenbaum@Sun.COM break; 9488268SMark.Shellenbaum@Sun.COM } else if (aclp->a_who > MAXUID && 9498268SMark.Shellenbaum@Sun.COM !(flags & ACL_NORESOLVE)) { 9508268SMark.Shellenbaum@Sun.COM idstr = lltostr(UID_NOBODY, 9518268SMark.Shellenbaum@Sun.COM &id[ID_STR_MAX - 1]); 9528268SMark.Shellenbaum@Sun.COM } else { 9538268SMark.Shellenbaum@Sun.COM idstr = lltostr(aclp->a_who, 9548268SMark.Shellenbaum@Sun.COM &id[ID_STR_MAX - 1]); 9558268SMark.Shellenbaum@Sun.COM } 9567057Smarks if (error = str_append(dstr, idstr)) 9577057Smarks break; 95811605SGowtham.Thommandra@Sun.COM if (rawsidp) { 9598268SMark.Shellenbaum@Sun.COM free(rawsidp); 96011605SGowtham.Thommandra@Sun.COM rawsidp = NULL; 96111605SGowtham.Thommandra@Sun.COM } 962789Sahrens } 9631420Smarks if (i < aclcnt - 1) { 9647057Smarks if (error = str_append(dstr, ",")) 9657057Smarks break; 966789Sahrens } 967789Sahrens } 96811605SGowtham.Thommandra@Sun.COM 96911605SGowtham.Thommandra@Sun.COM if (rawsidp) 97011605SGowtham.Thommandra@Sun.COM free(rawsidp); 9717057Smarks if (error) { 9727057Smarks if (dstr->d_aclexport) 9737057Smarks free(dstr->d_aclexport); 9747057Smarks } else { 9757057Smarks aclexport = dstr->d_aclexport; 9767057Smarks } 9777057Smarks free(dstr); 978789Sahrens return (aclexport); 979789Sahrens } 980789Sahrens 9811420Smarks char * 9821420Smarks acl_totext(acl_t *aclp, int flags) 983789Sahrens { 9841420Smarks char *txtp; 985789Sahrens 986789Sahrens if (aclp == NULL) 987789Sahrens return (NULL); 988789Sahrens 989789Sahrens switch (aclp->acl_type) { 990789Sahrens case ACE_T: 9911420Smarks txtp = ace_acltotext(aclp, flags); 9921420Smarks break; 993789Sahrens case ACLENT_T: 9941420Smarks txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags); 9951420Smarks break; 996789Sahrens } 9971420Smarks 9981420Smarks return (txtp); 999789Sahrens } 1000789Sahrens 1001789Sahrens int 1002789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp) 1003789Sahrens { 10041420Smarks int error; 10051420Smarks char *buf; 10061420Smarks 10071420Smarks buf = malloc(strlen(acltextp) + 2); 10081420Smarks if (buf == NULL) 10091420Smarks return (EACL_MEM_ERROR); 10101420Smarks strcpy(buf, acltextp); 10111420Smarks strcat(buf, "\n"); 1012*11963SAfshin.Ardakani@Sun.COM 1013*11963SAfshin.Ardakani@Sun.COM (void) mutex_lock(&yymutex); 10141420Smarks yybuf = buf; 10151420Smarks yyreset(); 10161420Smarks error = yyparse(); 10171420Smarks free(buf); 10181420Smarks 10191420Smarks if (yyacl) { 10201420Smarks if (error == 0) 10211420Smarks *ret_aclp = yyacl; 10221420Smarks else { 10231420Smarks acl_free(yyacl); 10241420Smarks } 10251420Smarks yyacl = NULL; 10261420Smarks } 1027*11963SAfshin.Ardakani@Sun.COM (void) mutex_unlock(&yymutex); 1028*11963SAfshin.Ardakani@Sun.COM 10291420Smarks return (error); 10301420Smarks } 10311420Smarks 10321420Smarks int 10331420Smarks acl_parse(const char *acltextp, acl_t **aclp) 10341420Smarks { 1035789Sahrens int error; 1036789Sahrens 10371420Smarks yyinteractive = 1; 10381420Smarks error = acl_fromtext(acltextp, aclp); 10391420Smarks yyinteractive = 0; 10401420Smarks return (error); 10411420Smarks } 10421420Smarks 10431420Smarks static void 10441420Smarks ace_compact_printacl(acl_t *aclp) 10451420Smarks { 10461420Smarks int cnt; 10471420Smarks ace_t *acep; 10487057Smarks dynaclstr_t *dstr; 10497057Smarks int len; 1050789Sahrens 10517057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 10527057Smarks return; 10537057Smarks dstr->d_bufsize = ACE_ENTRY_SIZE; 10547057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 10557057Smarks free(dstr); 10567057Smarks return; 10577057Smarks } 10587057Smarks *dstr->d_aclexport = '\0'; 10597057Smarks 10607057Smarks dstr->d_pos = 0; 10611420Smarks for (cnt = 0, acep = aclp->acl_aclp; 10621420Smarks cnt != aclp->acl_cnt; cnt++, acep++) { 10637057Smarks dstr->d_aclexport[0] = '\0'; 10647057Smarks dstr->d_pos = 0; 10657057Smarks 10667057Smarks if (ace_type_txt(dstr, acep, 0)) 10677057Smarks break; 10687057Smarks len = strlen(&dstr->d_aclexport[0]); 10697057Smarks if (ace_perm_txt(dstr, acep->a_access_mask, acep->a_flags, 10707057Smarks aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT)) 10717057Smarks break; 10727057Smarks if (ace_inherit_txt(dstr, acep->a_flags, ACL_COMPACT_FMT)) 10737057Smarks break; 10747057Smarks if (ace_access_txt(dstr, acep->a_type) == -1) 10757057Smarks break; 10767057Smarks (void) printf(" %20.*s%s\n", len, dstr->d_aclexport, 10777057Smarks &dstr->d_aclexport[len]); 10781420Smarks } 10797057Smarks 10807057Smarks if (dstr->d_aclexport) 10817057Smarks free(dstr->d_aclexport); 10827057Smarks free(dstr); 10831420Smarks } 1084789Sahrens 10851420Smarks static void 10861420Smarks ace_printacl(acl_t *aclp, int cols, int compact) 10871420Smarks { 10881420Smarks int slot = 0; 10891420Smarks char *token; 10901420Smarks char *acltext; 10911420Smarks 10921420Smarks if (compact) { 10931420Smarks ace_compact_printacl(aclp); 10941420Smarks return; 1095789Sahrens } 1096789Sahrens 10971420Smarks acltext = acl_totext(aclp, 0); 10981420Smarks 10991420Smarks if (acltext == NULL) 11001420Smarks return; 11011420Smarks 11021420Smarks token = strtok(acltext, ","); 11031420Smarks if (token == NULL) { 11041420Smarks free(acltext); 11051420Smarks return; 1106789Sahrens } 1107789Sahrens 11081420Smarks do { 11091420Smarks (void) printf(" %d:", slot++); 11101420Smarks split_line(token, cols - 5); 11111420Smarks } while (token = strtok(NULL, ",")); 11121420Smarks free(acltext); 11131420Smarks } 11141420Smarks 11151420Smarks /* 11161420Smarks * pretty print an ACL. 11171420Smarks * For aclent_t ACL's the format is 11181420Smarks * similar to the old format used by getfacl, 11191420Smarks * with the addition of adding a "slot" number 11201420Smarks * before each entry. 11211420Smarks * 11221420Smarks * for ace_t ACL's the cols variable will break up 11231420Smarks * the long lines into multiple lines and will also 11241420Smarks * print a "slot" number. 11251420Smarks */ 11261420Smarks void 11271420Smarks acl_printacl(acl_t *aclp, int cols, int compact) 11281420Smarks { 11291420Smarks 11301420Smarks switch (aclp->acl_type) { 11311420Smarks case ACLENT_T: 11321420Smarks aclent_printacl(aclp); 11331420Smarks break; 11341420Smarks case ACE_T: 11351420Smarks ace_printacl(aclp, cols, compact); 11361420Smarks break; 11371420Smarks } 11381420Smarks } 11391420Smarks 11401420Smarks typedef struct value_table { 11411420Smarks char p_letter; /* perm letter such as 'r' */ 11421420Smarks uint32_t p_value; /* value for perm when pletter found */ 11431420Smarks } value_table_t; 11441420Smarks 11451420Smarks /* 11465331Samw * The permission tables are laid out in positional order 11471420Smarks * a '-' character will indicate a permission at a given 11481420Smarks * position is not specified. The '-' is not part of the 11491420Smarks * table, but will be checked for in the permission computation 11501420Smarks * routine. 11511420Smarks */ 11525331Samw value_table_t ace_perm_table[] = { 11531420Smarks { 'r', ACE_READ_DATA}, 11541420Smarks { 'w', ACE_WRITE_DATA}, 11551420Smarks { 'x', ACE_EXECUTE}, 11561420Smarks { 'p', ACE_APPEND_DATA}, 11571420Smarks { 'd', ACE_DELETE}, 11581420Smarks { 'D', ACE_DELETE_CHILD}, 11591420Smarks { 'a', ACE_READ_ATTRIBUTES}, 11601420Smarks { 'A', ACE_WRITE_ATTRIBUTES}, 11611420Smarks { 'R', ACE_READ_NAMED_ATTRS}, 11621420Smarks { 'W', ACE_WRITE_NAMED_ATTRS}, 11631420Smarks { 'c', ACE_READ_ACL}, 11641420Smarks { 'C', ACE_WRITE_ACL}, 11651420Smarks { 'o', ACE_WRITE_OWNER}, 11661420Smarks { 's', ACE_SYNCHRONIZE} 11671420Smarks }; 11681420Smarks 11695331Samw #define ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t)) 11701420Smarks 11715331Samw value_table_t aclent_perm_table[] = { 11721420Smarks { 'r', S_IROTH}, 11731420Smarks { 'w', S_IWOTH}, 11741420Smarks { 'x', S_IXOTH} 11751420Smarks }; 11761420Smarks 11775331Samw #define ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t)) 11785331Samw 11795331Samw value_table_t inherit_table[] = { 11801420Smarks {'f', ACE_FILE_INHERIT_ACE}, 11811420Smarks {'d', ACE_DIRECTORY_INHERIT_ACE}, 11821420Smarks {'i', ACE_INHERIT_ONLY_ACE}, 11831420Smarks {'n', ACE_NO_PROPAGATE_INHERIT_ACE}, 11841420Smarks {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 11855331Samw {'F', ACE_FAILED_ACCESS_ACE_FLAG}, 11865331Samw {'I', ACE_INHERITED_ACE} 11871420Smarks }; 11881420Smarks 11895331Samw #define IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t)) 11906269Smarks #define IFLAG_COUNT_V1 6 /* Older version compatibility */ 11915331Samw 11921420Smarks /* 11931420Smarks * compute value from a permission table or inheritance table 11941420Smarks * based on string passed in. If positional is set then 11951420Smarks * string must match order in permtab, otherwise any order 11961420Smarks * is allowed. 11971420Smarks */ 11981420Smarks int 11991420Smarks compute_values(value_table_t *permtab, int count, 12001420Smarks char *permstr, int positional, uint32_t *mask) 12011420Smarks { 12021420Smarks uint32_t perm_val = 0; 12031420Smarks char *pstr; 12041420Smarks int i, found; 12051420Smarks 12061420Smarks if (count < 0) 12071420Smarks return (1); 12081420Smarks 12091420Smarks if (positional) { 12101420Smarks for (i = 0, pstr = permstr; i != count && pstr && 12111420Smarks *pstr; i++, pstr++) { 12121420Smarks if (*pstr == permtab[i].p_letter) { 12131420Smarks perm_val |= permtab[i].p_value; 12141420Smarks } else if (*pstr != '-') { 12151420Smarks return (1); 12161420Smarks } 1217789Sahrens } 12181420Smarks } else { /* random order single letters with no '-' */ 12191420Smarks for (pstr = permstr; pstr && *pstr; pstr++) { 12201420Smarks for (found = 0, i = 0; i != count; i++) { 12211420Smarks if (*pstr == permtab[i].p_letter) { 12221420Smarks perm_val |= permtab[i].p_value; 12231420Smarks found = 1; 12241420Smarks break; 12251420Smarks } 12261420Smarks } 12271420Smarks if (found == 0) 12281420Smarks return (1); 12291420Smarks } 1230789Sahrens } 1231789Sahrens 12321420Smarks *mask = perm_val; 12331420Smarks return (0); 12341420Smarks } 1235789Sahrens 12366269Smarks 12376269Smarks int 12386269Smarks ace_inherit_helper(char *str, uint32_t *imask, int table_length) 12396269Smarks { 12406269Smarks int rc = 0; 12416269Smarks 12426269Smarks if (strlen(str) == table_length) { 12436269Smarks /* 12446269Smarks * If the string == table_length then first check to see it's 12456269Smarks * in positional format. If that fails then see if it's in 12466269Smarks * non-positional format. 12476269Smarks */ 12486269Smarks if (compute_values(inherit_table, table_length, str, 12496269Smarks 1, imask) && compute_values(inherit_table, 12506269Smarks table_length, str, 0, imask)) { 12516269Smarks rc = 1; 12526269Smarks } 12536269Smarks } else { 12546269Smarks rc = compute_values(inherit_table, table_length, str, 0, imask); 12556269Smarks } 12566269Smarks 12576269Smarks return (rc ? EACL_INHERIT_ERROR : 0); 12586269Smarks } 12596269Smarks 12601420Smarks /* 12611420Smarks * compute value for inheritance flags. 12621420Smarks */ 12631420Smarks int 12641420Smarks compute_ace_inherit(char *str, uint32_t *imask) 12651420Smarks { 12666269Smarks int rc = 0; 1267789Sahrens 12686269Smarks rc = ace_inherit_helper(str, imask, IFLAG_COUNT); 12696269Smarks 12706269Smarks if (rc && strlen(str) != IFLAG_COUNT) { 12711420Smarks 12726269Smarks /* is it an old formatted inherit string? */ 12736269Smarks rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1); 12746269Smarks } 12751420Smarks 12766269Smarks return (rc); 1277789Sahrens } 12781420Smarks 12791420Smarks 12801420Smarks /* 12811420Smarks * compute value for ACE permissions. 12821420Smarks */ 12831420Smarks int 12841420Smarks compute_ace_perms(char *str, uint32_t *mask) 12851420Smarks { 12861420Smarks int positional = 0; 12871420Smarks int error; 12881420Smarks 12891420Smarks if (strlen(str) == ACE_PERM_COUNT) 12901420Smarks positional = 1; 12911420Smarks 12921420Smarks error = compute_values(ace_perm_table, ACE_PERM_COUNT, 12931420Smarks str, positional, mask); 12941420Smarks 12951420Smarks if (error && positional) { 12961420Smarks /* 12971420Smarks * If positional was set, then make sure permissions 12981420Smarks * aren't actually valid in non positional case where 12991420Smarks * all permissions are specified, just in random order. 13001420Smarks */ 13011420Smarks error = compute_values(ace_perm_table, 13021420Smarks ACE_PERM_COUNT, str, 0, mask); 13031420Smarks } 13041420Smarks if (error) 13051420Smarks error = EACL_PERM_MASK_ERROR; 13061420Smarks 13071420Smarks return (error); 13081420Smarks } 13091420Smarks 13101420Smarks 13111420Smarks 13121420Smarks /* 13131420Smarks * compute values for aclent permissions. 13141420Smarks */ 13151420Smarks int 13161420Smarks compute_aclent_perms(char *str, o_mode_t *mask) 13171420Smarks { 13181420Smarks int error; 13191420Smarks uint32_t pmask; 13201420Smarks 13211420Smarks if (strlen(str) != ACLENT_PERM_COUNT) 13221420Smarks return (EACL_PERM_MASK_ERROR); 13231420Smarks 13241420Smarks *mask = 0; 13251420Smarks error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT, 13261420Smarks str, 1, &pmask); 13271420Smarks if (error == 0) { 13281420Smarks *mask = (o_mode_t)pmask; 13291420Smarks } else 13301420Smarks error = EACL_PERM_MASK_ERROR; 13311420Smarks return (error); 13321420Smarks } 13331420Smarks 13341420Smarks /* 13351420Smarks * determine ACE permissions. 13361420Smarks */ 13371420Smarks int 13381420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask) 13391420Smarks { 13401420Smarks int error; 13411420Smarks 13421420Smarks if (aclperm->perm_style == PERM_TYPE_EMPTY) { 13431420Smarks *mask = 0; 13441420Smarks return (0); 13451420Smarks } 13461420Smarks 13471420Smarks if (aclperm->perm_style == PERM_TYPE_ACE) { 13481420Smarks *mask = aclperm->perm_val; 13491420Smarks return (0); 13501420Smarks } 13511420Smarks 13521420Smarks error = compute_ace_perms(aclperm->perm_str, mask); 13531420Smarks if (error) { 13541567Smarks acl_error(dgettext(TEXT_DOMAIN, 13551567Smarks "Invalid permission(s) '%s' specified\n"), 13561420Smarks aclperm->perm_str); 13571420Smarks return (EACL_PERM_MASK_ERROR); 13581420Smarks } 13591420Smarks 13601420Smarks return (0); 13611420Smarks } 1362