1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <unistd.h> 28 #include <pwd.h> 29 #include <string.h> 30 #include <deflt.h> 31 #include <libintl.h> 32 #include <locale.h> 33 #include <user_attr.h> 34 #include <prof_attr.h> 35 #include <auth_attr.h> 36 37 #define EXIT_OK 0 38 #define EXIT_FATAL 1 39 #define EXIT_NON_FATAL 2 40 41 #ifndef TEXT_DOMAIN /* Should be defined by cc -D */ 42 #define TEXT_DOMAIN "SYS_TEST" 43 #endif 44 45 #define INCRAUTHS 512 46 47 typedef struct cbs { 48 int auth_cnt; 49 int auth_max; 50 char **auths; 51 } cbs_t; 52 53 static int show_auths(char *, int); 54 static int add_auth(const char *, void *, void *); 55 static void free_auths(cbs_t *); 56 static void simplify(cbs_t *); 57 58 static char *progname = "auths"; 59 60 int 61 main(int argc, char *argv[]) 62 { 63 int status = EXIT_OK; 64 65 (void) setlocale(LC_ALL, ""); 66 (void) textdomain(TEXT_DOMAIN); 67 68 switch (argc) { 69 case 1: 70 status = show_auths(NULL, 0); 71 break; 72 case 2: 73 status = show_auths(argv[argc-1], 0); 74 break; 75 default: 76 while (*++argv) { 77 status = show_auths(*argv, 1); 78 if (status == EXIT_FATAL) { 79 break; 80 } 81 } 82 break; 83 } 84 85 status = (status == EXIT_OK) ? status : EXIT_FATAL; 86 return (status); 87 } 88 89 static int 90 show_auths(char *username, int print_name) 91 { 92 int status = EXIT_OK; 93 struct passwd *pw; 94 int i; 95 cbs_t cbs = { 0, 0, NULL }; 96 97 if (username == NULL) { 98 if ((pw = getpwuid(getuid())) == NULL) { 99 status = EXIT_NON_FATAL; 100 (void) fprintf(stderr, "%s: ", progname); 101 (void) fprintf(stderr, gettext("No passwd entry\n")); 102 return (status); 103 } 104 username = pw->pw_name; 105 } else if (getpwnam(username) == NULL) { 106 status = EXIT_NON_FATAL; 107 (void) fprintf(stderr, "%s: %s : ", progname, username); 108 (void) fprintf(stderr, gettext("No such user\n")); 109 return (status); 110 } 111 112 (void) _enum_auths(username, add_auth, NULL, &cbs); 113 114 if (cbs.auth_cnt == 0) 115 status = EXIT_NON_FATAL; 116 117 if (status == EXIT_NON_FATAL) { 118 (void) fprintf(stderr, "%s: %s: ", progname, username); 119 (void) fprintf(stderr, gettext("No authorizations\n")); 120 } else { 121 simplify(&cbs); 122 123 if (print_name) 124 (void) printf("%s: ", username); 125 126 /* print out the auths */ 127 for (i = 0; i < cbs.auth_cnt - 1; i++) 128 (void) printf("%s,", cbs.auths[i]); 129 130 /* print out the last entry, without the comma */ 131 (void) printf("%s\n", cbs.auths[cbs.auth_cnt - 1]); 132 133 /* free memory allocated for authorizations */ 134 free_auths(&cbs); 135 } 136 137 return (status); 138 } 139 140 /*ARGSUSED*/ 141 static int 142 add_auth(const char *authname, void *ctxt, void *res) 143 { 144 cbs_t *cbs = res; 145 146 if (cbs->auth_cnt >= cbs->auth_max) { 147 cbs->auth_max += INCRAUTHS; 148 cbs->auths = realloc(cbs->auths, 149 cbs->auth_max * sizeof (char *)); 150 151 if (cbs->auths == NULL) { 152 (void) fprintf(stderr, "%s: ", progname); 153 (void) fprintf(stderr, gettext("Out of memory\n")); 154 exit(1); 155 } 156 } 157 158 cbs->auths[cbs->auth_cnt] = strdup(authname); 159 cbs->auth_cnt++; 160 161 return (0); 162 } 163 164 static void 165 free_auths(cbs_t *cbs) 166 { 167 int i; 168 169 for (i = 0; i < cbs->auth_cnt; i++) 170 free(cbs->auths[i]); 171 172 free(cbs->auths); 173 } 174 175 /* We have always ignored .grant in auths(1) */ 176 static boolean_t 177 auth_match(const char *pattern, const char *auth) 178 { 179 size_t len = strlen(pattern); 180 181 if (pattern[len - 1] != KV_WILDCHAR) 182 return (B_FALSE); 183 184 return (strncmp(pattern, auth, len - 1) == 0); 185 } 186 187 static int 188 mstrptr(const void *a, const void *b) 189 { 190 char *const *ap = a; 191 char *const *bp = b; 192 193 return (strcmp(*ap, *bp)); 194 } 195 196 /* 197 * Simplify the returned authorizations: sort and match wildcards; 198 * we're using here that "*" sorts before any other character. 199 */ 200 static void 201 simplify(cbs_t *cbs) 202 { 203 int rem, i; 204 205 /* First we sort */ 206 qsort(cbs->auths, cbs->auth_cnt, sizeof (cbs->auths[0]), mstrptr); 207 208 /* 209 * Then we remove the entries which match a later entry. 210 * We walk the list, with "i + rem + 1" the cursor for the possible 211 * candidate for removal. With "rem" we count the removed entries 212 * and we copy while we're looking for duplicate/superfluous entries. 213 */ 214 for (i = 0, rem = 0; i < cbs->auth_cnt - rem - 1; ) { 215 if (strcmp(cbs->auths[i], cbs->auths[i + rem + 1]) == 0 || 216 strchr(cbs->auths[i], KV_WILDCHAR) != NULL && 217 auth_match(cbs->auths[i], cbs->auths[i + rem + 1])) { 218 free(cbs->auths[i + rem + 1]); 219 rem++; 220 } else { 221 i++; 222 if (rem > 0) 223 cbs->auths[i] = cbs->auths[i + rem]; 224 } 225 } 226 227 cbs->auth_cnt -= rem; 228 } 229