/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #define EXIT_OK 0 #define EXIT_FATAL 1 #define EXIT_NON_FATAL 2 #ifndef TEXT_DOMAIN /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" #endif #define INCRAUTHS 512 typedef struct cbs { int auth_cnt; int auth_max; char **auths; } cbs_t; static int show_auths(char *, int); static int add_auth(const char *, void *, void *); static void free_auths(cbs_t *); static void simplify(cbs_t *); static char *progname = "auths"; int main(int argc, char *argv[]) { int status = EXIT_OK; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); switch (argc) { case 1: status = show_auths(NULL, 0); break; case 2: status = show_auths(argv[argc-1], 0); break; default: while (*++argv) { status = show_auths(*argv, 1); if (status == EXIT_FATAL) { break; } } break; } status = (status == EXIT_OK) ? status : EXIT_FATAL; return (status); } static int show_auths(char *username, int print_name) { int status = EXIT_OK; struct passwd *pw; int i; cbs_t cbs = { 0, 0, NULL }; if (username == NULL) { if ((pw = getpwuid(getuid())) == NULL) { status = EXIT_NON_FATAL; (void) fprintf(stderr, "%s: ", progname); (void) fprintf(stderr, gettext("No passwd entry\n")); return (status); } username = pw->pw_name; } else if (getpwnam(username) == NULL) { status = EXIT_NON_FATAL; (void) fprintf(stderr, "%s: %s : ", progname, username); (void) fprintf(stderr, gettext("No such user\n")); return (status); } (void) _enum_auths(username, add_auth, NULL, &cbs); if (cbs.auth_cnt == 0) status = EXIT_NON_FATAL; if (status == EXIT_NON_FATAL) { (void) fprintf(stderr, "%s: %s: ", progname, username); (void) fprintf(stderr, gettext("No authorizations\n")); } else { simplify(&cbs); if (print_name) (void) printf("%s: ", username); /* print out the auths */ for (i = 0; i < cbs.auth_cnt - 1; i++) (void) printf("%s,", cbs.auths[i]); /* print out the last entry, without the comma */ (void) printf("%s\n", cbs.auths[cbs.auth_cnt - 1]); /* free memory allocated for authorizations */ free_auths(&cbs); } return (status); } /*ARGSUSED*/ static int add_auth(const char *authname, void *ctxt, void *res) { cbs_t *cbs = res; if (cbs->auth_cnt >= cbs->auth_max) { cbs->auth_max += INCRAUTHS; cbs->auths = realloc(cbs->auths, cbs->auth_max * sizeof (char *)); if (cbs->auths == NULL) { (void) fprintf(stderr, "%s: ", progname); (void) fprintf(stderr, gettext("Out of memory\n")); exit(1); } } cbs->auths[cbs->auth_cnt] = strdup(authname); cbs->auth_cnt++; return (0); } static void free_auths(cbs_t *cbs) { int i; for (i = 0; i < cbs->auth_cnt; i++) free(cbs->auths[i]); free(cbs->auths); } /* We have always ignored .grant in auths(1) */ static boolean_t auth_match(const char *pattern, const char *auth) { size_t len = strlen(pattern); if (pattern[len - 1] != KV_WILDCHAR) return (B_FALSE); return (strncmp(pattern, auth, len - 1) == 0); } static int mstrptr(const void *a, const void *b) { char *const *ap = a; char *const *bp = b; return (strcmp(*ap, *bp)); } /* * Simplify the returned authorizations: sort and match wildcards; * we're using here that "*" sorts before any other character. */ static void simplify(cbs_t *cbs) { int rem, i; /* First we sort */ qsort(cbs->auths, cbs->auth_cnt, sizeof (cbs->auths[0]), mstrptr); /* * Then we remove the entries which match a later entry. * We walk the list, with "i + rem + 1" the cursor for the possible * candidate for removal. With "rem" we count the removed entries * and we copy while we're looking for duplicate/superfluous entries. */ for (i = 0, rem = 0; i < cbs->auth_cnt - rem - 1; ) { if (strcmp(cbs->auths[i], cbs->auths[i + rem + 1]) == 0 || strchr(cbs->auths[i], KV_WILDCHAR) != NULL && auth_match(cbs->auths[i], cbs->auths[i + rem + 1])) { free(cbs->auths[i + rem + 1]); rem++; } else { i++; if (rem > 0) cbs->auths[i] = cbs->auths[i + rem]; } } cbs->auth_cnt -= rem; }