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