xref: /illumos-gate/usr/src/cmd/profiles/profiles.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <pwd.h>
30 #include <string.h>
31 #include <libintl.h>
32 #include <locale.h>
33 #include <deflt.h>
34 #include <user_attr.h>
35 #include <prof_attr.h>
36 #include <exec_attr.h>
37 #include <auth_attr.h>
38 
39 
40 #define	EXIT_OK		0
41 #define	EXIT_FATAL	1
42 #define	EXIT_NON_FATAL	2
43 
44 #define	TMP_BUF_LEN	2048		/* size of temp string buffer */
45 
46 #define	PRINT_DEFAULT	0x0000
47 #define	PRINT_NAME	0x0010
48 #define	PRINT_LONG	0x0020
49 
50 #ifndef TEXT_DOMAIN			/* Should be defined by cc -D */
51 #define	TEXT_DOMAIN	"SYS_TEST"
52 #endif
53 
54 #define	PROFLIST_SEP	","
55 
56 
57 static void usage();
58 static int show_profs(char *, int);
59 static int list_profs(userattr_t *, int);
60 static void print_profs_long(execattr_t *);
61 static void print_profs(char **, int, int);
62 static void getProfiles(char *, char **, int *);
63 static void getDefaultProfiles(char *, char **, int *);
64 static void print_profile_privs(const char *);
65 
66 static char *progname = "profiles";
67 
68 int
69 main(int argc, char *argv[])
70 {
71 	extern int	optind;
72 	int		c;
73 	int		status = EXIT_OK;
74 	int		print_flag = PRINT_DEFAULT;
75 
76 	(void) setlocale(LC_ALL, "");
77 	(void) textdomain(TEXT_DOMAIN);
78 
79 	while ((c = getopt(argc, argv, "l")) != EOF) {
80 		switch (c) {
81 		case 'l':
82 			print_flag |= PRINT_LONG;
83 			break;
84 		default:
85 			usage();
86 			return (EXIT_FATAL);
87 		}
88 	}
89 	argc -= optind;
90 	argv += optind;
91 
92 	if (*argv == NULL) {
93 		status = show_profs(NULL, print_flag);
94 	} else {
95 		do {
96 			(void) printf("%s:\n", *argv);
97 			status = show_profs((char *)*argv,
98 			    (print_flag | PRINT_NAME));
99 			if (status == EXIT_FATAL) {
100 				break;
101 			}
102 			if (argv[1] != NULL) {
103 				/* seperate users with empty line */
104 				(void) printf("\n");
105 			}
106 		} while (*++argv);
107 	}
108 	status = (status == EXIT_OK) ? status : EXIT_FATAL;
109 
110 	return (status);
111 }
112 
113 
114 static int
115 show_profs(char *username, int print_flag)
116 {
117 	int		status = EXIT_OK;
118 	struct passwd	*pw;
119 	userattr_t	*user;
120 	char		*profArray[MAXPROFS];
121 	int		profcnt = 0;
122 	execattr_t	*exec;
123 
124 	if (username == NULL) {
125 		if ((pw = getpwuid(getuid())) == NULL) {
126 			status = EXIT_NON_FATAL;
127 			(void) fprintf(stderr, "%s: ", progname);
128 			(void) fprintf(stderr, gettext("No passwd entry\n"));
129 			return (status);
130 		}
131 		username = pw->pw_name;
132 	} else if (getpwnam(username) == NULL) {
133 		status = EXIT_NON_FATAL;
134 		(void) fprintf(stderr, "%s: %s: ", progname, username);
135 		(void) fprintf(stderr, gettext("No such user\n"));
136 		return (status);
137 	}
138 	if (username != NULL) {
139 		if ((user = getusernam(username)) != NULL) {
140 			status = list_profs(user, print_flag);
141 		} else {
142 			getDefaultProfiles(username, profArray, &profcnt);
143 			if (profcnt == 0) {
144 				status = EXIT_NON_FATAL;
145 			} else {
146 				if (print_flag & PRINT_LONG) {
147 					exec = getexecuser(username, KV_COMMAND,
148 					    NULL, GET_ALL|__SEARCH_ALL_POLS);
149 					print_profs_long(exec);
150 					free_execattr(exec);
151 				} else {
152 					print_profs(profArray, print_flag,
153 					    profcnt);
154 				}
155 			}
156 		}
157 	}
158 
159 	if (status == EXIT_NON_FATAL) {
160 		(void) fprintf(stderr, "%s: %s: ", progname, username);
161 		(void) fprintf(stderr, gettext("No profiles\n"));
162 	}
163 
164 	return (status);
165 }
166 
167 
168 static int
169 list_profs(userattr_t *user, int print_flag)
170 {
171 	int		status = EXIT_OK;
172 	char		*proflist = (char *)NULL;
173 	execattr_t	*exec = (execattr_t *)NULL;
174 	char		*profArray[MAXPROFS];
175 	int		profcnt = 0;
176 
177 	if (print_flag & PRINT_LONG) {
178 		exec = getexecuser(user->name, KV_COMMAND, NULL,
179 		    GET_ALL|__SEARCH_ALL_POLS);
180 		if (exec == NULL) {
181 			status = EXIT_NON_FATAL;
182 		}
183 	} else {
184 		proflist = kva_match(user->attr, USERATTR_PROFILES_KW);
185 		if (proflist != NULL) {
186 			getProfiles(proflist, profArray, &profcnt);
187 		}
188 		/* Also get any default profiles */
189 		getDefaultProfiles(user->name, profArray, &profcnt);
190 		if (profcnt == 0) {
191 			status = EXIT_NON_FATAL;
192 		}
193 	}
194 	if (status == EXIT_OK) {
195 		if (print_flag & PRINT_LONG) {
196 			print_profs_long(exec);
197 			free_execattr(exec);
198 		} else {
199 			print_profs(profArray, print_flag, profcnt);
200 		}
201 	}
202 	free_userattr(user);
203 
204 	return (status);
205 }
206 
207 
208 /*
209  * print extended profile information.
210  *
211  * output is "pretty printed" like
212  *   [6spaces]Profile Name1[ possible profile privileges]
213  *   [10spaces  ]execname1 [skip to ATTR_COL]exec1 attributes1
214  *   [      spaces to ATTR_COL              ]exec1 attributes2
215  *   [10spaces  ]execname2 [skip to ATTR_COL]exec2 attributes1
216  *   [      spaces to ATTR_COL              ]exec2 attributes2
217  *   [6spaces]Profile Name2[ possible profile privileges]
218  *   etc
219  */
220 /*
221  * ATTR_COL is based on
222  *   10 leading spaces +
223  *   25 positions for the executable +
224  *    1 space seperating the execname from the attributes
225  * so attribute printing starts at column 37 (36 whitespaces)
226  *
227  *  25 spaces for the execname seems reasonable since currently
228  *  less than 3% of the shipped exec_attr would overflow this
229  */
230 #define	ATTR_COL	37
231 
232 static void
233 print_profs_long(execattr_t *exec)
234 {
235 	char	*curprofile;
236 	int	len;
237 	kv_t	*kv_pair;
238 	char	*key;
239 	char	*val;
240 	int	i;
241 
242 	for (curprofile = ""; exec != NULL; exec = exec->next) {
243 		/* print profile name if it is a new one */
244 		if (strcmp(curprofile, exec->name) != 0) {
245 			curprofile = exec->name;
246 			(void) printf("      %s", curprofile);
247 			print_profile_privs(curprofile);
248 			(void) printf("\n");
249 		}
250 		len = printf("          %s ", exec->id);
251 
252 		if ((exec->attr == NULL || exec->attr->data == NULL)) {
253 			(void) printf("\n");
254 			continue;
255 		}
256 
257 		/*
258 		 * if printing the name of the executable got us past the
259 		 * ATTR_COLth column, skip to ATTR_COL on a new line to
260 		 * print the attribues.
261 		 * else, just skip to ATTR_COL column.
262 		 */
263 		if (len >= ATTR_COL)
264 			(void) printf("\n%*s", ATTR_COL, " ");
265 		else
266 			(void) printf("%*s", ATTR_COL-len, " ");
267 		len = ATTR_COL;
268 
269 		/* print all attributes of this profile */
270 		kv_pair = exec->attr->data;
271 		for (i = 0; i < exec->attr->length; i++) {
272 			key = kv_pair[i].key;
273 			val = kv_pair[i].value;
274 			if (key == NULL || val == NULL)
275 				break;
276 			/* align subsequent attributes on the same column */
277 			if (i > 0)
278 				(void) printf("%*s", len, " ");
279 			(void) printf("%s=%s\n", key, val);
280 		}
281 	}
282 }
283 
284 static void
285 usage()
286 {
287 	(void) fprintf(stderr,
288 	    gettext("  usage: profiles [-l] [user1 user2 ...]\n"));
289 }
290 
291 static void
292 getProfiles(char *profiles, char **profArray, int *profcnt) {
293 
294 	char		*prof;
295 	char		*lasts;
296 
297 	for (prof = (char *)strtok_r(profiles, PROFLIST_SEP, &lasts);
298 	    prof != NULL;
299 	    prof = (char *)strtok_r(NULL, PROFLIST_SEP, &lasts)) {
300 
301 		getproflist(prof, profArray, profcnt);
302 
303 	}
304 }
305 
306 static void
307 print_profile_privs(const char *profile)
308 {
309 	profattr_t *prof_entry = getprofnam(profile);
310 	char *privs;
311 
312 	if (prof_entry) {
313 		privs = kva_match(prof_entry->attr, PROFATTR_PRIVS_KW);
314 		if (privs)
315 			(void) printf(" privs=%s", privs);
316 		free_profattr(prof_entry);
317 	}
318 }
319 
320 static void
321 print_profs(char **profnames, int print_flag, int profcnt)
322 {
323 
324 	int i;
325 	char *indent = "";
326 
327 	if (print_flag & PRINT_NAME) {
328 		indent = "          ";
329 	}
330 
331 	for (i = 0; i < profcnt; i++) {
332 		(void) printf("%s%s", indent, profnames[i]);
333 		print_profile_privs(profnames[i]);
334 		(void) printf("\n");
335 	}
336 
337 	free_proflist(profnames, profcnt);
338 }
339 
340 /*
341  * Get the list of default profiles from /etc/security/policy.conf
342  */
343 static void
344 getDefaultProfiles(char *user, char **profArray, int *profcnt)
345 {
346 	char *profs = NULL;
347 
348 	if (_get_user_defs(user, NULL, &profs) == 0) {
349 		if (profs != NULL) {
350 			getProfiles(profs, profArray, profcnt);
351 			_free_user_defs(NULL, profs);
352 		}
353 	}
354 }
355