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