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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <strings.h> 32 #include <auth_attr.h> 33 #include <prof_attr.h> 34 #include <user_attr.h> 35 #include <project.h> 36 #include <secdb.h> 37 #include <pwd.h> 38 #include <unistd.h> 39 #include <priv.h> 40 #include <errno.h> 41 #include "funcs.h" 42 #include "messages.h" 43 #include "userdefs.h" 44 45 typedef struct ua_key { 46 const char *key; 47 const char *(*check)(const char *); 48 const char *errstr; 49 char *newvalue; 50 } ua_key_t; 51 52 static const char role[] = "role name"; 53 static const char prof[] = "profile name"; 54 static const char proj[] = "project name"; 55 static const char priv[] = "privilege set"; 56 static const char auth[] = "authorization"; 57 static const char type[] = "user type"; 58 static const char lock[] = "lock_after_retries value"; 59 60 61 static const char *check_auth(const char *); 62 static const char *check_prof(const char *); 63 static const char *check_role(const char *); 64 static const char *check_proj(const char *); 65 static const char *check_privset(const char *); 66 static const char *check_type(const char *); 67 static const char *check_lock_after_retries(const char *); 68 69 int nkeys; 70 71 static ua_key_t keys[] = { 72 /* First entry is always set correctly in main() */ 73 { USERATTR_TYPE_KW, check_type, type }, 74 { USERATTR_AUTHS_KW, check_auth, auth }, 75 { USERATTR_PROFILES_KW, check_prof, prof }, 76 { USERATTR_ROLES_KW, check_role, role }, 77 { USERATTR_DEFAULTPROJ_KW, check_proj, proj }, 78 { USERATTR_LIMPRIV_KW, check_privset, priv }, 79 { USERATTR_DFLTPRIV_KW, check_privset, priv }, 80 { USERATTR_LOCK_AFTER_RETRIES_KW, check_lock_after_retries, lock }, 81 }; 82 83 #define NKEYS (sizeof (keys)/sizeof (ua_key_t)) 84 85 /* 86 * Change a key, there are three different call sequences: 87 * 88 * key, value - key with option letter, value. 89 * NULL, value - -K key=value option. 90 */ 91 92 void 93 change_key(const char *key, char *value) 94 { 95 int i; 96 const char *res; 97 98 if (key == NULL) { 99 key = value; 100 value = strchr(value, '='); 101 /* Bad value */ 102 if (value == NULL) { 103 errmsg(M_INVALID_VALUE); 104 exit(EX_BADARG); 105 } 106 *value++ = '\0'; 107 } 108 109 for (i = 0; i < NKEYS; i++) { 110 if (strcmp(key, keys[i].key) == 0) { 111 if (keys[i].newvalue != NULL) { 112 /* Can't set a value twice */ 113 errmsg(M_REDEFINED_KEY, key); 114 exit(EX_BADARG); 115 } 116 117 if (keys[i].check != NULL && 118 (res = keys[i].check(value)) != NULL) { 119 errmsg(M_INVALID, res, keys[i].errstr); 120 exit(EX_BADARG); 121 } 122 keys[i].newvalue = value; 123 nkeys++; 124 return; 125 } 126 } 127 errmsg(M_INVALID_KEY, key); 128 exit(EX_BADARG); 129 } 130 131 /* 132 * Add the keys to the argument vector. 133 */ 134 void 135 addkey_args(char **argv, int *index) 136 { 137 int i; 138 139 for (i = 0; i < NKEYS; i++) { 140 const char *key = keys[i].key; 141 char *val = keys[i].newvalue; 142 size_t len; 143 char *arg; 144 145 if (val == NULL) 146 continue; 147 148 len = strlen(key) + strlen(val) + 2; 149 arg = malloc(len); 150 151 (void) snprintf(arg, len, "%s=%s", key, val); 152 argv[(*index)++] = "-K"; 153 argv[(*index)++] = arg; 154 } 155 } 156 157 /* 158 * Propose a default value for a key and get the actual value back. 159 * If the proposed default value is NULL, return the actual value set. 160 * The key argument is the user_attr key. 161 */ 162 char * 163 getsetdefval(const char *key, char *dflt) 164 { 165 int i; 166 167 for (i = 0; i < NKEYS; i++) 168 if (strcmp(keys[i].key, key) == 0) 169 if (keys[i].newvalue != NULL) 170 return (keys[i].newvalue); 171 else 172 return (keys[i].newvalue = dflt); 173 return (NULL); 174 } 175 176 char * 177 getusertype(char *cmdname) 178 { 179 static char usertype[MAX_TYPE_LENGTH]; 180 char *cmd; 181 182 if (cmd = strrchr(cmdname, '/')) 183 ++cmd; 184 else 185 cmd = cmdname; 186 187 /* get user type based on the program name */ 188 if (strncmp(cmd, CMD_PREFIX_USER, 189 strlen(CMD_PREFIX_USER)) == 0) 190 strcpy(usertype, USERATTR_TYPE_NORMAL_KW); 191 else 192 strcpy(usertype, USERATTR_TYPE_NONADMIN_KW); 193 194 return (usertype); 195 } 196 197 int 198 is_role(char *usertype) 199 { 200 if (strcmp(usertype, USERATTR_TYPE_NONADMIN_KW) == 0) 201 return (1); 202 /* not a role */ 203 return (0); 204 } 205 206 /* 207 * Verifies the provided list of authorizations are all valid. 208 * 209 * Returns NULL if all authorization names are valid. 210 * Otherwise, returns the invalid authorization name 211 * 212 */ 213 static const char * 214 check_auth(const char *auths) 215 { 216 char *authname; 217 authattr_t *result; 218 char *tmp; 219 struct passwd *pw; 220 int have_grant = 0; 221 222 tmp = strdup(auths); 223 224 authname = strtok(tmp, AUTH_SEP); 225 pw = getpwuid(getuid()); 226 if (pw == NULL) { 227 return (authname); 228 } 229 230 while (authname != NULL) { 231 char *suffix; 232 char *authtoks; 233 234 /* Find the suffix */ 235 if ((suffix = rindex(authname, '.')) == NULL) 236 return (authname); 237 238 /* Check for existence in auth_attr */ 239 suffix++; 240 if (strcmp(suffix, KV_WILDCARD)) { /* Not a wildcard */ 241 result = getauthnam(authname); 242 if (result == NULL) { 243 /* can't find the auth */ 244 free_authattr(result); 245 return (authname); 246 } 247 free_authattr(result); 248 } 249 250 /* Check if user has been granted this authorization */ 251 if (!chkauthattr(authname, pw->pw_name)) { 252 return (authname); 253 } 254 255 /* Check if user can delegate this authorization */ 256 if (strcmp(suffix, "grant")) { /* Not a grant option */ 257 authtoks = malloc(strlen(authname) + sizeof ("grant")); 258 strcpy(authtoks, authname); 259 have_grant = 0; 260 while ((suffix = rindex(authtoks, '.')) && 261 !have_grant) { 262 strcpy(suffix, ".grant"); 263 if (chkauthattr(authtoks, pw->pw_name)) 264 have_grant = 1; 265 else 266 *suffix = '\0'; 267 } 268 if (!have_grant) 269 return (authname); 270 } 271 authname = strtok(NULL, AUTH_SEP); 272 } 273 return (NULL); 274 } 275 276 /* 277 * Verifies the provided list of profile names are valid. 278 * 279 * Returns NULL if all profile names are valid. 280 * Otherwise, returns the invalid profile name 281 * 282 */ 283 static const char * 284 check_prof(const char *profs) 285 { 286 char *profname; 287 profattr_t *result; 288 char *tmp; 289 290 tmp = strdup(profs); 291 292 profname = strtok(tmp, PROF_SEP); 293 while (profname != NULL) { 294 result = getprofnam(profname); 295 if (result == NULL) { 296 /* can't find the profile */ 297 return (profname); 298 } 299 free_profattr(result); 300 profname = strtok(NULL, PROF_SEP); 301 } 302 return (NULL); 303 } 304 305 306 /* 307 * Verifies the provided list of role names are valid. 308 * 309 * Returns NULL if all role names are valid. 310 * Otherwise, returns the invalid role name 311 * 312 */ 313 static const char * 314 check_role(const char *roles) 315 { 316 char *rolename; 317 userattr_t *result; 318 char *utype; 319 char *tmp; 320 321 tmp = strdup(roles); 322 323 rolename = strtok(tmp, ROLE_SEP); 324 while (rolename != NULL) { 325 result = getusernam(rolename); 326 if (result == NULL) { 327 /* can't find the rolename */ 328 return (rolename); 329 } 330 /* Now, make sure it is a role */ 331 utype = kva_match(result->attr, USERATTR_TYPE_KW); 332 if (utype == NULL) { 333 /* no user type defined. not a role */ 334 free_userattr(result); 335 return (rolename); 336 } 337 if (strcmp(utype, USERATTR_TYPE_NONADMIN_KW) != 0) { 338 free_userattr(result); 339 return (rolename); 340 } 341 free_userattr(result); 342 rolename = strtok(NULL, ROLE_SEP); 343 } 344 return (NULL); 345 } 346 347 static const char * 348 check_proj(const char *proj) 349 { 350 if (getprojidbyname(proj) < 0) { 351 return (proj); 352 } else { 353 return (NULL); 354 } 355 } 356 357 static const char * 358 check_privset(const char *pset) 359 { 360 priv_set_t *tmp; 361 const char *res; 362 363 tmp = priv_str_to_set(pset, ",", &res); 364 365 if (tmp != NULL) { 366 res = NULL; 367 priv_freeset(tmp); 368 } else if (res == NULL) 369 res = strerror(errno); 370 371 return (res); 372 } 373 374 static const char * 375 check_type(const char *type) 376 { 377 if (strcmp(type, USERATTR_TYPE_NONADMIN_KW) != 0 && 378 strcmp(type, USERATTR_TYPE_NORMAL_KW) != 0) 379 return (type); 380 381 return (NULL); 382 } 383 384 static const char * 385 check_lock_after_retries(const char *keyval) 386 { 387 if (keyval != NULL) { 388 if ((strcasecmp(keyval, "no") != 0) && 389 (strcasecmp(keyval, "yes") != 0) && 390 (*keyval != '\0')) { 391 return (keyval); 392 } 393 } 394 return (NULL); 395 } 396