xref: /illumos-gate/usr/src/cmd/profiles/profiles.c (revision 2bbdd445a21f9d61f4a0ca0faf05d5ceb2bd91f3)
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 
53 static void usage();
54 static int show_profs(char *, int);
55 static void print_profs_long(execattr_t *);
56 static void print_profile_privs(kva_t *);
57 
58 static char *progname = "profiles";
59 
60 int
61 main(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 
105 static int
106 show_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 
125 static int
126 show_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 
197 static void
198 print_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 
256 static void
257 usage()
258 {
259 	(void) fprintf(stderr,
260 	    gettext("  usage: profiles [-l] [user1 user2 ...]\n"));
261 }
262 
263 static void
264 print_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