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