Home | History | Annotate | Download | only in user
      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