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 #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate /*LINTLIBRARY*/ 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <grp.h> 300Sstevel@tonic-gate #include <pwd.h> 310Sstevel@tonic-gate #include <string.h> 320Sstevel@tonic-gate #include <limits.h> 330Sstevel@tonic-gate #include <stdlib.h> 34789Sahrens #include <errno.h> 350Sstevel@tonic-gate #include <sys/param.h> 360Sstevel@tonic-gate #include <sys/types.h> 371420Smarks #include <sys/stat.h> 380Sstevel@tonic-gate #include <sys/acl.h> 39789Sahrens #include <aclutils.h> 40*7057Smarks #include <idmap.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; 53789Sahrens 54789Sahrens extern acl_t *acl_alloc(enum acl_type); 550Sstevel@tonic-gate 56*7057Smarks /* 57*7057Smarks * dynamic string that will increase in size on an 58*7057Smarks * as needed basis. 59*7057Smarks */ 60*7057Smarks typedef struct dynaclstr { 61*7057Smarks size_t d_bufsize; /* current size of aclexport */ 62*7057Smarks char *d_aclexport; 63*7057Smarks int d_pos; 64*7057Smarks } dynaclstr_t; 65922Shm123892 66*7057Smarks static int str_append(dynaclstr_t *, char *); 67*7057Smarks static int aclent_perm_txt(dynaclstr_t *, o_mode_t); 680Sstevel@tonic-gate 691420Smarks static void 701420Smarks aclent_perms(int perm, char *txt_perms) 711420Smarks { 721420Smarks if (perm & S_IROTH) 731420Smarks txt_perms[0] = 'r'; 741420Smarks else 751420Smarks txt_perms[0] = '-'; 761420Smarks if (perm & S_IWOTH) 771420Smarks txt_perms[1] = 'w'; 781420Smarks else 791420Smarks txt_perms[1] = '-'; 801420Smarks if (perm & S_IXOTH) 811420Smarks txt_perms[2] = 'x'; 821420Smarks else 831420Smarks txt_perms[2] = '-'; 841420Smarks txt_perms[3] = '\0'; 851420Smarks } 861420Smarks 871420Smarks static char * 881535Smarks pruname(uid_t uid, char *uidp, size_t buflen, int noresolve) 891420Smarks { 901515Sgjelinek struct passwd *passwdp = NULL; 911420Smarks 921515Sgjelinek if (noresolve == 0) 931515Sgjelinek passwdp = getpwuid(uid); 941420Smarks if (passwdp == (struct passwd *)NULL) { 951420Smarks /* could not get passwd information: display uid instead */ 964321Scasper (void) snprintf(uidp, buflen, "%u", uid); 971535Smarks } else { 981535Smarks (void) strlcpy(uidp, passwdp->pw_name, buflen); 991535Smarks } 1001535Smarks return (uidp); 1011420Smarks } 1021420Smarks 1031420Smarks static char * 1041535Smarks prgname(gid_t gid, char *gidp, size_t buflen, int noresolve) 1051420Smarks { 1061515Sgjelinek struct group *groupp = NULL; 1071420Smarks 1081515Sgjelinek if (noresolve == 0) 1091515Sgjelinek groupp = getgrgid(gid); 1101420Smarks if (groupp == (struct group *)NULL) { 1111420Smarks /* could not get group information: display gid instead */ 1124321Scasper (void) snprintf(gidp, buflen, "%u", gid); 1131535Smarks } else { 1141535Smarks (void) strlcpy(gidp, groupp->gr_name, buflen); 1151535Smarks } 1161535Smarks return (gidp); 1171420Smarks } 118*7057Smarks 119*7057Smarks static char * 120*7057Smarks prsidname(uid_t who, boolean_t user, char **sidp, int noresolve) 121*7057Smarks { 122*7057Smarks idmap_handle_t *idmap_hdl = NULL; 123*7057Smarks idmap_get_handle_t *get_hdl = NULL; 124*7057Smarks idmap_stat status; 125*7057Smarks idmap_rid_t rid; 126*7057Smarks int error = 1; 127*7057Smarks int len; 128*7057Smarks char *domain; 129*7057Smarks char *name; 130*7057Smarks 131*7057Smarks if (noresolve) { 132*7057Smarks len = snprintf(NULL, 0, "%u", who); 133*7057Smarks *sidp = malloc(len + 1); 134*7057Smarks (void) snprintf(*sidp, len + 1, "%u", who); 135*7057Smarks return (*sidp); 136*7057Smarks } 137*7057Smarks 138*7057Smarks /* 139*7057Smarks * First try and get windows name 140*7057Smarks */ 141*7057Smarks 142*7057Smarks if (user) 143*7057Smarks error = idmap_getwinnamebyuid(who, &name, &domain); 144*7057Smarks else 145*7057Smarks error = idmap_getwinnamebygid(who, &name, &domain); 146*7057Smarks 147*7057Smarks if (error) { 148*7057Smarks if (idmap_init(&idmap_hdl) == 0 && 149*7057Smarks idmap_get_create(idmap_hdl, &get_hdl) == 0) { 150*7057Smarks if (user) 151*7057Smarks error = idmap_get_sidbyuid(get_hdl, who, 152*7057Smarks 0, &domain, &rid, &status); 153*7057Smarks else 154*7057Smarks error = idmap_get_sidbygid(get_hdl, who, 155*7057Smarks 0, &domain, &rid, &status); 156*7057Smarks if (error == 0) 157*7057Smarks error = idmap_get_mappings(get_hdl); 158*7057Smarks } 159*7057Smarks if (error == 0) { 160*7057Smarks len = snprintf(NULL, 0, "%s-%d", domain, rid); 161*7057Smarks *sidp = malloc(len + 1); 162*7057Smarks (void) snprintf(*sidp, len + 1, "%s-%d", domain, rid); 163*7057Smarks } else { 164*7057Smarks *sidp = NULL; 165*7057Smarks } 166*7057Smarks if (get_hdl) 167*7057Smarks idmap_get_destroy(get_hdl); 168*7057Smarks if (idmap_hdl) 169*7057Smarks (void) idmap_fini(idmap_hdl); 170*7057Smarks } else { 171*7057Smarks int len; 172*7057Smarks len = snprintf(NULL, 0, "%s@%d", name, domain); 173*7057Smarks *sidp = malloc(len + 1); 174*7057Smarks (void) snprintf(*sidp, len + 1, "%s@%s", name, domain); 175*7057Smarks } 176*7057Smarks return (*sidp); 177*7057Smarks } 178*7057Smarks 1791420Smarks static void 1801420Smarks aclent_printacl(acl_t *aclp) 181789Sahrens { 1821420Smarks aclent_t *tp; 1831420Smarks int aclcnt; 1841420Smarks int mask; 1851420Smarks int slot = 0; 1861420Smarks char perm[4]; 1871535Smarks char uidp[ID_STR_MAX]; 1881535Smarks char gidp[ID_STR_MAX]; 1891420Smarks 1901420Smarks /* display ACL: assume it is sorted. */ 1911420Smarks aclcnt = aclp->acl_cnt; 1921420Smarks for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) { 1931420Smarks if (tp->a_type == CLASS_OBJ) 1941420Smarks mask = tp->a_perm; 1951420Smarks } 1961420Smarks aclcnt = aclp->acl_cnt; 1971420Smarks for (tp = aclp->acl_aclp; aclcnt--; tp++) { 1981420Smarks (void) printf(" %d:", slot++); 1991420Smarks switch (tp->a_type) { 2001420Smarks case USER: 2011420Smarks aclent_perms(tp->a_perm, perm); 2021420Smarks (void) printf("user:%s:%s\t\t", 2031535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 2041420Smarks aclent_perms((tp->a_perm & mask), perm); 2051420Smarks (void) printf("#effective:%s\n", perm); 2061420Smarks break; 2071420Smarks case USER_OBJ: 2081420Smarks /* no need to display uid */ 2091420Smarks aclent_perms(tp->a_perm, perm); 2101420Smarks (void) printf("user::%s\n", perm); 2111420Smarks break; 2121420Smarks case GROUP: 2131420Smarks aclent_perms(tp->a_perm, perm); 2141420Smarks (void) printf("group:%s:%s\t\t", 2151535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 2161420Smarks aclent_perms(tp->a_perm & mask, perm); 2171420Smarks (void) printf("#effective:%s\n", perm); 2181420Smarks break; 2191420Smarks case GROUP_OBJ: 2201420Smarks aclent_perms(tp->a_perm, perm); 2211420Smarks (void) printf("group::%s\t\t", perm); 2221420Smarks aclent_perms(tp->a_perm & mask, perm); 2231420Smarks (void) printf("#effective:%s\n", perm); 2241420Smarks break; 2251420Smarks case CLASS_OBJ: 2261420Smarks aclent_perms(tp->a_perm, perm); 2271420Smarks (void) printf("mask:%s\n", perm); 2281420Smarks break; 2291420Smarks case OTHER_OBJ: 2301420Smarks aclent_perms(tp->a_perm, perm); 2311420Smarks (void) printf("other:%s\n", perm); 2321420Smarks break; 2331420Smarks case DEF_USER: 2341420Smarks aclent_perms(tp->a_perm, perm); 2351420Smarks (void) printf("default:user:%s:%s\n", 2361535Smarks pruname(tp->a_id, uidp, sizeof (uidp), 0), perm); 2371420Smarks break; 2381420Smarks case DEF_USER_OBJ: 2391420Smarks aclent_perms(tp->a_perm, perm); 2401420Smarks (void) printf("default:user::%s\n", perm); 2411420Smarks break; 2421420Smarks case DEF_GROUP: 2431420Smarks aclent_perms(tp->a_perm, perm); 2441420Smarks (void) printf("default:group:%s:%s\n", 2451535Smarks prgname(tp->a_id, gidp, sizeof (gidp), 0), perm); 2461420Smarks break; 2471420Smarks case DEF_GROUP_OBJ: 2481420Smarks aclent_perms(tp->a_perm, perm); 2491420Smarks (void) printf("default:group::%s\n", perm); 2501420Smarks break; 2511420Smarks case DEF_CLASS_OBJ: 2521420Smarks aclent_perms(tp->a_perm, perm); 2531420Smarks (void) printf("default:mask:%s\n", perm); 2541420Smarks break; 2551420Smarks case DEF_OTHER_OBJ: 2561420Smarks aclent_perms(tp->a_perm, perm); 2571420Smarks (void) printf("default:other:%s\n", perm); 2581420Smarks break; 2591420Smarks default: 2601420Smarks (void) fprintf(stderr, 2611567Smarks dgettext(TEXT_DOMAIN, "unrecognized entry\n")); 2621420Smarks break; 2631420Smarks } 2641420Smarks } 2651420Smarks } 2661420Smarks 2671420Smarks static void 2681420Smarks split_line(char *str, int cols) 2691420Smarks { 2701420Smarks char *ptr; 2711420Smarks int len; 2721420Smarks int i; 2731420Smarks int last_split; 2741420Smarks char *pad = ""; 2751420Smarks int pad_len; 2761420Smarks 2771420Smarks len = strlen(str); 2781420Smarks ptr = str; 2791420Smarks pad_len = 0; 2801420Smarks 2811420Smarks ptr = str; 2821420Smarks last_split = 0; 2831420Smarks for (i = 0; i != len; i++) { 2841420Smarks if ((i + pad_len + 4) >= cols) { 2851420Smarks (void) printf("%s%.*s\n", pad, last_split, ptr); 2861420Smarks ptr = &ptr[last_split]; 2871420Smarks len = strlen(ptr); 2881420Smarks i = 0; 2891420Smarks pad_len = 4; 2901420Smarks pad = " "; 2911420Smarks } else { 2921420Smarks if (ptr[i] == '/' || ptr[i] == ':') { 2931420Smarks last_split = i; 2941420Smarks } 2951420Smarks } 2961420Smarks } 2971420Smarks if (i == len) { 2981420Smarks (void) printf("%s%s\n", pad, ptr); 2991420Smarks } 3001420Smarks } 3011420Smarks 302*7057Smarks /* 303*7057Smarks * compute entry type string, such as user:joe, group:staff,... 304*7057Smarks */ 305*7057Smarks static int 306*7057Smarks aclent_type_txt(dynaclstr_t *dstr, aclent_t *aclp, int flags) 3071420Smarks { 308*7057Smarks char idp[ID_STR_MAX]; 309*7057Smarks int error; 310*7057Smarks 311*7057Smarks switch (aclp->a_type) { 312*7057Smarks case DEF_USER_OBJ: 313*7057Smarks case USER_OBJ: 314*7057Smarks if (aclp->a_type == USER_OBJ) 315*7057Smarks error = str_append(dstr, "user::"); 316*7057Smarks else 317*7057Smarks error = str_append(dstr, "defaultuser::"); 318*7057Smarks break; 319*7057Smarks 320*7057Smarks case DEF_USER: 321*7057Smarks case USER: 322*7057Smarks if (aclp->a_type == USER) 323*7057Smarks error = str_append(dstr, "user:"); 324*7057Smarks else 325*7057Smarks error = str_append(dstr, "defaultuser:"); 326*7057Smarks if (error) 327*7057Smarks break; 328*7057Smarks error = str_append(dstr, pruname(aclp->a_id, idp, 329*7057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 330*7057Smarks if (error == 0) 331*7057Smarks error = str_append(dstr, ":"); 332*7057Smarks break; 333*7057Smarks 334*7057Smarks case DEF_GROUP_OBJ: 335*7057Smarks case GROUP_OBJ: 336*7057Smarks if (aclp->a_type == GROUP_OBJ) 337*7057Smarks error = str_append(dstr, "group::"); 338*7057Smarks else 339*7057Smarks error = str_append(dstr, "defaultgroup::"); 340*7057Smarks break; 3411420Smarks 342*7057Smarks case DEF_GROUP: 343*7057Smarks case GROUP: 344*7057Smarks if (aclp->a_type == GROUP) 345*7057Smarks error = str_append(dstr, "group:"); 346*7057Smarks else 347*7057Smarks error = str_append(dstr, "defaultgroup:"); 348*7057Smarks if (error) 349*7057Smarks break; 350*7057Smarks error = str_append(dstr, prgname(aclp->a_id, idp, 351*7057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 352*7057Smarks if (error == 0) 353*7057Smarks error = str_append(dstr, ":"); 354*7057Smarks break; 355*7057Smarks 356*7057Smarks case DEF_CLASS_OBJ: 357*7057Smarks case CLASS_OBJ: 358*7057Smarks if (aclp->a_type == CLASS_OBJ) 359*7057Smarks error = str_append(dstr, "mask:"); 360*7057Smarks else 361*7057Smarks error = str_append(dstr, "defaultmask:"); 362*7057Smarks break; 3631420Smarks 364*7057Smarks case DEF_OTHER_OBJ: 365*7057Smarks case OTHER_OBJ: 366*7057Smarks if (aclp->a_type == OTHER_OBJ) 367*7057Smarks error = str_append(dstr, "other:"); 368*7057Smarks else 369*7057Smarks error = str_append(dstr, "defaultother:"); 370*7057Smarks break; 371*7057Smarks 372*7057Smarks default: 373*7057Smarks error = 1; 374*7057Smarks break; 375*7057Smarks } 376*7057Smarks 377*7057Smarks return (error); 378*7057Smarks } 379*7057Smarks 380*7057Smarks /* 381*7057Smarks * compute entry type string such as, owner@:, user:joe, group:staff,... 382*7057Smarks */ 383*7057Smarks static int 384*7057Smarks ace_type_txt(dynaclstr_t *dynstr, ace_t *acep, int flags) 385*7057Smarks { 386*7057Smarks char idp[ID_STR_MAX]; 387*7057Smarks int error; 388*7057Smarks char *sidp = NULL; 3891420Smarks 3901420Smarks switch (acep->a_flags & ACE_TYPE_FLAGS) { 3911420Smarks case ACE_OWNER: 392*7057Smarks error = str_append(dynstr, OWNERAT_TXT); 3931420Smarks break; 3941420Smarks 3951420Smarks case ACE_GROUP|ACE_IDENTIFIER_GROUP: 396*7057Smarks error = str_append(dynstr, GROUPAT_TXT); 3971420Smarks break; 3981420Smarks 3991420Smarks case ACE_IDENTIFIER_GROUP: 400*7057Smarks if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) { 401*7057Smarks if (error = str_append(dynstr, 402*7057Smarks GROUPSID_TXT)) 403*7057Smarks break; 404*7057Smarks error = str_append(dynstr, prsidname(acep->a_who, 405*7057Smarks B_FALSE, &sidp, flags & ACL_NORESOLVE)); 406*7057Smarks } else { 407*7057Smarks if (error = str_append(dynstr, GROUP_TXT)) 408*7057Smarks break; 409*7057Smarks error = str_append(dynstr, prgname(acep->a_who, idp, 410*7057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 411*7057Smarks } 412*7057Smarks if (error == 0) 413*7057Smarks error = str_append(dynstr, ":"); 4141420Smarks break; 4151420Smarks 4161420Smarks case ACE_EVERYONE: 417*7057Smarks error = str_append(dynstr, EVERYONEAT_TXT); 4181420Smarks break; 4191420Smarks 4201420Smarks case 0: 421*7057Smarks if ((flags & ACL_SID_FMT) && acep->a_who > MAXUID) { 422*7057Smarks if (error = str_append(dynstr, USERSID_TXT)) 423*7057Smarks break; 424*7057Smarks error = str_append(dynstr, prsidname(acep->a_who, 425*7057Smarks B_TRUE, &sidp, flags & ACL_NORESOLVE)); 426*7057Smarks } else { 427*7057Smarks if (error = str_append(dynstr, USER_TXT)) 428*7057Smarks break; 429*7057Smarks error = str_append(dynstr, pruname(acep->a_who, idp, 430*7057Smarks sizeof (idp), flags & ACL_NORESOLVE)); 431*7057Smarks } 432*7057Smarks if (error == 0) 433*7057Smarks error = str_append(dynstr, ":"); 434*7057Smarks break; 435*7057Smarks default: 436*7057Smarks error = 0; 4371420Smarks break; 4381420Smarks } 4391420Smarks 440*7057Smarks if (sidp) 441*7057Smarks free(sidp); 442*7057Smarks return (error); 4431420Smarks } 4441420Smarks 445*7057Smarks /* 446*7057Smarks * compute string of permissions, such as read_data/write_data or 447*7057Smarks * rwxp,... 448*7057Smarks * The format depends on the flags field which indicates whether the compact 449*7057Smarks * or verbose format should be used. 450*7057Smarks */ 451*7057Smarks static int 452*7057Smarks ace_perm_txt(dynaclstr_t *dstr, uint32_t mask, 4531420Smarks uint32_t iflags, int isdir, int flags) 4541420Smarks { 455*7057Smarks int error = 0; 4561420Smarks 4571420Smarks if (flags & ACL_COMPACT_FMT) { 458*7057Smarks char buf[16]; 459789Sahrens 4601420Smarks if (mask & ACE_READ_DATA) 4611420Smarks buf[0] = 'r'; 4621420Smarks else 4631420Smarks buf[0] = '-'; 4641420Smarks if (mask & ACE_WRITE_DATA) 4651420Smarks buf[1] = 'w'; 4661420Smarks else 4671420Smarks buf[1] = '-'; 4681420Smarks if (mask & ACE_EXECUTE) 4691420Smarks buf[2] = 'x'; 4701420Smarks else 4711420Smarks buf[2] = '-'; 4721420Smarks if (mask & ACE_APPEND_DATA) 4731420Smarks buf[3] = 'p'; 4741420Smarks else 4751420Smarks buf[3] = '-'; 4761420Smarks if (mask & ACE_DELETE) 4771420Smarks buf[4] = 'd'; 4781420Smarks else 4791420Smarks buf[4] = '-'; 4801420Smarks if (mask & ACE_DELETE_CHILD) 4811420Smarks buf[5] = 'D'; 4821420Smarks else 4831420Smarks buf[5] = '-'; 4841420Smarks if (mask & ACE_READ_ATTRIBUTES) 4851420Smarks buf[6] = 'a'; 4861420Smarks else 4871420Smarks buf[6] = '-'; 4881420Smarks if (mask & ACE_WRITE_ATTRIBUTES) 4891420Smarks buf[7] = 'A'; 4901420Smarks else 4911420Smarks buf[7] = '-'; 4921420Smarks if (mask & ACE_READ_NAMED_ATTRS) 4931420Smarks buf[8] = 'R'; 4941420Smarks else 4951420Smarks buf[8] = '-'; 4961420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) 4971420Smarks buf[9] = 'W'; 4981420Smarks else 4991420Smarks buf[9] = '-'; 5001420Smarks if (mask & ACE_READ_ACL) 5011420Smarks buf[10] = 'c'; 5021420Smarks else 5031420Smarks buf[10] = '-'; 5041420Smarks if (mask & ACE_WRITE_ACL) 5051420Smarks buf[11] = 'C'; 5061420Smarks else 5071420Smarks buf[11] = '-'; 5081420Smarks if (mask & ACE_WRITE_OWNER) 5091420Smarks buf[12] = 'o'; 5101420Smarks else 5111420Smarks buf[12] = '-'; 5121420Smarks if (mask & ACE_SYNCHRONIZE) 5131420Smarks buf[13] = 's'; 5141420Smarks else 5151420Smarks buf[13] = '-'; 516*7057Smarks buf[14] = ':'; 517*7057Smarks buf[15] = '\0'; 518*7057Smarks error = str_append(dstr, buf); 5191420Smarks } else { 5201420Smarks /* 5211420Smarks * If ACE is a directory, but inheritance indicates its 5221420Smarks * for a file then print permissions for file rather than 5231420Smarks * dir. 5241420Smarks */ 5251420Smarks if (isdir) { 5261420Smarks if (mask & ACE_LIST_DIRECTORY) { 5271420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 528*7057Smarks error = str_append(dstr, 529*7057Smarks READ_DATA_TXT); 5301420Smarks } else { 531*7057Smarks error = 532*7057Smarks str_append(dstr, READ_DIR_TXT); 5331420Smarks } 5341420Smarks } 535*7057Smarks if (error == 0 && (mask & ACE_ADD_FILE)) { 5361420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 537*7057Smarks error = 538*7057Smarks str_append(dstr, WRITE_DATA_TXT); 5391420Smarks } else { 540*7057Smarks error = 541*7057Smarks str_append(dstr, ADD_FILE_TXT); 5421420Smarks } 5431420Smarks } 544*7057Smarks if (error == 0 && (mask & ACE_ADD_SUBDIRECTORY)) { 5451420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 546*7057Smarks error = str_append(dstr, 547*7057Smarks APPEND_DATA_TXT); 5481420Smarks } else { 549*7057Smarks error = str_append(dstr, 550*7057Smarks ADD_DIR_TXT); 5511420Smarks } 5521420Smarks } 5531420Smarks } else { 5541420Smarks if (mask & ACE_READ_DATA) { 555*7057Smarks error = str_append(dstr, READ_DATA_TXT); 5561420Smarks } 557*7057Smarks if (error == 0 && (mask & ACE_WRITE_DATA)) { 558*7057Smarks error = str_append(dstr, WRITE_DATA_TXT); 5591420Smarks } 560*7057Smarks if (error == 0 && (mask & ACE_APPEND_DATA)) { 561*7057Smarks error = str_append(dstr, APPEND_DATA_TXT); 5621420Smarks } 5631420Smarks } 564*7057Smarks if (error == 0 && (mask & ACE_READ_NAMED_ATTRS)) { 565*7057Smarks error = str_append(dstr, READ_XATTR_TXT); 5661420Smarks } 567*7057Smarks if (error == 0 && (mask & ACE_WRITE_NAMED_ATTRS)) { 568*7057Smarks error = str_append(dstr, WRITE_XATTR_TXT); 5691420Smarks } 570*7057Smarks if (error == 0 && (mask & ACE_EXECUTE)) { 571*7057Smarks error = str_append(dstr, EXECUTE_TXT); 5721420Smarks } 573*7057Smarks if (error == 0 && (mask & ACE_DELETE_CHILD)) { 574*7057Smarks error = str_append(dstr, DELETE_CHILD_TXT); 5751420Smarks } 576*7057Smarks if (error == 0 && (mask & ACE_READ_ATTRIBUTES)) { 577*7057Smarks error = str_append(dstr, READ_ATTRIBUTES_TXT); 5781420Smarks } 579*7057Smarks if (error == 0 && (mask & ACE_WRITE_ATTRIBUTES)) { 580*7057Smarks error = str_append(dstr, WRITE_ATTRIBUTES_TXT); 5811420Smarks } 582*7057Smarks if (error == 0 && (mask & ACE_DELETE)) { 583*7057Smarks error = str_append(dstr, DELETE_TXT); 5841420Smarks } 585*7057Smarks if (error == 0 && (mask & ACE_READ_ACL)) { 586*7057Smarks error = str_append(dstr, READ_ACL_TXT); 5871420Smarks } 588*7057Smarks if (error == 0 && (mask & ACE_WRITE_ACL)) { 589*7057Smarks error = str_append(dstr, WRITE_ACL_TXT); 5901420Smarks } 591*7057Smarks if (error == 0 && (mask & ACE_WRITE_OWNER)) { 592*7057Smarks error = str_append(dstr, WRITE_OWNER_TXT); 5931420Smarks } 594*7057Smarks if (error == 0 && (mask & ACE_SYNCHRONIZE)) { 595*7057Smarks error = str_append(dstr, SYNCHRONIZE_TXT); 5961420Smarks } 597*7057Smarks if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') { 598*7057Smarks dstr->d_aclexport[--dstr->d_pos] = '\0'; 599*7057Smarks } 600*7057Smarks if (error == 0) 601*7057Smarks error = str_append(dstr, ":"); 6021420Smarks } 603*7057Smarks return (error); 6041420Smarks } 6051420Smarks 606*7057Smarks /* 607*7057Smarks * compute string of access type, such as allow, deny, ... 608*7057Smarks */ 609*7057Smarks static int 610*7057Smarks ace_access_txt(dynaclstr_t *dstr, int type) 6111420Smarks { 612*7057Smarks int error; 6131420Smarks 614*7057Smarks if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) 615*7057Smarks error = str_append(dstr, ALLOW_TXT); 616*7057Smarks else if (type == ACE_ACCESS_DENIED_ACE_TYPE) 617*7057Smarks error = str_append(dstr, DENY_TXT); 618*7057Smarks else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) 619*7057Smarks error = str_append(dstr, AUDIT_TXT); 620*7057Smarks else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) 621*7057Smarks error = str_append(dstr, ALARM_TXT); 622*7057Smarks else 623*7057Smarks error = str_append(dstr, UNKNOWN_TXT); 6241420Smarks 625*7057Smarks return (error); 6261420Smarks } 6271420Smarks 628*7057Smarks static int 629*7057Smarks ace_inherit_txt(dynaclstr_t *dstr, uint32_t iflags, int flags) 6301420Smarks { 631*7057Smarks int error = 0; 632789Sahrens 6331420Smarks if (flags & ACL_COMPACT_FMT) { 634*7057Smarks char buf[9]; 635*7057Smarks 6361420Smarks if (iflags & ACE_FILE_INHERIT_ACE) 6371420Smarks buf[0] = 'f'; 6381420Smarks else 6391420Smarks buf[0] = '-'; 6401420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) 6411420Smarks buf[1] = 'd'; 6421420Smarks else 6431420Smarks buf[1] = '-'; 6441420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) 6451420Smarks buf[2] = 'i'; 6461420Smarks else 6471420Smarks buf[2] = '-'; 6481420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) 6491420Smarks buf[3] = 'n'; 6501420Smarks else 6511420Smarks buf[3] = '-'; 6521420Smarks if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 6531420Smarks buf[4] = 'S'; 6541420Smarks else 6551420Smarks buf[4] = '-'; 6561420Smarks if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) 6571420Smarks buf[5] = 'F'; 6581420Smarks else 6591420Smarks buf[5] = '-'; 6605331Samw if (iflags & ACE_INHERITED_ACE) 6615331Samw buf[6] = 'I'; 6625331Samw else 6635331Samw buf[6] = '-'; 664*7057Smarks buf[7] = ':'; 665*7057Smarks buf[8] = '\0'; 666*7057Smarks error = str_append(dstr, buf); 6671420Smarks } else { 6681420Smarks if (iflags & ACE_FILE_INHERIT_ACE) { 669*7057Smarks error = str_append(dstr, FILE_INHERIT_TXT); 6701420Smarks } 671*7057Smarks if (error == 0 && (iflags & ACE_DIRECTORY_INHERIT_ACE)) { 672*7057Smarks error = str_append(dstr, DIR_INHERIT_TXT); 6731420Smarks } 674*7057Smarks if (error == 0 && (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) { 675*7057Smarks error = str_append(dstr, NO_PROPAGATE_TXT); 6761420Smarks } 677*7057Smarks if (error == 0 && (iflags & ACE_INHERIT_ONLY_ACE)) { 678*7057Smarks error = str_append(dstr, INHERIT_ONLY_TXT); 6791420Smarks } 680*7057Smarks if (error == 0 && (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)) { 681*7057Smarks error = str_append(dstr, SUCCESSFUL_ACCESS_TXT); 6825331Samw } 683*7057Smarks if (error == 0 && (iflags & ACE_FAILED_ACCESS_ACE_FLAG)) { 684*7057Smarks error = str_append(dstr, FAILED_ACCESS_TXT); 6855331Samw } 686*7057Smarks if (error == 0 && (iflags & ACE_INHERITED_ACE)) { 687*7057Smarks error = str_append(dstr, INHERITED_ACE_TXT); 6885331Samw } 689*7057Smarks if (error == 0 && dstr->d_aclexport[dstr->d_pos-1] == '/') { 690*7057Smarks dstr->d_aclexport[--dstr->d_pos] = '\0'; 691*7057Smarks error = str_append(dstr, ":"); 692*7057Smarks } 6931420Smarks } 6941420Smarks 695*7057Smarks return (error); 696789Sahrens } 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate /* 6990Sstevel@tonic-gate * Convert internal acl representation to external representation. 7000Sstevel@tonic-gate * 7010Sstevel@tonic-gate * The length of a non-owning user name or non-owning group name ie entries 7020Sstevel@tonic-gate * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We 7030Sstevel@tonic-gate * thus check the length of these entries, and if greater than LOGNAME_MAX, 7040Sstevel@tonic-gate * we realloc() via increase_length(). 7050Sstevel@tonic-gate * 7060Sstevel@tonic-gate * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always 7070Sstevel@tonic-gate * adhered to. 7080Sstevel@tonic-gate */ 7091420Smarks 7101420Smarks /* 7111420Smarks * acltotext() converts each ACL entry to look like this: 7121420Smarks * 7131420Smarks * entry_type:uid^gid^name:perms[:id] 7141420Smarks * 7151420Smarks * The maximum length of entry_type is 14 ("defaultgroup::" and 7161420Smarks * "defaultother::") hence ENTRYTYPELEN is set to 14. 7171420Smarks * 7181420Smarks * The max length of a uid^gid^name entry (in theory) is 8, hence we use, 7191420Smarks * however the ID could be a number so we therefore use ID_STR_MAX 7201420Smarks * 7211420Smarks * The length of a perms entry is 4 to allow for the comma appended to each 7221420Smarks * to each acl entry. Hence PERMS is set to 4. 7231420Smarks */ 7241420Smarks 7251420Smarks #define ENTRYTYPELEN 14 7261420Smarks #define PERMS 4 7271420Smarks #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX) 7281420Smarks 7290Sstevel@tonic-gate char * 7301420Smarks aclent_acltotext(aclent_t *aclp, int aclcnt, int flags) 7310Sstevel@tonic-gate { 732*7057Smarks dynaclstr_t *dstr; 7330Sstevel@tonic-gate char *aclexport; 734*7057Smarks int i; 735*7057Smarks int error = 0; 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate if (aclp == NULL) 7380Sstevel@tonic-gate return (NULL); 739*7057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 7400Sstevel@tonic-gate return (NULL); 741*7057Smarks dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE; 742*7057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 7430Sstevel@tonic-gate free(dstr); 7440Sstevel@tonic-gate return (NULL); 7450Sstevel@tonic-gate } 746*7057Smarks *dstr->d_aclexport = '\0'; 747*7057Smarks dstr->d_pos = 0; 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate for (i = 0; i < aclcnt; i++, aclp++) { 750*7057Smarks if (error = aclent_type_txt(dstr, aclp, flags)) 7510Sstevel@tonic-gate break; 752*7057Smarks if (error = aclent_perm_txt(dstr, aclp->a_perm)) 7530Sstevel@tonic-gate break; 7541420Smarks 7551420Smarks if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) || 7561420Smarks (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) || 7571420Smarks (aclp->a_type == DEF_GROUP))) { 758*7057Smarks char id[ID_STR_MAX], *idstr; 759*7057Smarks 760*7057Smarks if (error = str_append(dstr, ":")) 761*7057Smarks break; 7621420Smarks id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */ 7631420Smarks idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]); 764*7057Smarks if (error = str_append(dstr, idstr)) 765*7057Smarks break; 7661420Smarks } 7670Sstevel@tonic-gate if (i < aclcnt - 1) 768*7057Smarks if (error = str_append(dstr, ",")) 769*7057Smarks break; 7700Sstevel@tonic-gate } 771*7057Smarks if (error) { 772*7057Smarks if (dstr->d_aclexport) 773*7057Smarks free(dstr->d_aclexport); 774*7057Smarks } else { 775*7057Smarks aclexport = dstr->d_aclexport; 776*7057Smarks } 7770Sstevel@tonic-gate free(dstr); 7780Sstevel@tonic-gate return (aclexport); 7790Sstevel@tonic-gate } 7800Sstevel@tonic-gate 7811420Smarks char * 7821420Smarks acltotext(aclent_t *aclp, int aclcnt) 7830Sstevel@tonic-gate { 7841420Smarks return (aclent_acltotext(aclp, aclcnt, 0)); 7851420Smarks } 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate 788789Sahrens aclent_t * 789789Sahrens aclfromtext(char *aclstr, int *aclcnt) 790789Sahrens { 791789Sahrens acl_t *aclp; 792789Sahrens aclent_t *aclentp; 793789Sahrens int error; 794789Sahrens 7951420Smarks error = acl_fromtext(aclstr, &aclp); 796789Sahrens if (error) 797789Sahrens return (NULL); 798789Sahrens 799789Sahrens aclentp = aclp->acl_aclp; 800789Sahrens aclp->acl_aclp = NULL; 8011420Smarks *aclcnt = aclp->acl_cnt; 802789Sahrens 8031420Smarks acl_free(aclp); 804789Sahrens return (aclentp); 805789Sahrens } 806789Sahrens 807789Sahrens 808*7057Smarks /* 809*7057Smarks * returns a character position index of the start of the newly 810*7057Smarks * appended string. Returns -1 if operation couldn't be completed. 811*7057Smarks */ 812*7057Smarks static int 813*7057Smarks str_append(dynaclstr_t *dstr, char *newstr) 8140Sstevel@tonic-gate { 815*7057Smarks size_t len = strlen(newstr); 816*7057Smarks 817*7057Smarks if ((len + dstr->d_pos) >= dstr->d_bufsize) { 818*7057Smarks dstr->d_aclexport = realloc(dstr->d_aclexport, 819*7057Smarks dstr->d_bufsize + len + 1); 820*7057Smarks if (dstr->d_aclexport == NULL) 821*7057Smarks return (1); 822*7057Smarks dstr->d_bufsize += len; 823*7057Smarks } 824*7057Smarks (void) strcat(&dstr->d_aclexport[dstr->d_pos], newstr); 825*7057Smarks dstr->d_pos += len; 826*7057Smarks return (0); 8270Sstevel@tonic-gate } 8280Sstevel@tonic-gate 829*7057Smarks static int 830*7057Smarks aclent_perm_txt(dynaclstr_t *dstr, o_mode_t perm) 8310Sstevel@tonic-gate { 832*7057Smarks char buf[4]; 8330Sstevel@tonic-gate 834*7057Smarks if (perm & S_IROTH) 835*7057Smarks buf[0] = 'r'; 836*7057Smarks else 837*7057Smarks buf[0] = '-'; 838*7057Smarks if (perm & S_IWOTH) 839*7057Smarks buf[1] = 'w'; 840*7057Smarks else 841*7057Smarks buf[1] = '-'; 842*7057Smarks if (perm & S_IXOTH) 843*7057Smarks buf[2] = 'x'; 844*7057Smarks else 845*7057Smarks buf[2] = '-'; 846*7057Smarks buf[3] = '\0'; 847*7057Smarks return (str_append(dstr, buf)); 8480Sstevel@tonic-gate } 849789Sahrens 850789Sahrens /* 8511420Smarks * ace_acltotext() convert each ace formatted acl to look like this: 852789Sahrens * 8531420Smarks * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,] 854789Sahrens * 855789Sahrens * The maximum length of entry_type is 5 ("group") 856789Sahrens * 8571420Smarks * The max length of a uid^gid^name entry (in theory) is 8, 8581420Smarks * however id could be a number so we therefore use ID_STR_MAX 859789Sahrens * 860789Sahrens * The length of a perms entry is 144 i.e read_data/write_data... 861789Sahrens * to each acl entry. 862789Sahrens * 8635331Samw * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access 8645331Samw * /failed_access 865789Sahrens * 866789Sahrens */ 867789Sahrens 868789Sahrens #define ACE_ENTRYTYPLEN 6 8695331Samw #define IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \ 8705331Samw "successful_access/failed_access/inherited" 8715331Samw #define IFLAGS_SIZE (sizeof (IFLAGS_STR) - 1) 8721420Smarks #define ACCESS_TYPE_SIZE 7 /* if unknown */ 873789Sahrens #define COLON_CNT 3 874789Sahrens #define PERMS_LEN 216 8755331Samw #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \ 8761420Smarks ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX) 877789Sahrens 878789Sahrens static char * 8791420Smarks ace_acltotext(acl_t *aceaclp, int flags) 880789Sahrens { 881789Sahrens ace_t *aclp = aceaclp->acl_aclp; 882789Sahrens int aclcnt = aceaclp->acl_cnt; 883*7057Smarks int i; 884*7057Smarks int error = 0; 885*7057Smarks int isdir = (aceaclp->acl_flags & ACL_IS_DIR); 886*7057Smarks dynaclstr_t *dstr; 887789Sahrens char *aclexport; 888789Sahrens 889789Sahrens if (aclp == NULL) 890789Sahrens return (NULL); 891789Sahrens 892*7057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 893*7057Smarks return (NULL); 894*7057Smarks dstr->d_bufsize = aclcnt * ACL_ENTRY_SIZE; 895*7057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 896*7057Smarks free(dstr); 897*7057Smarks return (NULL); 898*7057Smarks } 899*7057Smarks *dstr->d_aclexport = '\0'; 900*7057Smarks dstr->d_pos = 0; 901*7057Smarks 902789Sahrens for (i = 0; i < aclcnt; i++, aclp++) { 9031420Smarks 904*7057Smarks if (error = ace_type_txt(dstr, aclp, flags)) 905*7057Smarks break; 906*7057Smarks if (error = ace_perm_txt(dstr, aclp->a_access_mask, 907*7057Smarks aclp->a_flags, isdir, flags)) 908*7057Smarks break; 909*7057Smarks if (error = ace_inherit_txt(dstr, aclp->a_flags, flags)) 910*7057Smarks break; 911*7057Smarks if (error = ace_access_txt(dstr, aclp->a_type)) 912*7057Smarks break; 913789Sahrens 9141420Smarks if ((flags & ACL_APPEND_ID) && 9151420Smarks (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) || 9161420Smarks ((aclp->a_flags & ACE_TYPE_FLAGS) == 9171420Smarks ACE_IDENTIFIER_GROUP))) { 918*7057Smarks char id[ID_STR_MAX], *idstr; 919*7057Smarks 920*7057Smarks if (error = str_append(dstr, ":")) 921*7057Smarks break; 9221420Smarks id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */ 923*7057Smarks idstr = lltostr((aclp->a_who > MAXUID && 924*7057Smarks !(flags & ACL_NORESOLVE)) ? UID_NOBODY : 925*7057Smarks aclp->a_who, &id[ID_STR_MAX - 1]); 926*7057Smarks if (error = str_append(dstr, idstr)) 927*7057Smarks break; 928789Sahrens } 9291420Smarks if (i < aclcnt - 1) { 930*7057Smarks if (error = str_append(dstr, ",")) 931*7057Smarks break; 932789Sahrens } 933789Sahrens } 934*7057Smarks if (error) { 935*7057Smarks if (dstr->d_aclexport) 936*7057Smarks free(dstr->d_aclexport); 937*7057Smarks } else { 938*7057Smarks aclexport = dstr->d_aclexport; 939*7057Smarks } 940*7057Smarks free(dstr); 941789Sahrens return (aclexport); 942789Sahrens } 943789Sahrens 9441420Smarks char * 9451420Smarks acl_totext(acl_t *aclp, int flags) 946789Sahrens { 9471420Smarks char *txtp; 948789Sahrens 949789Sahrens if (aclp == NULL) 950789Sahrens return (NULL); 951789Sahrens 952789Sahrens switch (aclp->acl_type) { 953789Sahrens case ACE_T: 9541420Smarks txtp = ace_acltotext(aclp, flags); 9551420Smarks break; 956789Sahrens case ACLENT_T: 9571420Smarks txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags); 9581420Smarks break; 959789Sahrens } 9601420Smarks 9611420Smarks return (txtp); 962789Sahrens } 963789Sahrens 964789Sahrens int 965789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp) 966789Sahrens { 9671420Smarks int error; 9681420Smarks char *buf; 9691420Smarks 9701420Smarks buf = malloc(strlen(acltextp) + 2); 9711420Smarks if (buf == NULL) 9721420Smarks return (EACL_MEM_ERROR); 9731420Smarks strcpy(buf, acltextp); 9741420Smarks strcat(buf, "\n"); 9751420Smarks yybuf = buf; 9761420Smarks yyreset(); 9771420Smarks error = yyparse(); 9781420Smarks free(buf); 9791420Smarks 9801420Smarks if (yyacl) { 9811420Smarks if (error == 0) 9821420Smarks *ret_aclp = yyacl; 9831420Smarks else { 9841420Smarks acl_free(yyacl); 9851420Smarks } 9861420Smarks yyacl = NULL; 9871420Smarks } 9881420Smarks return (error); 9891420Smarks } 9901420Smarks 9911420Smarks int 9921420Smarks acl_parse(const char *acltextp, acl_t **aclp) 9931420Smarks { 994789Sahrens int error; 995789Sahrens 9961420Smarks yyinteractive = 1; 9971420Smarks error = acl_fromtext(acltextp, aclp); 9981420Smarks yyinteractive = 0; 9991420Smarks return (error); 10001420Smarks } 10011420Smarks 10021420Smarks static void 10031420Smarks ace_compact_printacl(acl_t *aclp) 10041420Smarks { 10051420Smarks int cnt; 10061420Smarks ace_t *acep; 1007*7057Smarks dynaclstr_t *dstr; 1008*7057Smarks int len; 1009789Sahrens 1010*7057Smarks if ((dstr = malloc(sizeof (dynaclstr_t))) == NULL) 1011*7057Smarks return; 1012*7057Smarks dstr->d_bufsize = ACE_ENTRY_SIZE; 1013*7057Smarks if ((dstr->d_aclexport = malloc(dstr->d_bufsize)) == NULL) { 1014*7057Smarks free(dstr); 1015*7057Smarks return; 1016*7057Smarks } 1017*7057Smarks *dstr->d_aclexport = '\0'; 1018*7057Smarks 1019*7057Smarks dstr->d_pos = 0; 10201420Smarks for (cnt = 0, acep = aclp->acl_aclp; 10211420Smarks cnt != aclp->acl_cnt; cnt++, acep++) { 1022*7057Smarks dstr->d_aclexport[0] = '\0'; 1023*7057Smarks dstr->d_pos = 0; 1024*7057Smarks 1025*7057Smarks if (ace_type_txt(dstr, acep, 0)) 1026*7057Smarks break; 1027*7057Smarks len = strlen(&dstr->d_aclexport[0]); 1028*7057Smarks if (ace_perm_txt(dstr, acep->a_access_mask, acep->a_flags, 1029*7057Smarks aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT)) 1030*7057Smarks break; 1031*7057Smarks if (ace_inherit_txt(dstr, acep->a_flags, ACL_COMPACT_FMT)) 1032*7057Smarks break; 1033*7057Smarks if (ace_access_txt(dstr, acep->a_type) == -1) 1034*7057Smarks break; 1035*7057Smarks (void) printf(" %20.*s%s\n", len, dstr->d_aclexport, 1036*7057Smarks &dstr->d_aclexport[len]); 10371420Smarks } 1038*7057Smarks 1039*7057Smarks if (dstr->d_aclexport) 1040*7057Smarks free(dstr->d_aclexport); 1041*7057Smarks free(dstr); 10421420Smarks } 1043789Sahrens 10441420Smarks static void 10451420Smarks ace_printacl(acl_t *aclp, int cols, int compact) 10461420Smarks { 10471420Smarks int slot = 0; 10481420Smarks char *token; 10491420Smarks char *acltext; 10501420Smarks 10511420Smarks if (compact) { 10521420Smarks ace_compact_printacl(aclp); 10531420Smarks return; 1054789Sahrens } 1055789Sahrens 10561420Smarks acltext = acl_totext(aclp, 0); 10571420Smarks 10581420Smarks if (acltext == NULL) 10591420Smarks return; 10601420Smarks 10611420Smarks token = strtok(acltext, ","); 10621420Smarks if (token == NULL) { 10631420Smarks free(acltext); 10641420Smarks return; 1065789Sahrens } 1066789Sahrens 10671420Smarks do { 10681420Smarks (void) printf(" %d:", slot++); 10691420Smarks split_line(token, cols - 5); 10701420Smarks } while (token = strtok(NULL, ",")); 10711420Smarks free(acltext); 10721420Smarks } 10731420Smarks 10741420Smarks /* 10751420Smarks * pretty print an ACL. 10761420Smarks * For aclent_t ACL's the format is 10771420Smarks * similar to the old format used by getfacl, 10781420Smarks * with the addition of adding a "slot" number 10791420Smarks * before each entry. 10801420Smarks * 10811420Smarks * for ace_t ACL's the cols variable will break up 10821420Smarks * the long lines into multiple lines and will also 10831420Smarks * print a "slot" number. 10841420Smarks */ 10851420Smarks void 10861420Smarks acl_printacl(acl_t *aclp, int cols, int compact) 10871420Smarks { 10881420Smarks 10891420Smarks switch (aclp->acl_type) { 10901420Smarks case ACLENT_T: 10911420Smarks aclent_printacl(aclp); 10921420Smarks break; 10931420Smarks case ACE_T: 10941420Smarks ace_printacl(aclp, cols, compact); 10951420Smarks break; 10961420Smarks } 10971420Smarks } 10981420Smarks 10991420Smarks typedef struct value_table { 11001420Smarks char p_letter; /* perm letter such as 'r' */ 11011420Smarks uint32_t p_value; /* value for perm when pletter found */ 11021420Smarks } value_table_t; 11031420Smarks 11041420Smarks /* 11055331Samw * The permission tables are laid out in positional order 11061420Smarks * a '-' character will indicate a permission at a given 11071420Smarks * position is not specified. The '-' is not part of the 11081420Smarks * table, but will be checked for in the permission computation 11091420Smarks * routine. 11101420Smarks */ 11115331Samw value_table_t ace_perm_table[] = { 11121420Smarks { 'r', ACE_READ_DATA}, 11131420Smarks { 'w', ACE_WRITE_DATA}, 11141420Smarks { 'x', ACE_EXECUTE}, 11151420Smarks { 'p', ACE_APPEND_DATA}, 11161420Smarks { 'd', ACE_DELETE}, 11171420Smarks { 'D', ACE_DELETE_CHILD}, 11181420Smarks { 'a', ACE_READ_ATTRIBUTES}, 11191420Smarks { 'A', ACE_WRITE_ATTRIBUTES}, 11201420Smarks { 'R', ACE_READ_NAMED_ATTRS}, 11211420Smarks { 'W', ACE_WRITE_NAMED_ATTRS}, 11221420Smarks { 'c', ACE_READ_ACL}, 11231420Smarks { 'C', ACE_WRITE_ACL}, 11241420Smarks { 'o', ACE_WRITE_OWNER}, 11251420Smarks { 's', ACE_SYNCHRONIZE} 11261420Smarks }; 11271420Smarks 11285331Samw #define ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t)) 11291420Smarks 11305331Samw value_table_t aclent_perm_table[] = { 11311420Smarks { 'r', S_IROTH}, 11321420Smarks { 'w', S_IWOTH}, 11331420Smarks { 'x', S_IXOTH} 11341420Smarks }; 11351420Smarks 11365331Samw #define ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t)) 11375331Samw 11385331Samw value_table_t inherit_table[] = { 11391420Smarks {'f', ACE_FILE_INHERIT_ACE}, 11401420Smarks {'d', ACE_DIRECTORY_INHERIT_ACE}, 11411420Smarks {'i', ACE_INHERIT_ONLY_ACE}, 11421420Smarks {'n', ACE_NO_PROPAGATE_INHERIT_ACE}, 11431420Smarks {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 11445331Samw {'F', ACE_FAILED_ACCESS_ACE_FLAG}, 11455331Samw {'I', ACE_INHERITED_ACE} 11461420Smarks }; 11471420Smarks 11485331Samw #define IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t)) 11496269Smarks #define IFLAG_COUNT_V1 6 /* Older version compatibility */ 11505331Samw 11511420Smarks /* 11521420Smarks * compute value from a permission table or inheritance table 11531420Smarks * based on string passed in. If positional is set then 11541420Smarks * string must match order in permtab, otherwise any order 11551420Smarks * is allowed. 11561420Smarks */ 11571420Smarks int 11581420Smarks compute_values(value_table_t *permtab, int count, 11591420Smarks char *permstr, int positional, uint32_t *mask) 11601420Smarks { 11611420Smarks uint32_t perm_val = 0; 11621420Smarks char *pstr; 11631420Smarks int i, found; 11641420Smarks 11651420Smarks if (count < 0) 11661420Smarks return (1); 11671420Smarks 11681420Smarks if (positional) { 11691420Smarks for (i = 0, pstr = permstr; i != count && pstr && 11701420Smarks *pstr; i++, pstr++) { 11711420Smarks if (*pstr == permtab[i].p_letter) { 11721420Smarks perm_val |= permtab[i].p_value; 11731420Smarks } else if (*pstr != '-') { 11741420Smarks return (1); 11751420Smarks } 1176789Sahrens } 11771420Smarks } else { /* random order single letters with no '-' */ 11781420Smarks for (pstr = permstr; pstr && *pstr; pstr++) { 11791420Smarks for (found = 0, i = 0; i != count; i++) { 11801420Smarks if (*pstr == permtab[i].p_letter) { 11811420Smarks perm_val |= permtab[i].p_value; 11821420Smarks found = 1; 11831420Smarks break; 11841420Smarks } 11851420Smarks } 11861420Smarks if (found == 0) 11871420Smarks return (1); 11881420Smarks } 1189789Sahrens } 1190789Sahrens 11911420Smarks *mask = perm_val; 11921420Smarks return (0); 11931420Smarks } 1194789Sahrens 11956269Smarks 11966269Smarks int 11976269Smarks ace_inherit_helper(char *str, uint32_t *imask, int table_length) 11986269Smarks { 11996269Smarks int rc = 0; 12006269Smarks 12016269Smarks if (strlen(str) == table_length) { 12026269Smarks /* 12036269Smarks * If the string == table_length then first check to see it's 12046269Smarks * in positional format. If that fails then see if it's in 12056269Smarks * non-positional format. 12066269Smarks */ 12076269Smarks if (compute_values(inherit_table, table_length, str, 12086269Smarks 1, imask) && compute_values(inherit_table, 12096269Smarks table_length, str, 0, imask)) { 12106269Smarks rc = 1; 12116269Smarks } 12126269Smarks } else { 12136269Smarks rc = compute_values(inherit_table, table_length, str, 0, imask); 12146269Smarks } 12156269Smarks 12166269Smarks return (rc ? EACL_INHERIT_ERROR : 0); 12176269Smarks } 12186269Smarks 12191420Smarks /* 12201420Smarks * compute value for inheritance flags. 12211420Smarks */ 12221420Smarks int 12231420Smarks compute_ace_inherit(char *str, uint32_t *imask) 12241420Smarks { 12256269Smarks int rc = 0; 1226789Sahrens 12276269Smarks rc = ace_inherit_helper(str, imask, IFLAG_COUNT); 12286269Smarks 12296269Smarks if (rc && strlen(str) != IFLAG_COUNT) { 12301420Smarks 12316269Smarks /* is it an old formatted inherit string? */ 12326269Smarks rc = ace_inherit_helper(str, imask, IFLAG_COUNT_V1); 12336269Smarks } 12341420Smarks 12356269Smarks return (rc); 1236789Sahrens } 12371420Smarks 12381420Smarks 12391420Smarks /* 12401420Smarks * compute value for ACE permissions. 12411420Smarks */ 12421420Smarks int 12431420Smarks compute_ace_perms(char *str, uint32_t *mask) 12441420Smarks { 12451420Smarks int positional = 0; 12461420Smarks int error; 12471420Smarks 12481420Smarks if (strlen(str) == ACE_PERM_COUNT) 12491420Smarks positional = 1; 12501420Smarks 12511420Smarks error = compute_values(ace_perm_table, ACE_PERM_COUNT, 12521420Smarks str, positional, mask); 12531420Smarks 12541420Smarks if (error && positional) { 12551420Smarks /* 12561420Smarks * If positional was set, then make sure permissions 12571420Smarks * aren't actually valid in non positional case where 12581420Smarks * all permissions are specified, just in random order. 12591420Smarks */ 12601420Smarks error = compute_values(ace_perm_table, 12611420Smarks ACE_PERM_COUNT, str, 0, mask); 12621420Smarks } 12631420Smarks if (error) 12641420Smarks error = EACL_PERM_MASK_ERROR; 12651420Smarks 12661420Smarks return (error); 12671420Smarks } 12681420Smarks 12691420Smarks 12701420Smarks 12711420Smarks /* 12721420Smarks * compute values for aclent permissions. 12731420Smarks */ 12741420Smarks int 12751420Smarks compute_aclent_perms(char *str, o_mode_t *mask) 12761420Smarks { 12771420Smarks int error; 12781420Smarks uint32_t pmask; 12791420Smarks 12801420Smarks if (strlen(str) != ACLENT_PERM_COUNT) 12811420Smarks return (EACL_PERM_MASK_ERROR); 12821420Smarks 12831420Smarks *mask = 0; 12841420Smarks error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT, 12851420Smarks str, 1, &pmask); 12861420Smarks if (error == 0) { 12871420Smarks *mask = (o_mode_t)pmask; 12881420Smarks } else 12891420Smarks error = EACL_PERM_MASK_ERROR; 12901420Smarks return (error); 12911420Smarks } 12921420Smarks 12931420Smarks /* 12941420Smarks * determine ACE permissions. 12951420Smarks */ 12961420Smarks int 12971420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask) 12981420Smarks { 12991420Smarks int error; 13001420Smarks 13011420Smarks if (aclperm->perm_style == PERM_TYPE_EMPTY) { 13021420Smarks *mask = 0; 13031420Smarks return (0); 13041420Smarks } 13051420Smarks 13061420Smarks if (aclperm->perm_style == PERM_TYPE_ACE) { 13071420Smarks *mask = aclperm->perm_val; 13081420Smarks return (0); 13091420Smarks } 13101420Smarks 13111420Smarks error = compute_ace_perms(aclperm->perm_str, mask); 13121420Smarks if (error) { 13131567Smarks acl_error(dgettext(TEXT_DOMAIN, 13141567Smarks "Invalid permission(s) '%s' specified\n"), 13151420Smarks aclperm->perm_str); 13161420Smarks return (EACL_PERM_MASK_ERROR); 13171420Smarks } 13181420Smarks 13191420Smarks return (0); 13201420Smarks } 1321