Home | History | Annotate | Download | only in profiles
      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