17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 514839a76Sbubbva * Common Development and Distribution License (the "License"). 614839a76Sbubbva * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*134a1f4eSCasper H.S. Dik * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <stdio.h> 267c478bd9Sstevel@tonic-gate #include <stdlib.h> 277c478bd9Sstevel@tonic-gate #include <unistd.h> 287c478bd9Sstevel@tonic-gate #include <pwd.h> 297c478bd9Sstevel@tonic-gate #include <string.h> 307c478bd9Sstevel@tonic-gate #include <deflt.h> 317c478bd9Sstevel@tonic-gate #include <libintl.h> 327c478bd9Sstevel@tonic-gate #include <locale.h> 337c478bd9Sstevel@tonic-gate #include <user_attr.h> 347c478bd9Sstevel@tonic-gate #include <prof_attr.h> 357c478bd9Sstevel@tonic-gate #include <auth_attr.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #define EXIT_OK 0 387c478bd9Sstevel@tonic-gate #define EXIT_FATAL 1 397c478bd9Sstevel@tonic-gate #define EXIT_NON_FATAL 2 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN /* Should be defined by cc -D */ 427c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 437c478bd9Sstevel@tonic-gate #endif 447c478bd9Sstevel@tonic-gate 45*134a1f4eSCasper H.S. Dik #define INCRAUTHS 512 467c478bd9Sstevel@tonic-gate 47*134a1f4eSCasper H.S. Dik typedef struct cbs { 48*134a1f4eSCasper H.S. Dik int auth_cnt; 49*134a1f4eSCasper H.S. Dik int auth_max; 50*134a1f4eSCasper H.S. Dik char **auths; 51*134a1f4eSCasper H.S. Dik } cbs_t; 527c478bd9Sstevel@tonic-gate 53*134a1f4eSCasper H.S. Dik static int show_auths(char *, int); 54*134a1f4eSCasper H.S. Dik static int add_auth(const char *, void *, void *); 55*134a1f4eSCasper H.S. Dik static void free_auths(cbs_t *); 56*134a1f4eSCasper H.S. Dik static void simplify(cbs_t *); 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate static char *progname = "auths"; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate int 617c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate int status = EXIT_OK; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 667c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate switch (argc) { 697c478bd9Sstevel@tonic-gate case 1: 70*134a1f4eSCasper H.S. Dik status = show_auths(NULL, 0); 717c478bd9Sstevel@tonic-gate break; 727c478bd9Sstevel@tonic-gate case 2: 73*134a1f4eSCasper H.S. Dik status = show_auths(argv[argc-1], 0); 747c478bd9Sstevel@tonic-gate break; 757c478bd9Sstevel@tonic-gate default: 767c478bd9Sstevel@tonic-gate while (*++argv) { 77*134a1f4eSCasper H.S. Dik status = show_auths(*argv, 1); 787c478bd9Sstevel@tonic-gate if (status == EXIT_FATAL) { 797c478bd9Sstevel@tonic-gate break; 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate break; 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate status = (status == EXIT_OK) ? status : EXIT_FATAL; 867c478bd9Sstevel@tonic-gate return (status); 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate static int 90*134a1f4eSCasper H.S. Dik show_auths(char *username, int print_name) 917c478bd9Sstevel@tonic-gate { 927c478bd9Sstevel@tonic-gate int status = EXIT_OK; 937c478bd9Sstevel@tonic-gate struct passwd *pw; 94*134a1f4eSCasper H.S. Dik int i; 95*134a1f4eSCasper H.S. Dik cbs_t cbs = { 0, 0, NULL }; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate if (username == NULL) { 987c478bd9Sstevel@tonic-gate if ((pw = getpwuid(getuid())) == NULL) { 997c478bd9Sstevel@tonic-gate status = EXIT_NON_FATAL; 1007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", progname); 1017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("No passwd entry\n")); 1027c478bd9Sstevel@tonic-gate return (status); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate username = pw->pw_name; 10514839a76Sbubbva } else if (getpwnam(username) == NULL) { 1067c478bd9Sstevel@tonic-gate status = EXIT_NON_FATAL; 1077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s : ", progname, username); 1087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("No such user\n")); 1097c478bd9Sstevel@tonic-gate return (status); 1107c478bd9Sstevel@tonic-gate } 1117c478bd9Sstevel@tonic-gate 112*134a1f4eSCasper H.S. Dik (void) _enum_auths(username, add_auth, NULL, &cbs); 113*134a1f4eSCasper H.S. Dik 114*134a1f4eSCasper H.S. Dik if (cbs.auth_cnt == 0) 1157c478bd9Sstevel@tonic-gate status = EXIT_NON_FATAL; 116*134a1f4eSCasper H.S. Dik 1177c478bd9Sstevel@tonic-gate if (status == EXIT_NON_FATAL) { 1187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: ", progname, username); 1197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("No authorizations\n")); 1207c478bd9Sstevel@tonic-gate } else { 121*134a1f4eSCasper H.S. Dik simplify(&cbs); 1227c478bd9Sstevel@tonic-gate 123*134a1f4eSCasper H.S. Dik if (print_name) 124*134a1f4eSCasper H.S. Dik (void) printf("%s: ", username); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* print out the auths */ 127*134a1f4eSCasper H.S. Dik for (i = 0; i < cbs.auth_cnt - 1; i++) 128*134a1f4eSCasper H.S. Dik (void) printf("%s,", cbs.auths[i]); 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* print out the last entry, without the comma */ 131*134a1f4eSCasper H.S. Dik (void) printf("%s\n", cbs.auths[cbs.auth_cnt - 1]); 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* free memory allocated for authorizations */ 134*134a1f4eSCasper H.S. Dik free_auths(&cbs); 135*134a1f4eSCasper H.S. Dik } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate return (status); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 140*134a1f4eSCasper H.S. Dik /*ARGSUSED*/ 141*134a1f4eSCasper H.S. Dik static int 142*134a1f4eSCasper H.S. Dik add_auth(const char *authname, void *ctxt, void *res) 143*134a1f4eSCasper H.S. Dik { 144*134a1f4eSCasper H.S. Dik cbs_t *cbs = res; 145*134a1f4eSCasper H.S. Dik 146*134a1f4eSCasper H.S. Dik if (cbs->auth_cnt >= cbs->auth_max) { 147*134a1f4eSCasper H.S. Dik cbs->auth_max += INCRAUTHS; 148*134a1f4eSCasper H.S. Dik cbs->auths = realloc(cbs->auths, 149*134a1f4eSCasper H.S. Dik cbs->auth_max * sizeof (char *)); 150*134a1f4eSCasper H.S. Dik 151*134a1f4eSCasper H.S. Dik if (cbs->auths == NULL) { 152*134a1f4eSCasper H.S. Dik (void) fprintf(stderr, "%s: ", progname); 153*134a1f4eSCasper H.S. Dik (void) fprintf(stderr, gettext("Out of memory\n")); 154*134a1f4eSCasper H.S. Dik exit(1); 155*134a1f4eSCasper H.S. Dik } 156*134a1f4eSCasper H.S. Dik } 157*134a1f4eSCasper H.S. Dik 158*134a1f4eSCasper H.S. Dik cbs->auths[cbs->auth_cnt] = strdup(authname); 159*134a1f4eSCasper H.S. Dik cbs->auth_cnt++; 160*134a1f4eSCasper H.S. Dik 161*134a1f4eSCasper H.S. Dik return (0); 162*134a1f4eSCasper H.S. Dik } 163*134a1f4eSCasper H.S. Dik 164*134a1f4eSCasper H.S. Dik static void 165*134a1f4eSCasper H.S. Dik free_auths(cbs_t *cbs) 166*134a1f4eSCasper H.S. Dik { 167*134a1f4eSCasper H.S. Dik int i; 168*134a1f4eSCasper H.S. Dik 169*134a1f4eSCasper H.S. Dik for (i = 0; i < cbs->auth_cnt; i++) 170*134a1f4eSCasper H.S. Dik free(cbs->auths[i]); 171*134a1f4eSCasper H.S. Dik 172*134a1f4eSCasper H.S. Dik free(cbs->auths); 173*134a1f4eSCasper H.S. Dik } 174*134a1f4eSCasper H.S. Dik 175*134a1f4eSCasper H.S. Dik /* We have always ignored .grant in auths(1) */ 176*134a1f4eSCasper H.S. Dik static boolean_t 177*134a1f4eSCasper H.S. Dik auth_match(const char *pattern, const char *auth) 178*134a1f4eSCasper H.S. Dik { 179*134a1f4eSCasper H.S. Dik size_t len = strlen(pattern); 180*134a1f4eSCasper H.S. Dik 181*134a1f4eSCasper H.S. Dik if (pattern[len - 1] != KV_WILDCHAR) 182*134a1f4eSCasper H.S. Dik return (B_FALSE); 183*134a1f4eSCasper H.S. Dik 184*134a1f4eSCasper H.S. Dik return (strncmp(pattern, auth, len - 1) == 0); 185*134a1f4eSCasper H.S. Dik } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate static int 188*134a1f4eSCasper H.S. Dik mstrptr(const void *a, const void *b) 1897c478bd9Sstevel@tonic-gate { 190*134a1f4eSCasper H.S. Dik char *const *ap = a; 191*134a1f4eSCasper H.S. Dik char *const *bp = b; 1927c478bd9Sstevel@tonic-gate 193*134a1f4eSCasper H.S. Dik return (strcmp(*ap, *bp)); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* 197*134a1f4eSCasper H.S. Dik * Simplify the returned authorizations: sort and match wildcards; 198*134a1f4eSCasper H.S. Dik * we're using here that "*" sorts before any other character. 1997c478bd9Sstevel@tonic-gate */ 200*134a1f4eSCasper H.S. Dik static void 201*134a1f4eSCasper H.S. Dik simplify(cbs_t *cbs) 202*134a1f4eSCasper H.S. Dik { 203*134a1f4eSCasper H.S. Dik int rem, i; 204*134a1f4eSCasper H.S. Dik 205*134a1f4eSCasper H.S. Dik /* First we sort */ 206*134a1f4eSCasper H.S. Dik qsort(cbs->auths, cbs->auth_cnt, sizeof (cbs->auths[0]), mstrptr); 207*134a1f4eSCasper H.S. Dik 208*134a1f4eSCasper H.S. Dik /* 209*134a1f4eSCasper H.S. Dik * Then we remove the entries which match a later entry. 210*134a1f4eSCasper H.S. Dik * We walk the list, with "i + rem + 1" the cursor for the possible 211*134a1f4eSCasper H.S. Dik * candidate for removal. With "rem" we count the removed entries 212*134a1f4eSCasper H.S. Dik * and we copy while we're looking for duplicate/superfluous entries. 213*134a1f4eSCasper H.S. Dik */ 214*134a1f4eSCasper H.S. Dik for (i = 0, rem = 0; i < cbs->auth_cnt - rem - 1; ) { 215*134a1f4eSCasper H.S. Dik if (strcmp(cbs->auths[i], cbs->auths[i + rem + 1]) == 0 || 216*134a1f4eSCasper H.S. Dik strchr(cbs->auths[i], KV_WILDCHAR) != NULL && 217*134a1f4eSCasper H.S. Dik auth_match(cbs->auths[i], cbs->auths[i + rem + 1])) { 218*134a1f4eSCasper H.S. Dik free(cbs->auths[i + rem + 1]); 219*134a1f4eSCasper H.S. Dik rem++; 220*134a1f4eSCasper H.S. Dik } else { 221*134a1f4eSCasper H.S. Dik i++; 222*134a1f4eSCasper H.S. Dik if (rem > 0) 223*134a1f4eSCasper H.S. Dik cbs->auths[i] = cbs->auths[i + rem]; 224*134a1f4eSCasper H.S. Dik } 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 227*134a1f4eSCasper H.S. Dik cbs->auth_cnt -= rem; 2287c478bd9Sstevel@tonic-gate } 229