xref: /illumos-gate/usr/src/cmd/auths/auths.c (revision 134a1f4e)
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)
115*134a1f4eSCasper H.S. Dik 		status = EXIT_NON_FATAL;
116*134a1f4eSCasper H.S. Dik 
1177c478bd9Sstevel@tonic-gate 	if (status == EXIT_NON_FATAL) {
118*134a1f4eSCasper H.S. Dik 		(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 
126*134a1f4eSCasper H.S. Dik 		/* 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 
130*134a1f4eSCasper H.S. Dik 		/* 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 
133*134a1f4eSCasper H.S. Dik 		/* free memory allocated for authorizations */
134*134a1f4eSCasper H.S. Dik 		free_auths(&cbs);
1357c478bd9Sstevel@tonic-gate 	}
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)
1437c478bd9Sstevel@tonic-gate {
144*134a1f4eSCasper H.S. Dik 	cbs_t	*cbs = res;
1457c478bd9Sstevel@tonic-gate 
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 *));
150499fd601Sgww 
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);
155499fd601Sgww 		}
156499fd601Sgww 	}
157499fd601Sgww 
158*134a1f4eSCasper H.S. Dik 	cbs->auths[cbs->auth_cnt] = strdup(authname);
159*134a1f4eSCasper H.S. Dik 	cbs->auth_cnt++;
1607c478bd9Sstevel@tonic-gate 
161*134a1f4eSCasper H.S. Dik 	return (0);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
164*134a1f4eSCasper H.S. Dik static void
free_auths(cbs_t * cbs)165*134a1f4eSCasper H.S. Dik free_auths(cbs_t *cbs)
1667c478bd9Sstevel@tonic-gate {
167*134a1f4eSCasper H.S. Dik 	int i;
1687c478bd9Sstevel@tonic-gate 
169*134a1f4eSCasper H.S. Dik 	for (i = 0; i < cbs->auth_cnt; i++)
170*134a1f4eSCasper H.S. Dik 		free(cbs->auths[i]);
1717c478bd9Sstevel@tonic-gate 
172*134a1f4eSCasper H.S. Dik 	free(cbs->auths);
173*134a1f4eSCasper H.S. Dik }
1747c478bd9Sstevel@tonic-gate 
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);
1807c478bd9Sstevel@tonic-gate 
181*134a1f4eSCasper H.S. Dik 	if (pattern[len - 1] != KV_WILDCHAR)
182*134a1f4eSCasper H.S. Dik 		return (B_FALSE);
1837c478bd9Sstevel@tonic-gate 
184*134a1f4eSCasper H.S. Dik 	return (strncmp(pattern, auth, len - 1) == 0);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate 
187*134a1f4eSCasper H.S. Dik static int
mstrptr(const void * a,const void * b)188*134a1f4eSCasper H.S. Dik mstrptr(const void *a, const void *b)
189499fd601Sgww {
190*134a1f4eSCasper H.S. Dik 	char *const *ap = a;
191*134a1f4eSCasper H.S. Dik 	char *const *bp = b;
192499fd601Sgww 
193*134a1f4eSCasper H.S. Dik 	return (strcmp(*ap, *bp));
194499fd601Sgww }
195499fd601Sgww 
196*134a1f4eSCasper H.S. Dik /*
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.
199*134a1f4eSCasper H.S. Dik  */
2007c478bd9Sstevel@tonic-gate static void
simplify(cbs_t * cbs)201*134a1f4eSCasper H.S. Dik simplify(cbs_t *cbs)
2027c478bd9Sstevel@tonic-gate {
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];
2247c478bd9Sstevel@tonic-gate 		}
2257c478bd9Sstevel@tonic-gate 	}
226*134a1f4eSCasper H.S. Dik 
227*134a1f4eSCasper H.S. Dik 	cbs->auth_cnt -= rem;
2287c478bd9Sstevel@tonic-gate }
229