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
main(int argc,char * argv[])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
show_auths(char * username,int print_name)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
add_auth(const char * authname,void * ctxt,void * res)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
free_auths(cbs_t * cbs)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
auth_match(const char * pattern,const char * auth)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
mstrptr(const void * a,const void * b)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
simplify(cbs_t * cbs)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