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 (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <strings.h> 28 #include <auth_attr.h> 29 #include <prof_attr.h> 30 #include <user_attr.h> 31 #include <project.h> 32 #include <secdb.h> 33 #include <pwd.h> 34 #include <unistd.h> 35 #include <priv.h> 36 #include <errno.h> 37 #include <ctype.h> 38 #include <nss.h> 39 #include <bsm/libbsm.h> 40 #include <tsol/label.h> 41 #include "funcs.h" 42 #include "messages.h" 43 #undef GROUP 44 #include "userdefs.h" 45 46 typedef struct ua_key { 47 const char *key; 48 const char *(*check)(const char *); 49 const char *errstr; 50 char *newvalue; 51 } ua_key_t; 52 53 static const char role[] = "role name"; 54 static const char prof[] = "profile name"; 55 static const char proj[] = "project name"; 56 static const char priv[] = "privilege set"; 57 static const char auth[] = "authorization"; 58 static const char type[] = "user type"; 59 static const char lock[] = "lock_after_retries value"; 60 static const char label[] = "label"; 61 static const char idlecmd[] = "idlecmd value"; 62 static const char idletime[] = "idletime value"; 63 static const char auditflags[] = "audit mask"; 64 static char auditerr[256]; 65 66 67 static const char *check_auth(const char *); 68 static const char *check_prof(const char *); 69 static const char *check_role(const char *); 70 static const char *check_proj(const char *); 71 static const char *check_privset(const char *); 72 static const char *check_type(const char *); 73 static const char *check_lock_after_retries(const char *); 74 static const char *check_label(const char *); 75 static const char *check_idlecmd(const char *); 76 static const char *check_idletime(const char *); 77 static const char *check_auditflags(const char *); 78 79 int nkeys; 80 81 static ua_key_t keys[] = { 82 /* First entry is always set correctly in main() */ 83 { USERATTR_TYPE_KW, check_type, type }, 84 { USERATTR_AUTHS_KW, check_auth, auth }, 85 { USERATTR_PROFILES_KW, check_prof, prof }, 86 { USERATTR_ROLES_KW, check_role, role }, 87 { USERATTR_DEFAULTPROJ_KW, check_proj, proj }, 88 { USERATTR_LIMPRIV_KW, check_privset, priv }, 89 { USERATTR_DFLTPRIV_KW, check_privset, priv }, 90 { USERATTR_LOCK_AFTER_RETRIES_KW, check_lock_after_retries, lock }, 91 { USERATTR_CLEARANCE, check_label, label }, 92 { USERATTR_MINLABEL, check_label, label }, 93 { USERATTR_IDLECMD_KW, check_idlecmd, idlecmd }, 94 { USERATTR_IDLETIME_KW, check_idletime, idletime }, 95 { USERATTR_AUDIT_FLAGS_KW, check_auditflags, auditflags }, 96 }; 97 98 #define NKEYS (sizeof (keys)/sizeof (ua_key_t)) 99 100 /* 101 * Change a key, there are three different call sequences: 102 * 103 * key, value - key with option letter, value. 104 * NULL, value - -K key=value option. 105 */ 106 107 void 108 change_key(const char *key, char *value) 109 { 110 int i; 111 const char *res; 112 113 if (key == NULL) { 114 key = value; 115 value = strchr(value, '='); 116 /* Bad value */ 117 if (value == NULL) { 118 errmsg(M_INVALID_VALUE); 119 exit(EX_BADARG); 120 } 121 *value++ = '\0'; 122 } 123 124 for (i = 0; i < NKEYS; i++) { 125 if (strcmp(key, keys[i].key) == 0) { 126 if (keys[i].newvalue != NULL) { 127 /* Can't set a value twice */ 128 errmsg(M_REDEFINED_KEY, key); 129 exit(EX_BADARG); 130 } 131 132 if (keys[i].check != NULL && 133 (res = keys[i].check(value)) != NULL) { 134 errmsg(M_INVALID, res, keys[i].errstr); 135 exit(EX_BADARG); 136 } 137 keys[i].newvalue = value; 138 nkeys++; 139 return; 140 } 141 } 142 errmsg(M_INVALID_KEY, key); 143 exit(EX_BADARG); 144 } 145 146 /* 147 * Add the keys to the argument vector. 148 */ 149 void 150 addkey_args(char **argv, int *index) 151 { 152 int i; 153 154 for (i = 0; i < NKEYS; i++) { 155 const char *key = keys[i].key; 156 char *val = keys[i].newvalue; 157 size_t len; 158 char *arg; 159 160 if (val == NULL) 161 continue; 162 163 len = strlen(key) + strlen(val) + 2; 164 arg = malloc(len); 165 166 (void) snprintf(arg, len, "%s=%s", key, val); 167 argv[(*index)++] = "-K"; 168 argv[(*index)++] = arg; 169 } 170 } 171 172 /* 173 * Propose a default value for a key and get the actual value back. 174 * If the proposed default value is NULL, return the actual value set. 175 * The key argument is the user_attr key. 176 */ 177 char * 178 getsetdefval(const char *key, char *dflt) 179 { 180 int i; 181 182 for (i = 0; i < NKEYS; i++) 183 if (strcmp(keys[i].key, key) == 0) 184 if (keys[i].newvalue != NULL) 185 return (keys[i].newvalue); 186 else 187 return (keys[i].newvalue = dflt); 188 return (NULL); 189 } 190 191 char * 192 getusertype(char *cmdname) 193 { 194 static char usertype[MAX_TYPE_LENGTH]; 195 char *cmd; 196 197 if (cmd = strrchr(cmdname, '/')) 198 ++cmd; 199 else 200 cmd = cmdname; 201 202 /* get user type based on the program name */ 203 if (strncmp(cmd, CMD_PREFIX_USER, 204 strlen(CMD_PREFIX_USER)) == 0) 205 strcpy(usertype, USERATTR_TYPE_NORMAL_KW); 206 else 207 strcpy(usertype, USERATTR_TYPE_NONADMIN_KW); 208 209 return (usertype); 210 } 211 212 int 213 is_role(char *usertype) 214 { 215 if (strcmp(usertype, USERATTR_TYPE_NONADMIN_KW) == 0) 216 return (1); 217 /* not a role */ 218 return (0); 219 } 220 221 /* 222 * Verifies the provided list of authorizations are all valid. 223 * 224 * Returns NULL if all authorization names are valid. 225 * Otherwise, returns the invalid authorization name 226 * 227 */ 228 static const char * 229 check_auth(const char *auths) 230 { 231 char *authname; 232 authattr_t *result; 233 char *tmp; 234 struct passwd *pw; 235 int have_grant = 0; 236 237 tmp = strdup(auths); 238 if (tmp == NULL) { 239 errmsg(M_NOSPACE); 240 exit(EX_FAILURE); 241 } 242 243 authname = strtok(tmp, AUTH_SEP); 244 pw = getpwuid(getuid()); 245 if (pw == NULL) { 246 return (authname); 247 } 248 249 while (authname != NULL) { 250 char *suffix; 251 char *authtoks; 252 253 /* Check if user has been granted this authorization */ 254 if (!chkauthattr(authname, pw->pw_name)) 255 return (authname); 256 257 /* Remove named object after slash */ 258 if ((suffix = index(authname, KV_OBJECTCHAR)) != NULL) 259 *suffix = '\0'; 260 261 /* Find the suffix */ 262 if ((suffix = rindex(authname, '.')) == NULL) 263 return (authname); 264 265 /* Check for existence in auth_attr */ 266 suffix++; 267 if (strcmp(suffix, KV_WILDCARD)) { /* Not a wildcard */ 268 result = getauthnam(authname); 269 if (result == NULL) { 270 /* can't find the auth */ 271 free_authattr(result); 272 return (authname); 273 } 274 free_authattr(result); 275 } 276 277 /* Check if user can delegate this authorization */ 278 if (strcmp(suffix, "grant")) { /* Not a grant option */ 279 authtoks = malloc(strlen(authname) + sizeof ("grant")); 280 strcpy(authtoks, authname); 281 have_grant = 0; 282 while ((suffix = rindex(authtoks, '.')) && 283 !have_grant) { 284 strcpy(suffix, ".grant"); 285 if (chkauthattr(authtoks, pw->pw_name)) 286 have_grant = 1; 287 else 288 *suffix = '\0'; 289 } 290 if (!have_grant) 291 return (authname); 292 } 293 authname = strtok(NULL, AUTH_SEP); 294 } 295 free(tmp); 296 return (NULL); 297 } 298 299 /* 300 * Verifies the provided list of profile names are valid. 301 * 302 * Returns NULL if all profile names are valid. 303 * Otherwise, returns the invalid profile name 304 * 305 */ 306 static const char * 307 check_prof(const char *profs) 308 { 309 char *profname; 310 profattr_t *result; 311 char *tmp; 312 313 tmp = strdup(profs); 314 if (tmp == NULL) { 315 errmsg(M_NOSPACE); 316 exit(EX_FAILURE); 317 } 318 319 profname = strtok(tmp, PROF_SEP); 320 while (profname != NULL) { 321 result = getprofnam(profname); 322 if (result == NULL) { 323 /* can't find the profile */ 324 return (profname); 325 } 326 free_profattr(result); 327 profname = strtok(NULL, PROF_SEP); 328 } 329 free(tmp); 330 return (NULL); 331 } 332 333 334 /* 335 * Verifies the provided list of role names are valid. 336 * 337 * Returns NULL if all role names are valid. 338 * Otherwise, returns the invalid role name 339 * 340 */ 341 static const char * 342 check_role(const char *roles) 343 { 344 char *rolename; 345 userattr_t *result; 346 char *utype; 347 char *tmp; 348 349 tmp = strdup(roles); 350 if (tmp == NULL) { 351 errmsg(M_NOSPACE); 352 exit(EX_FAILURE); 353 } 354 355 rolename = strtok(tmp, ROLE_SEP); 356 while (rolename != NULL) { 357 result = getusernam(rolename); 358 if (result == NULL) { 359 /* can't find the rolename */ 360 return (rolename); 361 } 362 /* Now, make sure it is a role */ 363 utype = kva_match(result->attr, USERATTR_TYPE_KW); 364 if (utype == NULL) { 365 /* no user type defined. not a role */ 366 free_userattr(result); 367 return (rolename); 368 } 369 if (strcmp(utype, USERATTR_TYPE_NONADMIN_KW) != 0) { 370 free_userattr(result); 371 return (rolename); 372 } 373 free_userattr(result); 374 rolename = strtok(NULL, ROLE_SEP); 375 } 376 free(tmp); 377 return (NULL); 378 } 379 380 static const char * 381 check_proj(const char *proj) 382 { 383 if (getprojidbyname(proj) < 0) { 384 return (proj); 385 } else { 386 return (NULL); 387 } 388 } 389 390 static const char * 391 check_privset(const char *pset) 392 { 393 priv_set_t *tmp; 394 const char *res; 395 396 tmp = priv_str_to_set(pset, ",", &res); 397 398 if (tmp != NULL) { 399 res = NULL; 400 priv_freeset(tmp); 401 } else if (res == NULL) 402 res = strerror(errno); 403 404 return (res); 405 } 406 407 static const char * 408 check_type(const char *type) 409 { 410 if (strcmp(type, USERATTR_TYPE_NONADMIN_KW) != 0 && 411 strcmp(type, USERATTR_TYPE_NORMAL_KW) != 0) 412 return (type); 413 414 return (NULL); 415 } 416 417 static const char * 418 check_lock_after_retries(const char *keyval) 419 { 420 if (keyval != NULL) { 421 if ((strcasecmp(keyval, "no") != 0) && 422 (strcasecmp(keyval, "yes") != 0) && 423 (*keyval != '\0')) { 424 return (keyval); 425 } 426 } 427 return (NULL); 428 } 429 430 static const char * 431 check_label(const char *labelstr) 432 { 433 int err; 434 m_label_t *lbl = NULL; 435 436 if (!is_system_labeled()) 437 return (NULL); 438 439 err = str_to_label(labelstr, &lbl, MAC_LABEL, L_NO_CORRECTION, NULL); 440 m_label_free(lbl); 441 442 if (err == -1) 443 return (labelstr); 444 445 return (NULL); 446 } 447 448 static const char * 449 check_idlecmd(const char *cmd) 450 { 451 if ((strcmp(cmd, USERATTR_IDLECMD_LOCK_KW) != 0) && 452 (strcmp(cmd, USERATTR_IDLECMD_LOGOUT_KW) != 0)) { 453 return (cmd); 454 } 455 456 return (NULL); 457 } 458 459 static const char * 460 check_idletime(const char *time) 461 { 462 int c; 463 unsigned char *up = (unsigned char *)time; 464 465 c = *up; 466 while (c != '\0') { 467 if (!isdigit(c)) 468 return (time); 469 c = *++up; 470 } 471 472 return (NULL); 473 } 474 475 static const char * 476 check_auditflags(const char *auditflags) 477 { 478 au_mask_t mask; 479 char *flags; 480 char *last = NULL; 481 char *err = "NULL"; 482 483 /* if deleting audit_flags */ 484 if (*auditflags == '\0') { 485 return (NULL); 486 } 487 488 if ((flags = _strdup_null((char *)auditflags)) == NULL) { 489 errmsg(M_NOSPACE); 490 exit(EX_FAILURE); 491 } 492 493 if (!__chkflags(_strtok_escape(flags, KV_AUDIT_DELIMIT, &last), &mask, 494 B_FALSE, &err)) { 495 (void) snprintf(auditerr, sizeof (auditerr), 496 "always mask \"%s\"", err); 497 free(flags); 498 return (auditerr); 499 } 500 if (!__chkflags(_strtok_escape(NULL, KV_AUDIT_DELIMIT, &last), &mask, 501 B_FALSE, &err)) { 502 (void) snprintf(auditerr, sizeof (auditerr), 503 "never mask \"%s\"", err); 504 free(flags); 505 return (auditerr); 506 } 507 if (last != NULL) { 508 (void) snprintf(auditerr, sizeof (auditerr), "\"%s\"", 509 auditflags); 510 free(flags); 511 return (auditerr); 512 } 513 free(flags); 514 515 return (NULL); 516 }