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