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