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 <libintl.h>
31#include <locale.h>
32#include <deflt.h>
33#include <user_attr.h>
34#include <prof_attr.h>
35#include <exec_attr.h>
36#include <auth_attr.h>
37
38
39#define	EXIT_OK		0
40#define	EXIT_FATAL	1
41#define	EXIT_NON_FATAL	2
42
43#define	TMP_BUF_LEN	2048		/* size of temp string buffer */
44
45#define	PRINT_DEFAULT	0x0000
46#define	PRINT_NAME	0x0010
47#define	PRINT_LONG	0x0020
48
49#ifndef TEXT_DOMAIN			/* Should be defined by cc -D */
50#define	TEXT_DOMAIN	"SYS_TEST"
51#endif
52
53static void usage();
54static int show_profs(char *, int);
55static void print_profs_long(execattr_t *);
56static void print_profile_privs(kva_t *);
57
58static char *progname = "profiles";
59
60int
61main(int argc, char *argv[])
62{
63	extern int	optind;
64	int		c;
65	int		status = EXIT_OK;
66	int		print_flag = PRINT_DEFAULT;
67
68	(void) setlocale(LC_ALL, "");
69	(void) textdomain(TEXT_DOMAIN);
70
71	while ((c = getopt(argc, argv, "l")) != EOF) {
72		switch (c) {
73		case 'l':
74			print_flag |= PRINT_LONG;
75			break;
76		default:
77			usage();
78			return (EXIT_FATAL);
79		}
80	}
81	argc -= optind;
82	argv += optind;
83
84	if (*argv == NULL) {
85		status = show_profs(NULL, print_flag);
86	} else {
87		do {
88			(void) printf("%s:\n", *argv);
89			status = show_profs((char *)*argv,
90			    (print_flag | PRINT_NAME));
91			if (status == EXIT_FATAL) {
92				break;
93			}
94			if (argv[1] != NULL) {
95				/* seperate users with empty line */
96				(void) printf("\n");
97			}
98		} while (*++argv);
99	}
100	status = (status == EXIT_OK) ? status : EXIT_FATAL;
101
102	return (status);
103}
104
105static int
106show_profs_callback(const char *prof, kva_t *pa, void *pflag, void *vcnt)
107{
108	char *indent = "";
109	const int *print_flag = pflag;
110	int *pcnt = vcnt;
111
112	(*pcnt)++;
113
114	if ((*print_flag) & PRINT_NAME) {
115		indent = "          ";
116	}
117
118	(void) printf("%s%s", indent, prof);
119	print_profile_privs(pa);
120	(void) printf("\n");
121
122	return (0);
123}
124
125static int
126show_profs(char *username, int print_flag)
127{
128	int		status = EXIT_OK;
129	struct passwd	*pw;
130	execattr_t	*exec;
131
132	if (username == NULL) {
133		if ((pw = getpwuid(getuid())) == NULL) {
134			status = EXIT_NON_FATAL;
135			(void) fprintf(stderr, "%s: ", progname);
136			(void) fprintf(stderr, gettext("No passwd entry\n"));
137			return (status);
138		}
139		username = pw->pw_name;
140	} else if (getpwnam(username) == NULL) {
141		status = EXIT_NON_FATAL;
142		(void) fprintf(stderr, "%s: %s: ", progname, username);
143		(void) fprintf(stderr, gettext("No such user\n"));
144		return (status);
145	}
146
147	if (print_flag & PRINT_LONG) {
148		exec = getexecuser(username, KV_COMMAND, NULL,
149		    GET_ALL|__SEARCH_ALL_POLS);
150		if (exec != NULL) {
151			print_profs_long(exec);
152			free_execattr(exec);
153		} else {
154			status = EXIT_NON_FATAL;
155		}
156	} else {
157		int cnt = 0;
158		(void) _enum_profs(username, show_profs_callback, &print_flag,
159		    &cnt);
160
161		if (cnt == 0)
162			status = EXIT_NON_FATAL;
163	}
164
165	if (status == EXIT_NON_FATAL) {
166		(void) fprintf(stderr, "%s: %s: ", progname, username);
167		(void) fprintf(stderr, gettext("No profiles\n"));
168	}
169
170	return (status);
171}
172
173/*
174 * print extended profile information.
175 *
176 * output is "pretty printed" like
177 *   [6spaces]Profile Name1[ possible profile privileges]
178 *   [10spaces  ]execname1 [skip to ATTR_COL]exec1 attributes1
179 *   [      spaces to ATTR_COL              ]exec1 attributes2
180 *   [10spaces  ]execname2 [skip to ATTR_COL]exec2 attributes1
181 *   [      spaces to ATTR_COL              ]exec2 attributes2
182 *   [6spaces]Profile Name2[ possible profile privileges]
183 *   etc
184 */
185/*
186 * ATTR_COL is based on
187 *   10 leading spaces +
188 *   25 positions for the executable +
189 *    1 space seperating the execname from the attributes
190 * so attribute printing starts at column 37 (36 whitespaces)
191 *
192 *  25 spaces for the execname seems reasonable since currently
193 *  less than 3% of the shipped exec_attr would overflow this
194 */
195#define	ATTR_COL	37
196
197static void
198print_profs_long(execattr_t *exec)
199{
200	char	*curprofile;
201	int	len;
202	kv_t	*kv_pair;
203	char	*key;
204	char	*val;
205	int	i;
206
207	for (curprofile = ""; exec != NULL; exec = exec->next) {
208		/* print profile name if it is a new one */
209		if (strcmp(curprofile, exec->name) != 0) {
210			profattr_t *pa;
211			curprofile = exec->name;
212
213			(void) printf("      %s", curprofile);
214
215			pa = getprofnam(curprofile);
216			if (pa != NULL) {
217				print_profile_privs(pa->attr);
218				free_profattr(pa);
219			}
220			(void) printf("\n");
221		}
222		len = printf("          %s ", exec->id);
223
224		if ((exec->attr == NULL || exec->attr->data == NULL)) {
225			(void) printf("\n");
226			continue;
227		}
228
229		/*
230		 * if printing the name of the executable got us past the
231		 * ATTR_COLth column, skip to ATTR_COL on a new line to
232		 * print the attribues.
233		 * else, just skip to ATTR_COL column.
234		 */
235		if (len >= ATTR_COL)
236			(void) printf("\n%*s", ATTR_COL, " ");
237		else
238			(void) printf("%*s", ATTR_COL-len, " ");
239		len = ATTR_COL;
240
241		/* print all attributes of this profile */
242		kv_pair = exec->attr->data;
243		for (i = 0; i < exec->attr->length; i++) {
244			key = kv_pair[i].key;
245			val = kv_pair[i].value;
246			if (key == NULL || val == NULL)
247				break;
248			/* align subsequent attributes on the same column */
249			if (i > 0)
250				(void) printf("%*s", len, " ");
251			(void) printf("%s=%s\n", key, val);
252		}
253	}
254}
255
256static void
257usage()
258{
259	(void) fprintf(stderr,
260	    gettext("  usage: profiles [-l] [user1 user2 ...]\n"));
261}
262
263static void
264print_profile_privs(kva_t *attr)
265{
266	char *privs;
267
268	if (attr) {
269		privs = kva_match(attr, PROFATTR_PRIVS_KW);
270		if (privs)
271			(void) printf(" privs=%s", privs);
272	}
273}
274