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 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*1420Smarks * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate /*LINTLIBRARY*/ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <grp.h> 310Sstevel@tonic-gate #include <pwd.h> 320Sstevel@tonic-gate #include <string.h> 330Sstevel@tonic-gate #include <limits.h> 340Sstevel@tonic-gate #include <stdlib.h> 35789Sahrens #include <errno.h> 360Sstevel@tonic-gate #include <sys/param.h> 370Sstevel@tonic-gate #include <sys/types.h> 38*1420Smarks #include <sys/stat.h> 390Sstevel@tonic-gate #include <sys/acl.h> 40789Sahrens #include <aclutils.h> 41*1420Smarks 42*1420Smarks #define ID_STR_MAX 20 /* digits in LONG_MAX */ 43789Sahrens 44*1420Smarks #define APPENDED_ID_MAX ID_STR_MAX + 1 /* id + colon */ 45*1420Smarks /* 46*1420Smarks * yyinteractive controls whether yyparse should print out 47*1420Smarks * error messages to stderr, and whether or not id's should be 48*1420Smarks * allowed from acl_fromtext(). 49*1420Smarks */ 50*1420Smarks int yyinteractive; 51*1420Smarks acl_t *yyacl; 52*1420Smarks char *yybuf; 53789Sahrens 54789Sahrens extern acl_t *acl_alloc(enum acl_type); 550Sstevel@tonic-gate 56922Shm123892 570Sstevel@tonic-gate struct dynaclstr { 580Sstevel@tonic-gate size_t bufsize; /* current size of aclexport */ 590Sstevel@tonic-gate char *aclexport; 600Sstevel@tonic-gate }; 610Sstevel@tonic-gate 620Sstevel@tonic-gate static char *strappend(char *, char *); 630Sstevel@tonic-gate static char *convert_perm(char *, o_mode_t); 640Sstevel@tonic-gate static int increase_length(struct dynaclstr *, size_t); 650Sstevel@tonic-gate 66*1420Smarks static void 67*1420Smarks aclent_perms(int perm, char *txt_perms) 68*1420Smarks { 69*1420Smarks if (perm & S_IROTH) 70*1420Smarks txt_perms[0] = 'r'; 71*1420Smarks else 72*1420Smarks txt_perms[0] = '-'; 73*1420Smarks if (perm & S_IWOTH) 74*1420Smarks txt_perms[1] = 'w'; 75*1420Smarks else 76*1420Smarks txt_perms[1] = '-'; 77*1420Smarks if (perm & S_IXOTH) 78*1420Smarks txt_perms[2] = 'x'; 79*1420Smarks else 80*1420Smarks txt_perms[2] = '-'; 81*1420Smarks txt_perms[3] = '\0'; 82*1420Smarks } 83*1420Smarks 84*1420Smarks static char * 85*1420Smarks pruname(uid_t uid, char *uidp) 86*1420Smarks { 87*1420Smarks struct passwd *passwdp; 88*1420Smarks 89*1420Smarks passwdp = getpwuid(uid); 90*1420Smarks if (passwdp == (struct passwd *)NULL) { 91*1420Smarks /* could not get passwd information: display uid instead */ 92*1420Smarks (void) sprintf(uidp, "%ld", (long)uid); 93*1420Smarks return (uidp); 94*1420Smarks } else 95*1420Smarks return (passwdp->pw_name); 96*1420Smarks } 97*1420Smarks 98*1420Smarks static char * 99*1420Smarks prgname(gid_t gid, char *gidp) 100*1420Smarks { 101*1420Smarks struct group *groupp; 102*1420Smarks 103*1420Smarks groupp = getgrgid(gid); 104*1420Smarks if (groupp == (struct group *)NULL) { 105*1420Smarks /* could not get group information: display gid instead */ 106*1420Smarks (void) sprintf(gidp, "%ld", (long)gid); 107*1420Smarks return (gidp); 108*1420Smarks } else 109*1420Smarks return (groupp->gr_name); 110*1420Smarks } 111*1420Smarks static void 112*1420Smarks aclent_printacl(acl_t *aclp) 113789Sahrens { 114*1420Smarks aclent_t *tp; 115*1420Smarks int aclcnt; 116*1420Smarks int mask; 117*1420Smarks int slot = 0; 118*1420Smarks char perm[4]; 119*1420Smarks char uidp[10]; 120*1420Smarks char gidp[10]; 121*1420Smarks 122*1420Smarks /* display ACL: assume it is sorted. */ 123*1420Smarks aclcnt = aclp->acl_cnt; 124*1420Smarks for (tp = aclp->acl_aclp; tp && aclcnt--; tp++) { 125*1420Smarks if (tp->a_type == CLASS_OBJ) 126*1420Smarks mask = tp->a_perm; 127*1420Smarks } 128*1420Smarks aclcnt = aclp->acl_cnt; 129*1420Smarks for (tp = aclp->acl_aclp; aclcnt--; tp++) { 130*1420Smarks (void) printf(" %d:", slot++); 131*1420Smarks switch (tp->a_type) { 132*1420Smarks case USER: 133*1420Smarks aclent_perms(tp->a_perm, perm); 134*1420Smarks (void) printf("user:%s:%s\t\t", 135*1420Smarks pruname(tp->a_id, uidp), perm); 136*1420Smarks aclent_perms((tp->a_perm & mask), perm); 137*1420Smarks (void) printf("#effective:%s\n", perm); 138*1420Smarks break; 139*1420Smarks case USER_OBJ: 140*1420Smarks /* no need to display uid */ 141*1420Smarks aclent_perms(tp->a_perm, perm); 142*1420Smarks (void) printf("user::%s\n", perm); 143*1420Smarks break; 144*1420Smarks case GROUP: 145*1420Smarks aclent_perms(tp->a_perm, perm); 146*1420Smarks (void) printf("group:%s:%s\t\t", 147*1420Smarks prgname(tp->a_id, gidp), perm); 148*1420Smarks aclent_perms(tp->a_perm & mask, perm); 149*1420Smarks (void) printf("#effective:%s\n", perm); 150*1420Smarks break; 151*1420Smarks case GROUP_OBJ: 152*1420Smarks aclent_perms(tp->a_perm, perm); 153*1420Smarks (void) printf("group::%s\t\t", perm); 154*1420Smarks aclent_perms(tp->a_perm & mask, perm); 155*1420Smarks (void) printf("#effective:%s\n", perm); 156*1420Smarks break; 157*1420Smarks case CLASS_OBJ: 158*1420Smarks aclent_perms(tp->a_perm, perm); 159*1420Smarks (void) printf("mask:%s\n", perm); 160*1420Smarks break; 161*1420Smarks case OTHER_OBJ: 162*1420Smarks aclent_perms(tp->a_perm, perm); 163*1420Smarks (void) printf("other:%s\n", perm); 164*1420Smarks break; 165*1420Smarks case DEF_USER: 166*1420Smarks aclent_perms(tp->a_perm, perm); 167*1420Smarks (void) printf("default:user:%s:%s\n", 168*1420Smarks pruname(tp->a_id, uidp), perm); 169*1420Smarks break; 170*1420Smarks case DEF_USER_OBJ: 171*1420Smarks aclent_perms(tp->a_perm, perm); 172*1420Smarks (void) printf("default:user::%s\n", perm); 173*1420Smarks break; 174*1420Smarks case DEF_GROUP: 175*1420Smarks aclent_perms(tp->a_perm, perm); 176*1420Smarks (void) printf("default:group:%s:%s\n", 177*1420Smarks prgname(tp->a_id, gidp), perm); 178*1420Smarks break; 179*1420Smarks case DEF_GROUP_OBJ: 180*1420Smarks aclent_perms(tp->a_perm, perm); 181*1420Smarks (void) printf("default:group::%s\n", perm); 182*1420Smarks break; 183*1420Smarks case DEF_CLASS_OBJ: 184*1420Smarks aclent_perms(tp->a_perm, perm); 185*1420Smarks (void) printf("default:mask:%s\n", perm); 186*1420Smarks break; 187*1420Smarks case DEF_OTHER_OBJ: 188*1420Smarks aclent_perms(tp->a_perm, perm); 189*1420Smarks (void) printf("default:other:%s\n", perm); 190*1420Smarks break; 191*1420Smarks default: 192*1420Smarks (void) fprintf(stderr, 193*1420Smarks gettext("unrecognized entry\n")); 194*1420Smarks break; 195*1420Smarks } 196*1420Smarks } 197*1420Smarks } 198*1420Smarks 199*1420Smarks static void 200*1420Smarks split_line(char *str, int cols) 201*1420Smarks { 202*1420Smarks char *ptr; 203*1420Smarks int len; 204*1420Smarks int i; 205*1420Smarks int last_split; 206*1420Smarks char *pad = ""; 207*1420Smarks int pad_len; 208*1420Smarks 209*1420Smarks len = strlen(str); 210*1420Smarks ptr = str; 211*1420Smarks pad_len = 0; 212*1420Smarks 213*1420Smarks ptr = str; 214*1420Smarks last_split = 0; 215*1420Smarks for (i = 0; i != len; i++) { 216*1420Smarks if ((i + pad_len + 4) >= cols) { 217*1420Smarks (void) printf("%s%.*s\n", pad, last_split, ptr); 218*1420Smarks ptr = &ptr[last_split]; 219*1420Smarks len = strlen(ptr); 220*1420Smarks i = 0; 221*1420Smarks pad_len = 4; 222*1420Smarks pad = " "; 223*1420Smarks } else { 224*1420Smarks if (ptr[i] == '/' || ptr[i] == ':') { 225*1420Smarks last_split = i; 226*1420Smarks } 227*1420Smarks } 228*1420Smarks } 229*1420Smarks if (i == len) { 230*1420Smarks (void) printf("%s%s\n", pad, ptr); 231*1420Smarks } 232*1420Smarks } 233*1420Smarks 234*1420Smarks #define OWNERAT_TXT "owner@" 235*1420Smarks #define GROUPAT_TXT "group@" 236*1420Smarks #define EVERYONEAT_TXT "everyone@" 237*1420Smarks #define GROUP_TXT "group:" 238*1420Smarks #define USER_TXT "user:" 239*1420Smarks 240*1420Smarks char * 241*1420Smarks ace_type_txt(char *buf, char **endp, ace_t *acep) 242*1420Smarks { 243*1420Smarks 244*1420Smarks char idp[10]; 245*1420Smarks 246*1420Smarks if (buf == NULL) 247*1420Smarks return (NULL); 248*1420Smarks 249*1420Smarks switch (acep->a_flags & ACE_TYPE_FLAGS) { 250*1420Smarks case ACE_OWNER: 251*1420Smarks strcpy(buf, OWNERAT_TXT); 252*1420Smarks *endp = buf + sizeof (OWNERAT_TXT) - 1; 253*1420Smarks break; 254*1420Smarks 255*1420Smarks case ACE_GROUP|ACE_IDENTIFIER_GROUP: 256*1420Smarks strcpy(buf, GROUPAT_TXT); 257*1420Smarks *endp = buf + sizeof (GROUPAT_TXT) - 1; 258*1420Smarks break; 259*1420Smarks 260*1420Smarks case ACE_IDENTIFIER_GROUP: 261*1420Smarks strcpy(buf, GROUP_TXT); 262*1420Smarks strcat(buf, prgname(acep->a_who, idp)); 263*1420Smarks *endp = buf + strlen(buf); 264*1420Smarks break; 265*1420Smarks 266*1420Smarks case ACE_EVERYONE: 267*1420Smarks strcpy(buf, EVERYONEAT_TXT); 268*1420Smarks *endp = buf + sizeof (EVERYONEAT_TXT) - 1; 269*1420Smarks break; 270*1420Smarks 271*1420Smarks case 0: 272*1420Smarks strcpy(buf, USER_TXT); 273*1420Smarks strcat(buf, pruname(acep->a_who, idp)); 274*1420Smarks *endp = buf + strlen(buf); 275*1420Smarks break; 276*1420Smarks } 277*1420Smarks 278*1420Smarks return (buf); 279*1420Smarks } 280*1420Smarks 281*1420Smarks #define READ_DATA_TXT "read_data/" 282*1420Smarks #define WRITE_DATA_TXT "write_data/" 283*1420Smarks #define EXECUTE_TXT "execute/" 284*1420Smarks #define READ_XATTR_TXT "read_xattr/" 285*1420Smarks #define WRITE_XATTR_TXT "write_xattr/" 286*1420Smarks #define READ_ATTRIBUTES_TXT "read_attributes/" 287*1420Smarks #define WRITE_ATTRIBUTES_TXT "write_attributes/" 288*1420Smarks #define DELETE_TXT "delete/" 289*1420Smarks #define DELETE_CHILD_TXT "delete_child/" 290*1420Smarks #define WRITE_OWNER_TXT "write_owner/" 291*1420Smarks #define READ_ACL_TXT "read_acl/" 292*1420Smarks #define WRITE_ACL_TXT "write_acl/" 293*1420Smarks #define APPEND_DATA_TXT "append_data/" 294*1420Smarks #define READ_DIR_TXT "list_directory/read_data/" 295*1420Smarks #define ADD_DIR_TXT "add_subdirectory/append_data/" 296*1420Smarks #define ADD_FILE_TXT "add_file/write_data/" 297*1420Smarks #define SYNCHRONIZE_TXT "synchronize" /* not slash on this one */ 298*1420Smarks 299*1420Smarks char * 300*1420Smarks ace_perm_txt(char *buf, char **endp, uint32_t mask, 301*1420Smarks uint32_t iflags, int isdir, int flags) 302*1420Smarks { 303*1420Smarks char *lend = buf; /* local end */ 304*1420Smarks 305*1420Smarks if (buf == NULL) 306*1420Smarks return (NULL); 307*1420Smarks 308*1420Smarks if (flags & ACL_COMPACT_FMT) { 309789Sahrens 310*1420Smarks if (mask & ACE_READ_DATA) 311*1420Smarks buf[0] = 'r'; 312*1420Smarks else 313*1420Smarks buf[0] = '-'; 314*1420Smarks if (mask & ACE_WRITE_DATA) 315*1420Smarks buf[1] = 'w'; 316*1420Smarks else 317*1420Smarks buf[1] = '-'; 318*1420Smarks if (mask & ACE_EXECUTE) 319*1420Smarks buf[2] = 'x'; 320*1420Smarks else 321*1420Smarks buf[2] = '-'; 322*1420Smarks if (mask & ACE_APPEND_DATA) 323*1420Smarks buf[3] = 'p'; 324*1420Smarks else 325*1420Smarks buf[3] = '-'; 326*1420Smarks if (mask & ACE_DELETE) 327*1420Smarks buf[4] = 'd'; 328*1420Smarks else 329*1420Smarks buf[4] = '-'; 330*1420Smarks if (mask & ACE_DELETE_CHILD) 331*1420Smarks buf[5] = 'D'; 332*1420Smarks else 333*1420Smarks buf[5] = '-'; 334*1420Smarks if (mask & ACE_READ_ATTRIBUTES) 335*1420Smarks buf[6] = 'a'; 336*1420Smarks else 337*1420Smarks buf[6] = '-'; 338*1420Smarks if (mask & ACE_WRITE_ATTRIBUTES) 339*1420Smarks buf[7] = 'A'; 340*1420Smarks else 341*1420Smarks buf[7] = '-'; 342*1420Smarks if (mask & ACE_READ_NAMED_ATTRS) 343*1420Smarks buf[8] = 'R'; 344*1420Smarks else 345*1420Smarks buf[8] = '-'; 346*1420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) 347*1420Smarks buf[9] = 'W'; 348*1420Smarks else 349*1420Smarks buf[9] = '-'; 350*1420Smarks if (mask & ACE_READ_ACL) 351*1420Smarks buf[10] = 'c'; 352*1420Smarks else 353*1420Smarks buf[10] = '-'; 354*1420Smarks if (mask & ACE_WRITE_ACL) 355*1420Smarks buf[11] = 'C'; 356*1420Smarks else 357*1420Smarks buf[11] = '-'; 358*1420Smarks if (mask & ACE_WRITE_OWNER) 359*1420Smarks buf[12] = 'o'; 360*1420Smarks else 361*1420Smarks buf[12] = '-'; 362*1420Smarks if (mask & ACE_SYNCHRONIZE) 363*1420Smarks buf[13] = 's'; 364*1420Smarks else 365*1420Smarks buf[13] = '-'; 366*1420Smarks buf[14] = '\0'; 367*1420Smarks *endp = buf + 14; 368*1420Smarks return (buf); 369*1420Smarks } else { 370*1420Smarks /* 371*1420Smarks * If ACE is a directory, but inheritance indicates its 372*1420Smarks * for a file then print permissions for file rather than 373*1420Smarks * dir. 374*1420Smarks */ 375*1420Smarks if (isdir) { 376*1420Smarks if (mask & ACE_LIST_DIRECTORY) { 377*1420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 378*1420Smarks strcpy(lend, READ_DATA_TXT); 379*1420Smarks lend += sizeof (READ_DATA_TXT) - 1; 380*1420Smarks } else { 381*1420Smarks strcpy(lend, READ_DIR_TXT); 382*1420Smarks lend += sizeof (READ_DIR_TXT) - 1; 383*1420Smarks } 384*1420Smarks } 385*1420Smarks if (mask & ACE_ADD_FILE) { 386*1420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 387*1420Smarks strcpy(lend, WRITE_DATA_TXT); 388*1420Smarks lend += sizeof (WRITE_DATA_TXT) - 1; 389*1420Smarks } else { 390*1420Smarks strcpy(lend, ADD_FILE_TXT); 391*1420Smarks lend += 392*1420Smarks sizeof (ADD_FILE_TXT) -1; 393*1420Smarks } 394*1420Smarks } 395*1420Smarks if (mask & ACE_ADD_SUBDIRECTORY) { 396*1420Smarks if (iflags == ACE_FILE_INHERIT_ACE) { 397*1420Smarks strcpy(lend, APPEND_DATA_TXT); 398*1420Smarks lend += sizeof (APPEND_DATA_TXT) - 1; 399*1420Smarks } else { 400*1420Smarks strcpy(lend, ADD_DIR_TXT); 401*1420Smarks lend += sizeof (ADD_DIR_TXT) - 1; 402*1420Smarks } 403*1420Smarks } 404*1420Smarks } else { 405*1420Smarks if (mask & ACE_READ_DATA) { 406*1420Smarks strcpy(lend, READ_DATA_TXT); 407*1420Smarks lend += sizeof (READ_DATA_TXT) - 1; 408*1420Smarks } 409*1420Smarks if (mask & ACE_WRITE_DATA) { 410*1420Smarks strcpy(lend, WRITE_DATA_TXT); 411*1420Smarks lend += sizeof (WRITE_DATA_TXT) - 1; 412*1420Smarks } 413*1420Smarks if (mask & ACE_APPEND_DATA) { 414*1420Smarks strcpy(lend, APPEND_DATA_TXT); 415*1420Smarks lend += sizeof (APPEND_DATA_TXT) - 1; 416*1420Smarks } 417*1420Smarks } 418*1420Smarks if (mask & ACE_READ_NAMED_ATTRS) { 419*1420Smarks strcpy(lend, READ_XATTR_TXT); 420*1420Smarks lend += sizeof (READ_XATTR_TXT) - 1; 421*1420Smarks } 422*1420Smarks if (mask & ACE_WRITE_NAMED_ATTRS) { 423*1420Smarks strcpy(lend, WRITE_XATTR_TXT); 424*1420Smarks lend += sizeof (WRITE_XATTR_TXT) - 1; 425*1420Smarks } 426*1420Smarks if (mask & ACE_EXECUTE) { 427*1420Smarks strcpy(lend, EXECUTE_TXT); 428*1420Smarks lend += sizeof (EXECUTE_TXT) - 1; 429*1420Smarks } 430*1420Smarks if (mask & ACE_DELETE_CHILD) { 431*1420Smarks strcpy(lend, DELETE_CHILD_TXT); 432*1420Smarks lend += sizeof (DELETE_CHILD_TXT) - 1; 433*1420Smarks } 434*1420Smarks if (mask & ACE_READ_ATTRIBUTES) { 435*1420Smarks strcpy(lend, READ_ATTRIBUTES_TXT); 436*1420Smarks lend += sizeof (READ_ATTRIBUTES_TXT) - 1; 437*1420Smarks } 438*1420Smarks if (mask & ACE_WRITE_ATTRIBUTES) { 439*1420Smarks strcpy(lend, WRITE_ATTRIBUTES_TXT); 440*1420Smarks lend += sizeof (WRITE_ATTRIBUTES_TXT) - 1; 441*1420Smarks } 442*1420Smarks if (mask & ACE_DELETE) { 443*1420Smarks strcpy(lend, DELETE_TXT); 444*1420Smarks lend += sizeof (DELETE_TXT) - 1; 445*1420Smarks } 446*1420Smarks if (mask & ACE_READ_ACL) { 447*1420Smarks strcpy(lend, READ_ACL_TXT); 448*1420Smarks lend += sizeof (READ_ACL_TXT) - 1; 449*1420Smarks } 450*1420Smarks if (mask & ACE_WRITE_ACL) { 451*1420Smarks strcpy(lend, WRITE_ACL_TXT); 452*1420Smarks lend += sizeof (WRITE_ACL_TXT) - 1; 453*1420Smarks } 454*1420Smarks if (mask & ACE_WRITE_OWNER) { 455*1420Smarks strcpy(lend, WRITE_OWNER_TXT); 456*1420Smarks lend += sizeof (WRITE_OWNER_TXT) - 1; 457*1420Smarks } 458*1420Smarks if (mask & ACE_SYNCHRONIZE) { 459*1420Smarks strcpy(lend, SYNCHRONIZE_TXT); 460*1420Smarks lend += sizeof (SYNCHRONIZE_TXT) - 1; 461*1420Smarks } 462789Sahrens 463*1420Smarks if (*(lend - 1) == '/') 464*1420Smarks *--lend = '\0'; 465*1420Smarks } 466*1420Smarks 467*1420Smarks *endp = lend; 468*1420Smarks return (buf); 469*1420Smarks } 470*1420Smarks 471*1420Smarks #define ALLOW_TXT "allow" 472*1420Smarks #define DENY_TXT "deny" 473*1420Smarks #define ALARM_TXT "alarm" 474*1420Smarks #define AUDIT_TXT "audit" 475*1420Smarks #define UNKNOWN_TXT "unknown" 476*1420Smarks char * 477*1420Smarks ace_access_txt(char *buf, char **endp, int type) 478*1420Smarks { 479*1420Smarks 480*1420Smarks if (buf == NULL) 481*1420Smarks return (NULL); 482*1420Smarks 483*1420Smarks if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 484*1420Smarks strcpy(buf, ALLOW_TXT); 485*1420Smarks *endp += sizeof (ALLOW_TXT) - 1; 486*1420Smarks } else if (type == ACE_ACCESS_DENIED_ACE_TYPE) { 487*1420Smarks strcpy(buf, DENY_TXT); 488*1420Smarks *endp += sizeof (DENY_TXT) - 1; 489*1420Smarks } else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) { 490*1420Smarks strcpy(buf, AUDIT_TXT); 491*1420Smarks *endp += sizeof (AUDIT_TXT) - 1; 492*1420Smarks } else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) { 493*1420Smarks strcpy(buf, ALARM_TXT); 494*1420Smarks *endp += sizeof (ALARM_TXT) - 1; 495*1420Smarks } else { 496*1420Smarks strcpy(buf, UNKNOWN_TXT); 497*1420Smarks *endp += sizeof (UNKNOWN_TXT) - 1; 498*1420Smarks } 499*1420Smarks 500*1420Smarks return (buf); 501*1420Smarks } 502*1420Smarks 503*1420Smarks static char * 504*1420Smarks ace_inherit_txt(char *buf, char **endp, uint32_t iflags, int flags) 505*1420Smarks { 506*1420Smarks 507*1420Smarks char *lend = buf; 508*1420Smarks 509*1420Smarks if (buf == NULL) { 510*1420Smarks return (NULL); 511*1420Smarks } 512789Sahrens 513*1420Smarks if (flags & ACL_COMPACT_FMT) { 514*1420Smarks if (iflags & ACE_FILE_INHERIT_ACE) 515*1420Smarks buf[0] = 'f'; 516*1420Smarks else 517*1420Smarks buf[0] = '-'; 518*1420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) 519*1420Smarks buf[1] = 'd'; 520*1420Smarks else 521*1420Smarks buf[1] = '-'; 522*1420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) 523*1420Smarks buf[2] = 'i'; 524*1420Smarks else 525*1420Smarks buf[2] = '-'; 526*1420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) 527*1420Smarks buf[3] = 'n'; 528*1420Smarks else 529*1420Smarks buf[3] = '-'; 530*1420Smarks if (iflags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 531*1420Smarks buf[4] = 'S'; 532*1420Smarks else 533*1420Smarks buf[4] = '-'; 534*1420Smarks if (iflags & ACE_FAILED_ACCESS_ACE_FLAG) 535*1420Smarks buf[5] = 'F'; 536*1420Smarks else 537*1420Smarks buf[5] = '-'; 538*1420Smarks buf[6] = '\0'; 539*1420Smarks *endp = buf + 6; 540*1420Smarks } else { 541*1420Smarks if (iflags & ACE_FILE_INHERIT_ACE) { 542*1420Smarks strcpy(lend, "file_inherit/"); 543*1420Smarks lend += sizeof ("file_inherit/") - 1; 544*1420Smarks } 545*1420Smarks if (iflags & ACE_DIRECTORY_INHERIT_ACE) { 546*1420Smarks strcpy(lend, "dir_inherit/"); 547*1420Smarks lend += sizeof ("dir_inherit/") - 1; 548*1420Smarks } 549*1420Smarks if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) { 550*1420Smarks strcpy(lend, "no_propagate/"); 551*1420Smarks lend += sizeof ("no_propagate/") - 1; 552*1420Smarks } 553*1420Smarks if (iflags & ACE_INHERIT_ONLY_ACE) { 554*1420Smarks strcpy(lend, "inherit_only/"); 555*1420Smarks lend += sizeof ("inherit_only/") - 1; 556*1420Smarks } 557789Sahrens 558*1420Smarks if (*(lend - 1) == '/') 559*1420Smarks *--lend = '\0'; 560*1420Smarks *endp = lend; 561*1420Smarks } 562*1420Smarks 563*1420Smarks return (buf); 564789Sahrens } 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate /* 5670Sstevel@tonic-gate * Convert internal acl representation to external representation. 5680Sstevel@tonic-gate * 5690Sstevel@tonic-gate * The length of a non-owning user name or non-owning group name ie entries 5700Sstevel@tonic-gate * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We 5710Sstevel@tonic-gate * thus check the length of these entries, and if greater than LOGNAME_MAX, 5720Sstevel@tonic-gate * we realloc() via increase_length(). 5730Sstevel@tonic-gate * 5740Sstevel@tonic-gate * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always 5750Sstevel@tonic-gate * adhered to. 5760Sstevel@tonic-gate */ 577*1420Smarks 578*1420Smarks /* 579*1420Smarks * acltotext() converts each ACL entry to look like this: 580*1420Smarks * 581*1420Smarks * entry_type:uid^gid^name:perms[:id] 582*1420Smarks * 583*1420Smarks * The maximum length of entry_type is 14 ("defaultgroup::" and 584*1420Smarks * "defaultother::") hence ENTRYTYPELEN is set to 14. 585*1420Smarks * 586*1420Smarks * The max length of a uid^gid^name entry (in theory) is 8, hence we use, 587*1420Smarks * however the ID could be a number so we therefore use ID_STR_MAX 588*1420Smarks * 589*1420Smarks * The length of a perms entry is 4 to allow for the comma appended to each 590*1420Smarks * to each acl entry. Hence PERMS is set to 4. 591*1420Smarks */ 592*1420Smarks 593*1420Smarks #define ENTRYTYPELEN 14 594*1420Smarks #define PERMS 4 595*1420Smarks #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX) 596*1420Smarks #define UPDATE_WHERE where = dstr->aclexport + strlen(dstr->aclexport) 597*1420Smarks 5980Sstevel@tonic-gate char * 599*1420Smarks aclent_acltotext(aclent_t *aclp, int aclcnt, int flags) 6000Sstevel@tonic-gate { 6010Sstevel@tonic-gate char *aclexport; 6020Sstevel@tonic-gate char *where; 6030Sstevel@tonic-gate struct group *groupp; 6040Sstevel@tonic-gate struct passwd *passwdp; 6050Sstevel@tonic-gate struct dynaclstr *dstr; 6060Sstevel@tonic-gate int i, rtn; 6070Sstevel@tonic-gate size_t excess = 0; 608*1420Smarks char id[20], *idstr; 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate if (aclp == NULL) 6110Sstevel@tonic-gate return (NULL); 6120Sstevel@tonic-gate if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL) 6130Sstevel@tonic-gate return (NULL); 6140Sstevel@tonic-gate dstr->bufsize = aclcnt * ACL_ENTRY_SIZE; 6150Sstevel@tonic-gate if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) { 6160Sstevel@tonic-gate free(dstr); 6170Sstevel@tonic-gate return (NULL); 6180Sstevel@tonic-gate } 6190Sstevel@tonic-gate *dstr->aclexport = '\0'; 6200Sstevel@tonic-gate where = dstr->aclexport; 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate for (i = 0; i < aclcnt; i++, aclp++) { 6230Sstevel@tonic-gate switch (aclp->a_type) { 6240Sstevel@tonic-gate case DEF_USER_OBJ: 6250Sstevel@tonic-gate case USER_OBJ: 6260Sstevel@tonic-gate if (aclp->a_type == USER_OBJ) 6270Sstevel@tonic-gate where = strappend(where, "user::"); 6280Sstevel@tonic-gate else 6290Sstevel@tonic-gate where = strappend(where, "defaultuser::"); 6300Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6310Sstevel@tonic-gate break; 6320Sstevel@tonic-gate case DEF_USER: 6330Sstevel@tonic-gate case USER: 6340Sstevel@tonic-gate if (aclp->a_type == USER) 6350Sstevel@tonic-gate where = strappend(where, "user:"); 6360Sstevel@tonic-gate else 6370Sstevel@tonic-gate where = strappend(where, "defaultuser:"); 6380Sstevel@tonic-gate passwdp = getpwuid(aclp->a_id); 6390Sstevel@tonic-gate if (passwdp == (struct passwd *)NULL) { 6400Sstevel@tonic-gate /* put in uid instead */ 6410Sstevel@tonic-gate (void) sprintf(where, "%d", aclp->a_id); 642922Shm123892 UPDATE_WHERE; 6430Sstevel@tonic-gate } else { 6440Sstevel@tonic-gate excess = strlen(passwdp->pw_name) - LOGNAME_MAX; 6450Sstevel@tonic-gate if (excess > 0) { 6460Sstevel@tonic-gate rtn = increase_length(dstr, excess); 6470Sstevel@tonic-gate if (rtn == 1) { 648922Shm123892 UPDATE_WHERE; 6490Sstevel@tonic-gate } else { 6500Sstevel@tonic-gate free(dstr->aclexport); 6510Sstevel@tonic-gate free(dstr); 6520Sstevel@tonic-gate return (NULL); 6530Sstevel@tonic-gate } 6540Sstevel@tonic-gate } 6550Sstevel@tonic-gate where = strappend(where, passwdp->pw_name); 6560Sstevel@tonic-gate } 6570Sstevel@tonic-gate where = strappend(where, ":"); 6580Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6590Sstevel@tonic-gate break; 6600Sstevel@tonic-gate case DEF_GROUP_OBJ: 6610Sstevel@tonic-gate case GROUP_OBJ: 6620Sstevel@tonic-gate if (aclp->a_type == GROUP_OBJ) 6630Sstevel@tonic-gate where = strappend(where, "group::"); 6640Sstevel@tonic-gate else 6650Sstevel@tonic-gate where = strappend(where, "defaultgroup::"); 6660Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6670Sstevel@tonic-gate break; 6680Sstevel@tonic-gate case DEF_GROUP: 6690Sstevel@tonic-gate case GROUP: 6700Sstevel@tonic-gate if (aclp->a_type == GROUP) 6710Sstevel@tonic-gate where = strappend(where, "group:"); 6720Sstevel@tonic-gate else 6730Sstevel@tonic-gate where = strappend(where, "defaultgroup:"); 6740Sstevel@tonic-gate groupp = getgrgid(aclp->a_id); 6750Sstevel@tonic-gate if (groupp == (struct group *)NULL) { 6760Sstevel@tonic-gate /* put in gid instead */ 6770Sstevel@tonic-gate (void) sprintf(where, "%d", aclp->a_id); 678922Shm123892 UPDATE_WHERE; 6790Sstevel@tonic-gate } else { 6800Sstevel@tonic-gate excess = strlen(groupp->gr_name) - LOGNAME_MAX; 6810Sstevel@tonic-gate if (excess > 0) { 6820Sstevel@tonic-gate rtn = increase_length(dstr, excess); 6830Sstevel@tonic-gate if (rtn == 1) { 684922Shm123892 UPDATE_WHERE; 6850Sstevel@tonic-gate } else { 6860Sstevel@tonic-gate free(dstr->aclexport); 6870Sstevel@tonic-gate free(dstr); 6880Sstevel@tonic-gate return (NULL); 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate } 6910Sstevel@tonic-gate where = strappend(where, groupp->gr_name); 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate where = strappend(where, ":"); 6940Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 6950Sstevel@tonic-gate break; 6960Sstevel@tonic-gate case DEF_CLASS_OBJ: 6970Sstevel@tonic-gate case CLASS_OBJ: 6980Sstevel@tonic-gate if (aclp->a_type == CLASS_OBJ) 6990Sstevel@tonic-gate where = strappend(where, "mask:"); 7000Sstevel@tonic-gate else 7010Sstevel@tonic-gate where = strappend(where, "defaultmask:"); 7020Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7030Sstevel@tonic-gate break; 7040Sstevel@tonic-gate case DEF_OTHER_OBJ: 7050Sstevel@tonic-gate case OTHER_OBJ: 7060Sstevel@tonic-gate if (aclp->a_type == OTHER_OBJ) 7070Sstevel@tonic-gate where = strappend(where, "other:"); 7080Sstevel@tonic-gate else 7090Sstevel@tonic-gate where = strappend(where, "defaultother:"); 7100Sstevel@tonic-gate where = convert_perm(where, aclp->a_perm); 7110Sstevel@tonic-gate break; 7120Sstevel@tonic-gate default: 7130Sstevel@tonic-gate free(dstr->aclexport); 7140Sstevel@tonic-gate free(dstr); 7150Sstevel@tonic-gate return (NULL); 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate } 718*1420Smarks 719*1420Smarks if ((flags & ACL_APPEND_ID) && ((aclp->a_type == USER) || 720*1420Smarks (aclp->a_type == DEF_USER) || (aclp->a_type == GROUP) || 721*1420Smarks (aclp->a_type == DEF_GROUP))) { 722*1420Smarks where = strappend(where, ":"); 723*1420Smarks id[ID_STR_MAX - 1] = '\0'; /* null terminate buffer */ 724*1420Smarks idstr = lltostr(aclp->a_id, &id[ID_STR_MAX - 1]); 725*1420Smarks where = strappend(where, idstr); 726*1420Smarks } 7270Sstevel@tonic-gate if (i < aclcnt - 1) 7280Sstevel@tonic-gate where = strappend(where, ","); 7290Sstevel@tonic-gate } 7300Sstevel@tonic-gate aclexport = dstr->aclexport; 7310Sstevel@tonic-gate free(dstr); 7320Sstevel@tonic-gate return (aclexport); 733*1420Smarks 734*1420Smarks 735*1420Smarks 736*1420Smarks 7370Sstevel@tonic-gate } 7380Sstevel@tonic-gate 739*1420Smarks char * 740*1420Smarks acltotext(aclent_t *aclp, int aclcnt) 7410Sstevel@tonic-gate { 742*1420Smarks return (aclent_acltotext(aclp, aclcnt, 0)); 743*1420Smarks } 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate 746789Sahrens aclent_t * 747789Sahrens aclfromtext(char *aclstr, int *aclcnt) 748789Sahrens { 749789Sahrens acl_t *aclp; 750789Sahrens aclent_t *aclentp; 751789Sahrens int error; 752789Sahrens 753*1420Smarks error = acl_fromtext(aclstr, &aclp); 754789Sahrens if (error) 755789Sahrens return (NULL); 756789Sahrens 757789Sahrens aclentp = aclp->acl_aclp; 758789Sahrens aclp->acl_aclp = NULL; 759*1420Smarks *aclcnt = aclp->acl_cnt; 760789Sahrens 761*1420Smarks acl_free(aclp); 762789Sahrens return (aclentp); 763789Sahrens } 764789Sahrens 765789Sahrens 7660Sstevel@tonic-gate static char * 7670Sstevel@tonic-gate strappend(char *where, char *newstr) 7680Sstevel@tonic-gate { 7690Sstevel@tonic-gate (void) strcat(where, newstr); 7700Sstevel@tonic-gate return (where + strlen(newstr)); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate static char * 7740Sstevel@tonic-gate convert_perm(char *where, o_mode_t perm) 7750Sstevel@tonic-gate { 776*1420Smarks if (perm & S_IROTH) 7770Sstevel@tonic-gate where = strappend(where, "r"); 7780Sstevel@tonic-gate else 7790Sstevel@tonic-gate where = strappend(where, "-"); 780*1420Smarks if (perm & S_IWOTH) 7810Sstevel@tonic-gate where = strappend(where, "w"); 7820Sstevel@tonic-gate else 7830Sstevel@tonic-gate where = strappend(where, "-"); 784*1420Smarks if (perm & S_IXOTH) 7850Sstevel@tonic-gate where = strappend(where, "x"); 7860Sstevel@tonic-gate else 7870Sstevel@tonic-gate where = strappend(where, "-"); 7880Sstevel@tonic-gate /* perm is the last field */ 7890Sstevel@tonic-gate return (where); 7900Sstevel@tonic-gate } 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate /* 7930Sstevel@tonic-gate * Callers should check the return code as this routine may change the string 7940Sstevel@tonic-gate * pointer in dynaclstr. 7950Sstevel@tonic-gate */ 7960Sstevel@tonic-gate static int 7970Sstevel@tonic-gate increase_length(struct dynaclstr *dacl, size_t increase) 7980Sstevel@tonic-gate { 7990Sstevel@tonic-gate char *tptr; 8000Sstevel@tonic-gate size_t newsize; 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate newsize = dacl->bufsize + increase; 8030Sstevel@tonic-gate tptr = realloc(dacl->aclexport, newsize); 8040Sstevel@tonic-gate if (tptr != NULL) { 8050Sstevel@tonic-gate dacl->aclexport = tptr; 8060Sstevel@tonic-gate dacl->bufsize = newsize; 8070Sstevel@tonic-gate return (1); 8080Sstevel@tonic-gate } else 8090Sstevel@tonic-gate return (0); 8100Sstevel@tonic-gate } 811789Sahrens 812789Sahrens /* 813*1420Smarks * ace_acltotext() convert each ace formatted acl to look like this: 814789Sahrens * 815*1420Smarks * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,] 816789Sahrens * 817789Sahrens * The maximum length of entry_type is 5 ("group") 818789Sahrens * 819*1420Smarks * The max length of a uid^gid^name entry (in theory) is 8, 820*1420Smarks * however id could be a number so we therefore use ID_STR_MAX 821789Sahrens * 822789Sahrens * The length of a perms entry is 144 i.e read_data/write_data... 823789Sahrens * to each acl entry. 824789Sahrens * 825789Sahrens * iflags: file_inherit/dir_inherit/inherit_only/no_propagate 826789Sahrens * 827789Sahrens */ 828789Sahrens 829789Sahrens #define ACE_ENTRYTYPLEN 6 830789Sahrens #define IFLAGS_SIZE 51 831*1420Smarks #define ACCESS_TYPE_SIZE 7 /* if unknown */ 832789Sahrens #define COLON_CNT 3 833789Sahrens #define PERMS_LEN 216 834*1420Smarks #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN +\ 835*1420Smarks ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX) 836789Sahrens 837789Sahrens static char * 838*1420Smarks ace_acltotext(acl_t *aceaclp, int flags) 839789Sahrens { 840789Sahrens ace_t *aclp = aceaclp->acl_aclp; 841789Sahrens int aclcnt = aceaclp->acl_cnt; 842789Sahrens char *aclexport; 843*1420Smarks char *endp; 844*1420Smarks int i; 845*1420Smarks char id[ID_STR_MAX], *idstr; 846789Sahrens int isdir = (aceaclp->acl_flags & ACL_IS_DIR); 847789Sahrens 848789Sahrens if (aclp == NULL) 849789Sahrens return (NULL); 850*1420Smarks if ((aclexport = malloc(aclcnt * ACE_ENTRY_SIZE)) == NULL) 851789Sahrens return (NULL); 852789Sahrens 853*1420Smarks aclexport[0] = '\0'; 854*1420Smarks endp = aclexport; 855789Sahrens for (i = 0; i < aclcnt; i++, aclp++) { 856*1420Smarks 857*1420Smarks (void) ace_type_txt(endp, &endp, aclp); 858*1420Smarks *endp++ = ':'; 859*1420Smarks *endp = '\0'; 860*1420Smarks (void) ace_perm_txt(endp, &endp, aclp->a_access_mask, 861*1420Smarks aclp->a_flags, isdir, flags); 862*1420Smarks *endp++ = ':'; 863*1420Smarks *endp = '\0'; 864*1420Smarks (void) ace_inherit_txt(endp, &endp, aclp->a_flags, flags); 865*1420Smarks if (flags & ACL_COMPACT_FMT || aclp->a_flags & 866*1420Smarks (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE | 867*1420Smarks (ACE_INHERIT_ONLY_ACE | ACE_NO_PROPAGATE_INHERIT_ACE))) { 868*1420Smarks *endp++ = ':'; 869*1420Smarks *endp = '\0'; 870*1420Smarks } 871*1420Smarks (void) ace_access_txt(endp, &endp, aclp->a_type); 872789Sahrens 873*1420Smarks if ((flags & ACL_APPEND_ID) && 874*1420Smarks (((aclp->a_flags & ACE_TYPE_FLAGS) == 0) || 875*1420Smarks ((aclp->a_flags & ACE_TYPE_FLAGS) == 876*1420Smarks ACE_IDENTIFIER_GROUP))) { 877*1420Smarks *endp++ = ':'; 878*1420Smarks *endp = '\0'; 879*1420Smarks id[ID_STR_MAX -1] = '\0'; /* null terminate buffer */ 880*1420Smarks idstr = lltostr(aclp->a_who, &id[ID_STR_MAX - 1]); 881*1420Smarks strcpy(endp, idstr); 882*1420Smarks endp += strlen(idstr); 883789Sahrens } 884*1420Smarks if (i < aclcnt - 1) { 885*1420Smarks *endp++ = ','; 886*1420Smarks *(endp + 1) = '\0'; 887789Sahrens } 888789Sahrens } 889789Sahrens return (aclexport); 890789Sahrens } 891789Sahrens 892*1420Smarks char * 893*1420Smarks acl_totext(acl_t *aclp, int flags) 894789Sahrens { 895789Sahrens 896*1420Smarks char *txtp; 897789Sahrens 898789Sahrens if (aclp == NULL) 899789Sahrens return (NULL); 900789Sahrens 901789Sahrens switch (aclp->acl_type) { 902789Sahrens case ACE_T: 903*1420Smarks txtp = ace_acltotext(aclp, flags); 904*1420Smarks break; 905789Sahrens case ACLENT_T: 906*1420Smarks txtp = aclent_acltotext(aclp->acl_aclp, aclp->acl_cnt, flags); 907*1420Smarks break; 908789Sahrens } 909*1420Smarks 910*1420Smarks return (txtp); 911789Sahrens } 912789Sahrens 913789Sahrens int 914789Sahrens acl_fromtext(const char *acltextp, acl_t **ret_aclp) 915789Sahrens { 916*1420Smarks int error; 917*1420Smarks char *buf; 918*1420Smarks 919*1420Smarks buf = malloc(strlen(acltextp) + 2); 920*1420Smarks if (buf == NULL) 921*1420Smarks return (EACL_MEM_ERROR); 922*1420Smarks strcpy(buf, acltextp); 923*1420Smarks strcat(buf, "\n"); 924*1420Smarks yybuf = buf; 925*1420Smarks yyreset(); 926*1420Smarks error = yyparse(); 927*1420Smarks free(buf); 928*1420Smarks 929*1420Smarks if (yyacl) { 930*1420Smarks if (error == 0) 931*1420Smarks *ret_aclp = yyacl; 932*1420Smarks else { 933*1420Smarks acl_free(yyacl); 934*1420Smarks } 935*1420Smarks yyacl = NULL; 936*1420Smarks } 937*1420Smarks return (error); 938*1420Smarks } 939*1420Smarks 940*1420Smarks int 941*1420Smarks acl_parse(const char *acltextp, acl_t **aclp) 942*1420Smarks { 943789Sahrens int error; 944789Sahrens 945*1420Smarks yyinteractive = 1; 946*1420Smarks error = acl_fromtext(acltextp, aclp); 947*1420Smarks yyinteractive = 0; 948*1420Smarks return (error); 949*1420Smarks } 950*1420Smarks 951*1420Smarks static void 952*1420Smarks ace_compact_printacl(acl_t *aclp) 953*1420Smarks { 954*1420Smarks int cnt; 955*1420Smarks ace_t *acep; 956*1420Smarks char *endp; 957*1420Smarks char buf[ACE_ENTRY_SIZE]; 958789Sahrens 959*1420Smarks for (cnt = 0, acep = aclp->acl_aclp; 960*1420Smarks cnt != aclp->acl_cnt; cnt++, acep++) { 961*1420Smarks buf[0] = '\0'; 962*1420Smarks (void) printf(" %14s:", ace_type_txt(buf, &endp, acep)); 963*1420Smarks (void) printf("%s:", ace_perm_txt(endp, &endp, 964*1420Smarks acep->a_access_mask, acep->a_flags, 965*1420Smarks aclp->acl_flags & ACL_IS_DIR, ACL_COMPACT_FMT)); 966*1420Smarks (void) printf("%s:", 967*1420Smarks ace_inherit_txt(endp, &endp, acep->a_flags, 968*1420Smarks ACL_COMPACT_FMT)); 969*1420Smarks (void) printf("%s\n", ace_access_txt(endp, &endp, 970*1420Smarks acep->a_type)); 971*1420Smarks } 972*1420Smarks } 973789Sahrens 974*1420Smarks static void 975*1420Smarks ace_printacl(acl_t *aclp, int cols, int compact) 976*1420Smarks { 977*1420Smarks int slot = 0; 978*1420Smarks char *token; 979*1420Smarks char *acltext; 980*1420Smarks 981*1420Smarks if (compact) { 982*1420Smarks ace_compact_printacl(aclp); 983*1420Smarks return; 984789Sahrens } 985789Sahrens 986*1420Smarks acltext = acl_totext(aclp, 0); 987*1420Smarks 988*1420Smarks if (acltext == NULL) 989*1420Smarks return; 990*1420Smarks 991*1420Smarks token = strtok(acltext, ","); 992*1420Smarks if (token == NULL) { 993*1420Smarks free(acltext); 994*1420Smarks return; 995789Sahrens } 996789Sahrens 997*1420Smarks do { 998*1420Smarks (void) printf(" %d:", slot++); 999*1420Smarks split_line(token, cols - 5); 1000*1420Smarks } while (token = strtok(NULL, ",")); 1001*1420Smarks free(acltext); 1002*1420Smarks } 1003*1420Smarks 1004*1420Smarks /* 1005*1420Smarks * pretty print an ACL. 1006*1420Smarks * For aclent_t ACL's the format is 1007*1420Smarks * similar to the old format used by getfacl, 1008*1420Smarks * with the addition of adding a "slot" number 1009*1420Smarks * before each entry. 1010*1420Smarks * 1011*1420Smarks * for ace_t ACL's the cols variable will break up 1012*1420Smarks * the long lines into multiple lines and will also 1013*1420Smarks * print a "slot" number. 1014*1420Smarks */ 1015*1420Smarks void 1016*1420Smarks acl_printacl(acl_t *aclp, int cols, int compact) 1017*1420Smarks { 1018*1420Smarks 1019*1420Smarks switch (aclp->acl_type) { 1020*1420Smarks case ACLENT_T: 1021*1420Smarks aclent_printacl(aclp); 1022*1420Smarks break; 1023*1420Smarks case ACE_T: 1024*1420Smarks ace_printacl(aclp, cols, compact); 1025*1420Smarks break; 1026*1420Smarks } 1027*1420Smarks } 1028*1420Smarks 1029*1420Smarks typedef struct value_table { 1030*1420Smarks char p_letter; /* perm letter such as 'r' */ 1031*1420Smarks uint32_t p_value; /* value for perm when pletter found */ 1032*1420Smarks } value_table_t; 1033*1420Smarks 1034*1420Smarks #define ACE_PERM_COUNT 14 1035*1420Smarks 1036*1420Smarks /* 1037*1420Smarks * The permission tables are layed out in positional order 1038*1420Smarks * a '-' character will indicate a permission at a given 1039*1420Smarks * position is not specified. The '-' is not part of the 1040*1420Smarks * table, but will be checked for in the permission computation 1041*1420Smarks * routine. 1042*1420Smarks */ 1043*1420Smarks value_table_t ace_perm_table[ACE_PERM_COUNT] = { 1044*1420Smarks { 'r', ACE_READ_DATA}, 1045*1420Smarks { 'w', ACE_WRITE_DATA}, 1046*1420Smarks { 'x', ACE_EXECUTE}, 1047*1420Smarks { 'p', ACE_APPEND_DATA}, 1048*1420Smarks { 'd', ACE_DELETE}, 1049*1420Smarks { 'D', ACE_DELETE_CHILD}, 1050*1420Smarks { 'a', ACE_READ_ATTRIBUTES}, 1051*1420Smarks { 'A', ACE_WRITE_ATTRIBUTES}, 1052*1420Smarks { 'R', ACE_READ_NAMED_ATTRS}, 1053*1420Smarks { 'W', ACE_WRITE_NAMED_ATTRS}, 1054*1420Smarks { 'c', ACE_READ_ACL}, 1055*1420Smarks { 'C', ACE_WRITE_ACL}, 1056*1420Smarks { 'o', ACE_WRITE_OWNER}, 1057*1420Smarks { 's', ACE_SYNCHRONIZE} 1058*1420Smarks }; 1059*1420Smarks 1060*1420Smarks #define ACLENT_PERM_COUNT 3 1061*1420Smarks 1062*1420Smarks value_table_t aclent_perm_table[ACLENT_PERM_COUNT] = { 1063*1420Smarks { 'r', S_IROTH}, 1064*1420Smarks { 'w', S_IWOTH}, 1065*1420Smarks { 'x', S_IXOTH} 1066*1420Smarks }; 1067*1420Smarks 1068*1420Smarks #define IFLAG_COUNT 6 1069*1420Smarks value_table_t inherit_table[IFLAG_COUNT] = { 1070*1420Smarks {'f', ACE_FILE_INHERIT_ACE}, 1071*1420Smarks {'d', ACE_DIRECTORY_INHERIT_ACE}, 1072*1420Smarks {'i', ACE_INHERIT_ONLY_ACE}, 1073*1420Smarks {'n', ACE_NO_PROPAGATE_INHERIT_ACE}, 1074*1420Smarks {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 1075*1420Smarks {'F', ACE_FAILED_ACCESS_ACE_FLAG} 1076*1420Smarks }; 1077*1420Smarks 1078*1420Smarks /* 1079*1420Smarks * compute value from a permission table or inheritance table 1080*1420Smarks * based on string passed in. If positional is set then 1081*1420Smarks * string must match order in permtab, otherwise any order 1082*1420Smarks * is allowed. 1083*1420Smarks */ 1084*1420Smarks int 1085*1420Smarks compute_values(value_table_t *permtab, int count, 1086*1420Smarks char *permstr, int positional, uint32_t *mask) 1087*1420Smarks { 1088*1420Smarks uint32_t perm_val = 0; 1089*1420Smarks char *pstr; 1090*1420Smarks int i, found; 1091*1420Smarks 1092*1420Smarks if (count < 0) 1093*1420Smarks return (1); 1094*1420Smarks 1095*1420Smarks if (positional) { 1096*1420Smarks for (i = 0, pstr = permstr; i != count && pstr && 1097*1420Smarks *pstr; i++, pstr++) { 1098*1420Smarks if (*pstr == permtab[i].p_letter) { 1099*1420Smarks perm_val |= permtab[i].p_value; 1100*1420Smarks } else if (*pstr != '-') { 1101*1420Smarks return (1); 1102*1420Smarks } 1103789Sahrens } 1104*1420Smarks } else { /* random order single letters with no '-' */ 1105*1420Smarks for (pstr = permstr; pstr && *pstr; pstr++) { 1106*1420Smarks for (found = 0, i = 0; i != count; i++) { 1107*1420Smarks if (*pstr == permtab[i].p_letter) { 1108*1420Smarks perm_val |= permtab[i].p_value; 1109*1420Smarks found = 1; 1110*1420Smarks break; 1111*1420Smarks } 1112*1420Smarks } 1113*1420Smarks if (found == 0) 1114*1420Smarks return (1); 1115*1420Smarks } 1116789Sahrens } 1117789Sahrens 1118*1420Smarks *mask = perm_val; 1119*1420Smarks return (0); 1120*1420Smarks } 1121789Sahrens 1122*1420Smarks /* 1123*1420Smarks * compute value for inheritance flags. 1124*1420Smarks */ 1125*1420Smarks int 1126*1420Smarks compute_ace_inherit(char *str, uint32_t *imask) 1127*1420Smarks { 1128*1420Smarks int error; 1129*1420Smarks int positional = 0; 1130789Sahrens 1131*1420Smarks if (strlen(str) == IFLAG_COUNT) 1132*1420Smarks positional = 1; 1133*1420Smarks 1134*1420Smarks error = compute_values(inherit_table, IFLAG_COUNT, 1135*1420Smarks str, positional, imask); 1136*1420Smarks 1137*1420Smarks if (error) 1138*1420Smarks return (EACL_INHERIT_ERROR); 1139*1420Smarks 1140789Sahrens return (error); 1141789Sahrens } 1142*1420Smarks 1143*1420Smarks 1144*1420Smarks /* 1145*1420Smarks * compute value for ACE permissions. 1146*1420Smarks */ 1147*1420Smarks int 1148*1420Smarks compute_ace_perms(char *str, uint32_t *mask) 1149*1420Smarks { 1150*1420Smarks int positional = 0; 1151*1420Smarks int error; 1152*1420Smarks 1153*1420Smarks if (strlen(str) == ACE_PERM_COUNT) 1154*1420Smarks positional = 1; 1155*1420Smarks 1156*1420Smarks error = compute_values(ace_perm_table, ACE_PERM_COUNT, 1157*1420Smarks str, positional, mask); 1158*1420Smarks 1159*1420Smarks if (error && positional) { 1160*1420Smarks /* 1161*1420Smarks * If positional was set, then make sure permissions 1162*1420Smarks * aren't actually valid in non positional case where 1163*1420Smarks * all permissions are specified, just in random order. 1164*1420Smarks */ 1165*1420Smarks error = compute_values(ace_perm_table, 1166*1420Smarks ACE_PERM_COUNT, str, 0, mask); 1167*1420Smarks } 1168*1420Smarks if (error) 1169*1420Smarks error = EACL_PERM_MASK_ERROR; 1170*1420Smarks 1171*1420Smarks return (error); 1172*1420Smarks } 1173*1420Smarks 1174*1420Smarks 1175*1420Smarks 1176*1420Smarks /* 1177*1420Smarks * compute values for aclent permissions. 1178*1420Smarks */ 1179*1420Smarks int 1180*1420Smarks compute_aclent_perms(char *str, o_mode_t *mask) 1181*1420Smarks { 1182*1420Smarks int error; 1183*1420Smarks uint32_t pmask; 1184*1420Smarks 1185*1420Smarks if (strlen(str) != ACLENT_PERM_COUNT) 1186*1420Smarks return (EACL_PERM_MASK_ERROR); 1187*1420Smarks 1188*1420Smarks *mask = 0; 1189*1420Smarks error = compute_values(aclent_perm_table, ACLENT_PERM_COUNT, 1190*1420Smarks str, 1, &pmask); 1191*1420Smarks if (error == 0) { 1192*1420Smarks *mask = (o_mode_t)pmask; 1193*1420Smarks } else 1194*1420Smarks error = EACL_PERM_MASK_ERROR; 1195*1420Smarks return (error); 1196*1420Smarks } 1197*1420Smarks 1198*1420Smarks /* 1199*1420Smarks * determine ACE permissions. 1200*1420Smarks */ 1201*1420Smarks int 1202*1420Smarks ace_perm_mask(struct acl_perm_type *aclperm, uint32_t *mask) 1203*1420Smarks { 1204*1420Smarks int error; 1205*1420Smarks 1206*1420Smarks if (aclperm->perm_style == PERM_TYPE_EMPTY) { 1207*1420Smarks *mask = 0; 1208*1420Smarks return (0); 1209*1420Smarks } 1210*1420Smarks 1211*1420Smarks if (aclperm->perm_style == PERM_TYPE_ACE) { 1212*1420Smarks *mask = aclperm->perm_val; 1213*1420Smarks return (0); 1214*1420Smarks } 1215*1420Smarks 1216*1420Smarks error = compute_ace_perms(aclperm->perm_str, mask); 1217*1420Smarks if (error) { 1218*1420Smarks acl_error(gettext("Invalid permission(s) '%s' specified\n"), 1219*1420Smarks aclperm->perm_str); 1220*1420Smarks return (EACL_PERM_MASK_ERROR); 1221*1420Smarks } 1222*1420Smarks 1223*1420Smarks return (0); 1224*1420Smarks } 1225