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