xref: /illumos-gate/usr/src/cmd/profiles/profiles.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 <libintl.h>
317c478bd9Sstevel@tonic-gate #include <locale.h>
327c478bd9Sstevel@tonic-gate #include <deflt.h>
337c478bd9Sstevel@tonic-gate #include <user_attr.h>
347c478bd9Sstevel@tonic-gate #include <prof_attr.h>
357c478bd9Sstevel@tonic-gate #include <exec_attr.h>
367c478bd9Sstevel@tonic-gate #include <auth_attr.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #define	EXIT_OK		0
407c478bd9Sstevel@tonic-gate #define	EXIT_FATAL	1
417c478bd9Sstevel@tonic-gate #define	EXIT_NON_FATAL	2
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #define	TMP_BUF_LEN	2048		/* size of temp string buffer */
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define	PRINT_DEFAULT	0x0000
467c478bd9Sstevel@tonic-gate #define	PRINT_NAME	0x0010
477c478bd9Sstevel@tonic-gate #define	PRINT_LONG	0x0020
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN			/* Should be defined by cc -D */
507c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
517c478bd9Sstevel@tonic-gate #endif
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate static void usage();
547c478bd9Sstevel@tonic-gate static int show_profs(char *, int);
55b4820df8SJoep Vesseur static void print_profs_long(execattr_t *);
56*134a1f4eSCasper H.S. Dik static void print_profile_privs(kva_t *);
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate static char *progname = "profiles";
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 	extern int	optind;
6458d1a73cSgww 	int		c;
6558d1a73cSgww 	int		status = EXIT_OK;
667c478bd9Sstevel@tonic-gate 	int		print_flag = PRINT_DEFAULT;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
697c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "l")) != EOF) {
727c478bd9Sstevel@tonic-gate 		switch (c) {
737c478bd9Sstevel@tonic-gate 		case 'l':
747c478bd9Sstevel@tonic-gate 			print_flag |= PRINT_LONG;
757c478bd9Sstevel@tonic-gate 			break;
767c478bd9Sstevel@tonic-gate 		default:
777c478bd9Sstevel@tonic-gate 			usage();
787c478bd9Sstevel@tonic-gate 			return (EXIT_FATAL);
797c478bd9Sstevel@tonic-gate 		}
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 	argc -= optind;
827c478bd9Sstevel@tonic-gate 	argv += optind;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (*argv == NULL) {
85499fd601Sgww 		status = show_profs(NULL, print_flag);
867c478bd9Sstevel@tonic-gate 	} else {
877c478bd9Sstevel@tonic-gate 		do {
88b4820df8SJoep Vesseur 			(void) printf("%s:\n", *argv);
8958d1a73cSgww 			status = show_profs((char *)*argv,
9058d1a73cSgww 			    (print_flag | PRINT_NAME));
917c478bd9Sstevel@tonic-gate 			if (status == EXIT_FATAL) {
927c478bd9Sstevel@tonic-gate 				break;
937c478bd9Sstevel@tonic-gate 			}
94b4820df8SJoep Vesseur 			if (argv[1] != NULL) {
95b4820df8SJoep Vesseur 				/* seperate users with empty line */
96b4820df8SJoep Vesseur 				(void) printf("\n");
97b4820df8SJoep Vesseur 			}
987c478bd9Sstevel@tonic-gate 		} while (*++argv);
997c478bd9Sstevel@tonic-gate 	}
1007c478bd9Sstevel@tonic-gate 	status = (status == EXIT_OK) ? status : EXIT_FATAL;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	return (status);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate 
105*134a1f4eSCasper H.S. Dik static int
show_profs_callback(const char * prof,kva_t * pa,void * pflag,void * vcnt)106*134a1f4eSCasper H.S. Dik show_profs_callback(const char *prof, kva_t *pa, void *pflag, void *vcnt)
107*134a1f4eSCasper H.S. Dik {
108*134a1f4eSCasper H.S. Dik 	char *indent = "";
109*134a1f4eSCasper H.S. Dik 	const int *print_flag = pflag;
110*134a1f4eSCasper H.S. Dik 	int *pcnt = vcnt;
111*134a1f4eSCasper H.S. Dik 
112*134a1f4eSCasper H.S. Dik 	(*pcnt)++;
113*134a1f4eSCasper H.S. Dik 
114*134a1f4eSCasper H.S. Dik 	if ((*print_flag) & PRINT_NAME) {
115*134a1f4eSCasper H.S. Dik 		indent = "          ";
116*134a1f4eSCasper H.S. Dik 	}
117*134a1f4eSCasper H.S. Dik 
118*134a1f4eSCasper H.S. Dik 	(void) printf("%s%s", indent, prof);
119*134a1f4eSCasper H.S. Dik 	print_profile_privs(pa);
120*134a1f4eSCasper H.S. Dik 	(void) printf("\n");
121*134a1f4eSCasper H.S. Dik 
122*134a1f4eSCasper H.S. Dik 	return (0);
123*134a1f4eSCasper H.S. Dik }
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate static int
show_profs(char * username,int print_flag)1267c478bd9Sstevel@tonic-gate show_profs(char *username, int print_flag)
1277c478bd9Sstevel@tonic-gate {
12858d1a73cSgww 	int		status = EXIT_OK;
12958d1a73cSgww 	struct passwd	*pw;
13058d1a73cSgww 	execattr_t	*exec;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	if (username == NULL) {
1337c478bd9Sstevel@tonic-gate 		if ((pw = getpwuid(getuid())) == NULL) {
1347c478bd9Sstevel@tonic-gate 			status = EXIT_NON_FATAL;
1357c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: ", progname);
1367c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("No passwd entry\n"));
1377c478bd9Sstevel@tonic-gate 			return (status);
1387c478bd9Sstevel@tonic-gate 		}
1397c478bd9Sstevel@tonic-gate 		username = pw->pw_name;
14014839a76Sbubbva 	} else if (getpwnam(username) == NULL) {
1417c478bd9Sstevel@tonic-gate 		status = EXIT_NON_FATAL;
142b4820df8SJoep Vesseur 		(void) fprintf(stderr, "%s: %s: ", progname, username);
1437c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("No such user\n"));
1447c478bd9Sstevel@tonic-gate 		return (status);
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	if (print_flag & PRINT_LONG) {
148*134a1f4eSCasper H.S. Dik 		exec = getexecuser(username, KV_COMMAND, NULL,
14901ef659dSJoep Vesseur 		    GET_ALL|__SEARCH_ALL_POLS);
150*134a1f4eSCasper H.S. Dik 		if (exec != NULL) {
151*134a1f4eSCasper H.S. Dik 			print_profs_long(exec);
152*134a1f4eSCasper H.S. Dik 			free_execattr(exec);
153*134a1f4eSCasper H.S. Dik 		} else {
1547c478bd9Sstevel@tonic-gate 			status = EXIT_NON_FATAL;
1557c478bd9Sstevel@tonic-gate 		}
1567c478bd9Sstevel@tonic-gate 	} else {
157*134a1f4eSCasper H.S. Dik 		int cnt = 0;
158*134a1f4eSCasper H.S. Dik 		(void) _enum_profs(username, show_profs_callback, &print_flag,
159*134a1f4eSCasper H.S. Dik 		    &cnt);
160*134a1f4eSCasper H.S. Dik 
161*134a1f4eSCasper H.S. Dik 		if (cnt == 0)
1627c478bd9Sstevel@tonic-gate 			status = EXIT_NON_FATAL;
1637c478bd9Sstevel@tonic-gate 	}
164*134a1f4eSCasper H.S. Dik 
165*134a1f4eSCasper H.S. Dik 	if (status == EXIT_NON_FATAL) {
166*134a1f4eSCasper H.S. Dik 		(void) fprintf(stderr, "%s: %s: ", progname, username);
167*134a1f4eSCasper H.S. Dik 		(void) fprintf(stderr, gettext("No profiles\n"));
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	return (status);
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate 
173b4820df8SJoep Vesseur /*
174b4820df8SJoep Vesseur  * print extended profile information.
175b4820df8SJoep Vesseur  *
176b4820df8SJoep Vesseur  * output is "pretty printed" like
177b4820df8SJoep Vesseur  *   [6spaces]Profile Name1[ possible profile privileges]
178b4820df8SJoep Vesseur  *   [10spaces  ]execname1 [skip to ATTR_COL]exec1 attributes1
179b4820df8SJoep Vesseur  *   [      spaces to ATTR_COL              ]exec1 attributes2
180b4820df8SJoep Vesseur  *   [10spaces  ]execname2 [skip to ATTR_COL]exec2 attributes1
181b4820df8SJoep Vesseur  *   [      spaces to ATTR_COL              ]exec2 attributes2
182b4820df8SJoep Vesseur  *   [6spaces]Profile Name2[ possible profile privileges]
183b4820df8SJoep Vesseur  *   etc
184b4820df8SJoep Vesseur  */
185b4820df8SJoep Vesseur /*
186b4820df8SJoep Vesseur  * ATTR_COL is based on
187b4820df8SJoep Vesseur  *   10 leading spaces +
188b4820df8SJoep Vesseur  *   25 positions for the executable +
189b4820df8SJoep Vesseur  *    1 space seperating the execname from the attributes
190b4820df8SJoep Vesseur  * so attribute printing starts at column 37 (36 whitespaces)
191b4820df8SJoep Vesseur  *
192b4820df8SJoep Vesseur  *  25 spaces for the execname seems reasonable since currently
193b4820df8SJoep Vesseur  *  less than 3% of the shipped exec_attr would overflow this
194b4820df8SJoep Vesseur  */
195b4820df8SJoep Vesseur #define	ATTR_COL	37
196b4820df8SJoep Vesseur 
1977c478bd9Sstevel@tonic-gate static void
print_profs_long(execattr_t * exec)198b4820df8SJoep Vesseur print_profs_long(execattr_t *exec)
1997c478bd9Sstevel@tonic-gate {
200b4820df8SJoep Vesseur 	char	*curprofile;
201b4820df8SJoep Vesseur 	int	len;
202b4820df8SJoep Vesseur 	kv_t	*kv_pair;
203b4820df8SJoep Vesseur 	char	*key;
204b4820df8SJoep Vesseur 	char	*val;
205b4820df8SJoep Vesseur 	int	i;
206b4820df8SJoep Vesseur 
207b4820df8SJoep Vesseur 	for (curprofile = ""; exec != NULL; exec = exec->next) {
208b4820df8SJoep Vesseur 		/* print profile name if it is a new one */
209b4820df8SJoep Vesseur 		if (strcmp(curprofile, exec->name) != 0) {
210*134a1f4eSCasper H.S. Dik 			profattr_t *pa;
211b4820df8SJoep Vesseur 			curprofile = exec->name;
212*134a1f4eSCasper H.S. Dik 
213b4820df8SJoep Vesseur 			(void) printf("      %s", curprofile);
214*134a1f4eSCasper H.S. Dik 
215*134a1f4eSCasper H.S. Dik 			pa = getprofnam(curprofile);
216*134a1f4eSCasper H.S. Dik 			if (pa != NULL) {
217*134a1f4eSCasper H.S. Dik 				print_profile_privs(pa->attr);
218*134a1f4eSCasper H.S. Dik 				free_profattr(pa);
219*134a1f4eSCasper H.S. Dik 			}
220b4820df8SJoep Vesseur 			(void) printf("\n");
2217c478bd9Sstevel@tonic-gate 		}
222b4820df8SJoep Vesseur 		len = printf("          %s ", exec->id);
223b4820df8SJoep Vesseur 
224b4820df8SJoep Vesseur 		if ((exec->attr == NULL || exec->attr->data == NULL)) {
2257c478bd9Sstevel@tonic-gate 			(void) printf("\n");
2267c478bd9Sstevel@tonic-gate 			continue;
2277c478bd9Sstevel@tonic-gate 		}
228b4820df8SJoep Vesseur 
229b4820df8SJoep Vesseur 		/*
230b4820df8SJoep Vesseur 		 * if printing the name of the executable got us past the
231b4820df8SJoep Vesseur 		 * ATTR_COLth column, skip to ATTR_COL on a new line to
232b4820df8SJoep Vesseur 		 * print the attribues.
233b4820df8SJoep Vesseur 		 * else, just skip to ATTR_COL column.
234b4820df8SJoep Vesseur 		 */
235b4820df8SJoep Vesseur 		if (len >= ATTR_COL)
236b4820df8SJoep Vesseur 			(void) printf("\n%*s", ATTR_COL, " ");
237b4820df8SJoep Vesseur 		else
238b4820df8SJoep Vesseur 			(void) printf("%*s", ATTR_COL-len, " ");
239b4820df8SJoep Vesseur 		len = ATTR_COL;
240b4820df8SJoep Vesseur 
241b4820df8SJoep Vesseur 		/* print all attributes of this profile */
242b4820df8SJoep Vesseur 		kv_pair = exec->attr->data;
2437c478bd9Sstevel@tonic-gate 		for (i = 0; i < exec->attr->length; i++) {
2447c478bd9Sstevel@tonic-gate 			key = kv_pair[i].key;
2457c478bd9Sstevel@tonic-gate 			val = kv_pair[i].value;
246b4820df8SJoep Vesseur 			if (key == NULL || val == NULL)
2477c478bd9Sstevel@tonic-gate 				break;
248b4820df8SJoep Vesseur 			/* align subsequent attributes on the same column */
249b4820df8SJoep Vesseur 			if (i > 0)
250b4820df8SJoep Vesseur 				(void) printf("%*s", len, " ");
251b4820df8SJoep Vesseur 			(void) printf("%s=%s\n", key, val);
2527c478bd9Sstevel@tonic-gate 		}
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate static void
usage()2577c478bd9Sstevel@tonic-gate usage()
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
2607c478bd9Sstevel@tonic-gate 	    gettext("  usage: profiles [-l] [user1 user2 ...]\n"));
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate static void
print_profile_privs(kva_t * attr)264*134a1f4eSCasper H.S. Dik print_profile_privs(kva_t *attr)
265b4820df8SJoep Vesseur {
266b4820df8SJoep Vesseur 	char *privs;
267b4820df8SJoep Vesseur 
268*134a1f4eSCasper H.S. Dik 	if (attr) {
269*134a1f4eSCasper H.S. Dik 		privs = kva_match(attr, PROFATTR_PRIVS_KW);
270b4820df8SJoep Vesseur 		if (privs)
271b4820df8SJoep Vesseur 			(void) printf(" privs=%s", privs);
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate }
274