xref: /illumos-gate/usr/src/cmd/profiles/profiles.c (revision 753a6d45)
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);
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, GET_ALL);
179 		if (exec == NULL) {
180 			status = EXIT_NON_FATAL;
181 		}
182 	} else {
183 		proflist = kva_match(user->attr, USERATTR_PROFILES_KW);
184 		if (proflist != NULL) {
185 			getProfiles(proflist, profArray, &profcnt);
186 		}
187 		/* Also get any default profiles */
188 		getDefaultProfiles(user->name, profArray, &profcnt);
189 		if (profcnt == 0) {
190 			status = EXIT_NON_FATAL;
191 		}
192 	}
193 	if (status == EXIT_OK) {
194 		if (print_flag & PRINT_LONG) {
195 			print_profs_long(exec);
196 			free_execattr(exec);
197 		} else {
198 			print_profs(profArray, print_flag, profcnt);
199 		}
200 	}
201 	free_userattr(user);
202 
203 	return (status);
204 }
205 
206 
207 /*
208  * print extended profile information.
209  *
210  * output is "pretty printed" like
211  *   [6spaces]Profile Name1[ possible profile privileges]
212  *   [10spaces  ]execname1 [skip to ATTR_COL]exec1 attributes1
213  *   [      spaces to ATTR_COL              ]exec1 attributes2
214  *   [10spaces  ]execname2 [skip to ATTR_COL]exec2 attributes1
215  *   [      spaces to ATTR_COL              ]exec2 attributes2
216  *   [6spaces]Profile Name2[ possible profile privileges]
217  *   etc
218  */
219 /*
220  * ATTR_COL is based on
221  *   10 leading spaces +
222  *   25 positions for the executable +
223  *    1 space seperating the execname from the attributes
224  * so attribute printing starts at column 37 (36 whitespaces)
225  *
226  *  25 spaces for the execname seems reasonable since currently
227  *  less than 3% of the shipped exec_attr would overflow this
228  */
229 #define	ATTR_COL	37
230 
231 static void
232 print_profs_long(execattr_t *exec)
233 {
234 	char	*curprofile;
235 	int	len;
236 	kv_t	*kv_pair;
237 	char	*key;
238 	char	*val;
239 	int	i;
240 
241 	for (curprofile = ""; exec != NULL; exec = exec->next) {
242 		/* print profile name if it is a new one */
243 		if (strcmp(curprofile, exec->name) != 0) {
244 			curprofile = exec->name;
245 			(void) printf("      %s", curprofile);
246 			print_profile_privs(curprofile);
247 			(void) printf("\n");
248 		}
249 		len = printf("          %s ", exec->id);
250 
251 		if ((exec->attr == NULL || exec->attr->data == NULL)) {
252 			(void) printf("\n");
253 			continue;
254 		}
255 
256 		/*
257 		 * if printing the name of the executable got us past the
258 		 * ATTR_COLth column, skip to ATTR_COL on a new line to
259 		 * print the attribues.
260 		 * else, just skip to ATTR_COL column.
261 		 */
262 		if (len >= ATTR_COL)
263 			(void) printf("\n%*s", ATTR_COL, " ");
264 		else
265 			(void) printf("%*s", ATTR_COL-len, " ");
266 		len = ATTR_COL;
267 
268 		/* print all attributes of this profile */
269 		kv_pair = exec->attr->data;
270 		for (i = 0; i < exec->attr->length; i++) {
271 			key = kv_pair[i].key;
272 			val = kv_pair[i].value;
273 			if (key == NULL || val == NULL)
274 				break;
275 			/* align subsequent attributes on the same column */
276 			if (i > 0)
277 				(void) printf("%*s", len, " ");
278 			(void) printf("%s=%s\n", key, val);
279 		}
280 	}
281 }
282 
283 static void
284 usage()
285 {
286 	(void) fprintf(stderr,
287 	    gettext("  usage: profiles [-l] [user1 user2 ...]\n"));
288 }
289 
290 static void
291 getProfiles(char *profiles, char **profArray, int *profcnt) {
292 
293 	char		*prof;
294 	char		*lasts;
295 
296 	for (prof = (char *)strtok_r(profiles, PROFLIST_SEP, &lasts);
297 	    prof != NULL;
298 	    prof = (char *)strtok_r(NULL, PROFLIST_SEP, &lasts)) {
299 
300 		getproflist(prof, profArray, profcnt);
301 
302 	}
303 }
304 
305 static void
306 print_profile_privs(const char *profile)
307 {
308 	profattr_t *prof_entry = getprofnam(profile);
309 	char *privs;
310 
311 	if (prof_entry) {
312 		privs = kva_match(prof_entry->attr, PROFATTR_PRIVS_KW);
313 		if (privs)
314 			(void) printf(" privs=%s", privs);
315 		free_profattr(prof_entry);
316 	}
317 }
318 
319 static void
320 print_profs(char **profnames, int print_flag, int profcnt)
321 {
322 
323 	int i;
324 	char *indent = "";
325 
326 	if (print_flag & PRINT_NAME) {
327 		indent = "          ";
328 	}
329 
330 	for (i = 0; i < profcnt; i++) {
331 		(void) printf("%s%s", indent, profnames[i]);
332 		print_profile_privs(profnames[i]);
333 		(void) printf("\n");
334 	}
335 
336 	free_proflist(profnames, profcnt);
337 }
338 
339 /*
340  * Get the list of default profiles from /etc/security/policy.conf
341  */
342 static void
343 getDefaultProfiles(char *user, char **profArray, int *profcnt)
344 {
345 	char *profs = NULL;
346 
347 	if (_get_user_defs(user, NULL, &profs) == 0) {
348 		if (profs != NULL) {
349 			getProfiles(profs, profArray, profcnt);
350 			_free_user_defs(NULL, profs);
351 		}
352 	}
353 }
354