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