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