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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <strings.h> 31 #include <auth_attr.h> 32 #include <prof_attr.h> 33 #include <user_attr.h> 34 #include <project.h> 35 #include <secdb.h> 36 #include <pwd.h> 37 #include <unistd.h> 38 #include <priv.h> 39 #include <errno.h> 40 #include <ctype.h> 41 #include <tsol/label.h> 42 #include "funcs.h" 43 #include "messages.h" 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 64 65 static const char *check_auth(const char *); 66 static const char *check_prof(const char *); 67 static const char *check_role(const char *); 68 static const char *check_proj(const char *); 69 static const char *check_privset(const char *); 70 static const char *check_type(const char *); 71 static const char *check_lock_after_retries(const char *); 72 static const char *check_label(const char *); 73 static const char *check_idlecmd(const char *); 74 static const char *check_idletime(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_IDLECMD_KW, check_idlecmd, idlecmd }, 91 { USERATTR_IDLETIME_KW, check_idletime, idletime }, 92 }; 93 94 #define NKEYS (sizeof (keys)/sizeof (ua_key_t)) 95 96 /* 97 * Change a key, there are three different call sequences: 98 * 99 * key, value - key with option letter, value. 100 * NULL, value - -K key=value option. 101 */ 102 103 void 104 change_key(const char *key, char *value) 105 { 106 int i; 107 const char *res; 108 109 if (key == NULL) { 110 key = value; 111 value = strchr(value, '='); 112 /* Bad value */ 113 if (value == NULL) { 114 errmsg(M_INVALID_VALUE); 115 exit(EX_BADARG); 116 } 117 *value++ = '\0'; 118 } 119 120 for (i = 0; i < NKEYS; i++) { 121 if (strcmp(key, keys[i].key) == 0) { 122 if (keys[i].newvalue != NULL) { 123 /* Can't set a value twice */ 124 errmsg(M_REDEFINED_KEY, key); 125 exit(EX_BADARG); 126 } 127 128 if (keys[i].check != NULL && 129 (res = keys[i].check(value)) != NULL) { 130 errmsg(M_INVALID, res, keys[i].errstr); 131 exit(EX_BADARG); 132 } 133 keys[i].newvalue = value; 134 nkeys++; 135 return; 136 } 137 } 138 errmsg(M_INVALID_KEY, key); 139 exit(EX_BADARG); 140 } 141 142 /* 143 * Add the keys to the argument vector. 144 */ 145 void 146 addkey_args(char **argv, int *index) 147 { 148 int i; 149 150 for (i = 0; i < NKEYS; i++) { 151 const char *key = keys[i].key; 152 char *val = keys[i].newvalue; 153 size_t len; 154 char *arg; 155 156 if (val == NULL) 157 continue; 158 159 len = strlen(key) + strlen(val) + 2; 160 arg = malloc(len); 161 162 (void) snprintf(arg, len, "%s=%s", key, val); 163 argv[(*index)++] = "-K"; 164 argv[(*index)++] = arg; 165 } 166 } 167 168 /* 169 * Propose a default value for a key and get the actual value back. 170 * If the proposed default value is NULL, return the actual value set. 171 * The key argument is the user_attr key. 172 */ 173 char * 174 getsetdefval(const char *key, char *dflt) 175 { 176 int i; 177 178 for (i = 0; i < NKEYS; i++) 179 if (strcmp(keys[i].key, key) == 0) 180 if (keys[i].newvalue != NULL) 181 return (keys[i].newvalue); 182 else 183 return (keys[i].newvalue = dflt); 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 235 authname = strtok(tmp, AUTH_SEP); 236 pw = getpwuid(getuid()); 237 if (pw == NULL) { 238 return (authname); 239 } 240 241 while (authname != NULL) { 242 char *suffix; 243 char *authtoks; 244 245 /* Find the suffix */ 246 if ((suffix = rindex(authname, '.')) == NULL) 247 return (authname); 248 249 /* Check for existence in auth_attr */ 250 suffix++; 251 if (strcmp(suffix, KV_WILDCARD)) { /* Not a wildcard */ 252 result = getauthnam(authname); 253 if (result == NULL) { 254 /* can't find the auth */ 255 free_authattr(result); 256 return (authname); 257 } 258 free_authattr(result); 259 } 260 261 /* Check if user has been granted this authorization */ 262 if (!chkauthattr(authname, pw->pw_name)) { 263 return (authname); 264 } 265 266 /* Check if user can delegate this authorization */ 267 if (strcmp(suffix, "grant")) { /* Not a grant option */ 268 authtoks = malloc(strlen(authname) + sizeof ("grant")); 269 strcpy(authtoks, authname); 270 have_grant = 0; 271 while ((suffix = rindex(authtoks, '.')) && 272 !have_grant) { 273 strcpy(suffix, ".grant"); 274 if (chkauthattr(authtoks, pw->pw_name)) 275 have_grant = 1; 276 else 277 *suffix = '\0'; 278 } 279 if (!have_grant) 280 return (authname); 281 } 282 authname = strtok(NULL, AUTH_SEP); 283 } 284 return (NULL); 285 } 286 287 /* 288 * Verifies the provided list of profile names are valid. 289 * 290 * Returns NULL if all profile names are valid. 291 * Otherwise, returns the invalid profile name 292 * 293 */ 294 static const char * 295 check_prof(const char *profs) 296 { 297 char *profname; 298 profattr_t *result; 299 char *tmp; 300 301 tmp = strdup(profs); 302 303 profname = strtok(tmp, PROF_SEP); 304 while (profname != NULL) { 305 result = getprofnam(profname); 306 if (result == NULL) { 307 /* can't find the profile */ 308 return (profname); 309 } 310 free_profattr(result); 311 profname = strtok(NULL, PROF_SEP); 312 } 313 return (NULL); 314 } 315 316 317 /* 318 * Verifies the provided list of role names are valid. 319 * 320 * Returns NULL if all role names are valid. 321 * Otherwise, returns the invalid role name 322 * 323 */ 324 static const char * 325 check_role(const char *roles) 326 { 327 char *rolename; 328 userattr_t *result; 329 char *utype; 330 char *tmp; 331 332 tmp = strdup(roles); 333 334 rolename = strtok(tmp, ROLE_SEP); 335 while (rolename != NULL) { 336 result = getusernam(rolename); 337 if (result == NULL) { 338 /* can't find the rolename */ 339 return (rolename); 340 } 341 /* Now, make sure it is a role */ 342 utype = kva_match(result->attr, USERATTR_TYPE_KW); 343 if (utype == NULL) { 344 /* no user type defined. not a role */ 345 free_userattr(result); 346 return (rolename); 347 } 348 if (strcmp(utype, USERATTR_TYPE_NONADMIN_KW) != 0) { 349 free_userattr(result); 350 return (rolename); 351 } 352 free_userattr(result); 353 rolename = strtok(NULL, ROLE_SEP); 354 } 355 return (NULL); 356 } 357 358 static const char * 359 check_proj(const char *proj) 360 { 361 if (getprojidbyname(proj) < 0) { 362 return (proj); 363 } else { 364 return (NULL); 365 } 366 } 367 368 static const char * 369 check_privset(const char *pset) 370 { 371 priv_set_t *tmp; 372 const char *res; 373 374 tmp = priv_str_to_set(pset, ",", &res); 375 376 if (tmp != NULL) { 377 res = NULL; 378 priv_freeset(tmp); 379 } else if (res == NULL) 380 res = strerror(errno); 381 382 return (res); 383 } 384 385 static const char * 386 check_type(const char *type) 387 { 388 if (strcmp(type, USERATTR_TYPE_NONADMIN_KW) != 0 && 389 strcmp(type, USERATTR_TYPE_NORMAL_KW) != 0) 390 return (type); 391 392 return (NULL); 393 } 394 395 static const char * 396 check_lock_after_retries(const char *keyval) 397 { 398 if (keyval != NULL) { 399 if ((strcasecmp(keyval, "no") != 0) && 400 (strcasecmp(keyval, "yes") != 0) && 401 (*keyval != '\0')) { 402 return (keyval); 403 } 404 } 405 return (NULL); 406 } 407 408 static const char * 409 check_label(const char *labelstr) 410 { 411 int err; 412 m_label_t *lbl = NULL; 413 414 if (!is_system_labeled()) 415 return (NULL); 416 417 err = str_to_label(labelstr, &lbl, MAC_LABEL, L_NO_CORRECTION, NULL); 418 m_label_free(lbl); 419 420 if (err == -1) 421 return (labelstr); 422 423 return (NULL); 424 } 425 426 static const char * 427 check_idlecmd(const char *cmd) 428 { 429 if ((strcmp(cmd, USERATTR_IDLECMD_LOCK_KW) != 0) && 430 (strcmp(cmd, USERATTR_IDLECMD_LOGOUT_KW) != 0)) { 431 return (cmd); 432 } 433 434 return (NULL); 435 } 436 437 static const char * 438 check_idletime(const char *time) 439 { 440 int c; 441 unsigned char *up = (unsigned char *)time; 442 443 c = *up; 444 while (c != '\0') { 445 if (!isdigit(c)) 446 return (time); 447 c = *++up; 448 } 449 450 return (NULL); 451 } 452