usr/src/lib/libsecdb/common/chkauthattr.c
changeset 12273 63678502e95e
parent 12195 cf3a8ea2dcfd
child 12471 10160519e417
equal deleted inserted replaced
12272:400aca678a81 12273:63678502e95e
    20  */
    20  */
    21 /*
    21 /*
    22  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
    22  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
    23  */
    23  */
    24 
    24 
       
    25 #include <alloca.h>
    25 #include <stdio.h>
    26 #include <stdio.h>
    26 #include <stdlib.h>
    27 #include <stdlib.h>
    27 #include <string.h>
    28 #include <string.h>
    28 #include <sys/types.h>
       
    29 #include <sys/stat.h>
    29 #include <sys/stat.h>
    30 #include <fcntl.h>
       
    31 #include <sys/mman.h>
       
    32 #include <limits.h>
       
    33 #include <pwd.h>
    30 #include <pwd.h>
    34 #include <nss_dbdefs.h>
    31 #include <nss_dbdefs.h>
    35 #include <deflt.h>
    32 #include <deflt.h>
    36 #include <auth_attr.h>
    33 #include <auth_attr.h>
    37 #include <prof_attr.h>
    34 #include <prof_attr.h>
    38 #include <user_attr.h>
    35 #include <user_attr.h>
    39 
    36 
    40 
    37 #define	COPYTOSTACK(dst, csrc)		{	\
    41 static int _is_authorized(const char *, char *);
    38 		size_t len = strlen(csrc) + 1;	\
    42 static int _chk_policy_auth(const char *, const char *, char **, int *);
    39 		dst = alloca(len);		\
    43 static int _chkprof_for_auth(const char *, const char *, char **, int *);
    40 		(void) memcpy(dst, csrc, len);	\
    44 int
    41 	}
    45 chkauthattr(const char *authname, const char *username)
    42 
    46 {
    43 static kva_t *get_default_attrs(const char *);
    47 	int		auth_granted = 0;
    44 static void free_default_attrs(kva_t *);
    48 	char		*auths;
    45 
    49 	char		*profiles;
    46 /*
    50 	userattr_t	*user = NULL;
    47  * Enumeration functions for auths and profiles; the enumeration functions
    51 	char		*chkedprof[MAXPROFS];
    48  * take a callback with four arguments:
    52 	int		chkedprof_cnt = 0;
    49  *	const char *		profile name (or NULL unless wantattr is false)
    53 	int		i;
    50  *	kva_t *			attributes (or NULL unless wantattr is true)
    54 
    51  *	void *			context
    55 	if (authname == NULL || username == NULL)
    52  *	void *			pointer to the result
    56 		return (0);
    53  * When the call back returns non-zero, the enumeration ends.
    57 
    54  * The function might be NULL but only for profiles as we are always collecting
    58 	/* Check against AUTHS_GRANTED and PROFS_GRANTED in policy.conf */
    55  * all the profiles.
    59 	auth_granted = _chk_policy_auth(authname, username, chkedprof,
    56  * Both the auths and the profiles arguments may be NULL.
    60 	    &chkedprof_cnt);
    57  *
    61 	if (auth_granted)
    58  * These should be the only implementation of the algorithm of "finding me
    62 		goto exit;
    59  * all the profiles/athorizations/keywords/etc.
    63 
    60  */
    64 	if ((user = getusernam(username)) == NULL)
    61 
    65 		goto exit;
    62 #define	CONSUSER_PROFILE_KW		"consprofile"
    66 
    63 #define	DEF_LOCK_AFTER_RETRIES		"LOCK_AFTER_RETRIES="
    67 	/* Check against authorizations listed in user_attr */
    64 
    68 	if ((auths = kva_match(user->attr, USERATTR_AUTHS_KW)) != NULL) {
    65 static struct dfltplcy {
    69 		auth_granted = _is_authorized(authname, auths);
    66 	char *attr;
    70 		if (auth_granted)
    67 	const char *defkw;
    71 			goto exit;
    68 } dfltply[] = {
    72 	}
    69 	/* CONSUSER MUST BE FIRST! */
    73 
    70 	{ CONSUSER_PROFILE_KW,			DEF_CONSUSER},
    74 	/* Check against authorizations specified by profiles */
    71 	{ PROFATTR_AUTHS_KW,			DEF_AUTH},
    75 	if ((profiles = kva_match(user->attr, USERATTR_PROFILES_KW)) != NULL)
    72 	{ PROFATTR_PROFS_KW,			DEF_PROF},
    76 		auth_granted = _chkprof_for_auth(profiles, authname,
    73 	{ USERATTR_LIMPRIV_KW,			DEF_LIMITPRIV},
    77 		    chkedprof, &chkedprof_cnt);
    74 	{ USERATTR_DFLTPRIV_KW,			DEF_DFLTPRIV},
    78 
    75 	{ USERATTR_LOCK_AFTER_RETRIES_KW,	DEF_LOCK_AFTER_RETRIES}
    79 exit:
    76 };
    80 	/* free memory allocated for checked array */
    77 
    81 	for (i = 0; i < chkedprof_cnt; i++) {
    78 #define	NDFLTPLY	(sizeof (dfltply)/sizeof (struct dfltplcy))
    82 		free(chkedprof[i]);
    79 #define	GETCONSPROF(a)	(kva_match((a), CONSUSER_PROFILE_KW))
    83 	}
    80 #define	GETPROF(a)	(kva_match((a), PROFATTR_PROFS_KW))
    84 
    81 
    85 	if (user != NULL)
    82 /*
    86 		free_userattr(user);
    83  * Enumerate profiles from listed profiles.
    87 
    84  */
    88 	return (auth_granted);
    85 int
    89 }
    86 _enum_common_p(const char *cprofiles,
    90 
    87     int (*cb)(const char *, kva_t *, void *, void *),
    91 static int
    88     void *ctxt, void *pres, boolean_t wantattr,
    92 _chkprof_for_auth(const char *profs, const char *authname,
    89     int *pcnt, char *profs[MAXPROFS])
    93     char **chkedprof, int *chkedprof_cnt)
    90 {
    94 {
    91 	char *prof, *last;
    95 
    92 	char *profiles;
    96 	char *prof, *lasts, *auths, *profiles;
    93 	profattr_t *pa;
    97 	profattr_t	*pa;
    94 	int i;
    98 	int		i;
    95 	int res = 0;
    99 	int		checked = 0;
    96 
   100 
    97 	if (cprofiles == NULL)
   101 	for (prof = strtok_r((char *)profs, ",", &lasts); prof != NULL;
    98 		return (0);
   102 	    prof = strtok_r(NULL, ",", &lasts)) {
    99 
   103 
   100 	if (*pcnt > 0 && strcmp(profs[*pcnt - 1], PROFILE_STOP) == NULL)
   104 		checked = 0;
   101 		return (0);
   105 		/* check if this profile has been checked */
   102 
   106 		for (i = 0; i < *chkedprof_cnt; i++) {
   103 	COPYTOSTACK(profiles, cprofiles)
   107 			if (strcmp(chkedprof[i], prof) == 0) {
   104 
   108 				checked = 1;
   105 	while (prof = strtok_r(profiles, KV_SEPSTR, &last)) {
   109 				break;
   106 
   110 			}
   107 		profiles = NULL;	/* For next iterations of strtok_r */
   111 		}
   108 
   112 
   109 		for (i = 0; i < *pcnt; i++)
   113 		if (!checked) {
   110 			if (strcmp(profs[i], prof) == 0)
   114 
   111 				goto cont;
   115 			chkedprof[*chkedprof_cnt] = strdup(prof);
   112 
   116 			*chkedprof_cnt = *chkedprof_cnt + 1;
   113 		if (*pcnt >= MAXPROFS)		/* oops: too many profs */
   117 
   114 			return (-1);
   118 			if ((pa = getprofnam(prof)) == NULL)
   115 
   119 				continue;
   116 		/* Add it */
   120 
   117 		profs[(*pcnt)++] = strdup(prof);
   121 			if ((auths = kva_match(pa->attr,
   118 
   122 			    PROFATTR_AUTHS_KW)) != NULL) {
   119 		if (strcmp(profs[*pcnt - 1], PROFILE_STOP) == 0)
   123 				if (_is_authorized(authname, auths)) {
   120 			break;
   124 					free_profattr(pa);
   121 
   125 					return (1);
   122 		/* find the profiles for this profile */
   126 				}
   123 		pa = getprofnam(prof);
   127 			}
   124 
   128 			if ((profiles =
   125 		if (cb != NULL && (!wantattr || pa != NULL && pa->attr != NULL))
   129 			    kva_match(pa->attr, PROFATTR_PROFS_KW)) != NULL) {
   126 			res = cb(prof, pa ? pa->attr : NULL, ctxt, pres);
   130 				/* Check for authorization in subprofiles */
   127 
   131 				if (_chkprof_for_auth(profiles, authname,
   128 		if (pa != NULL) {
   132 				    chkedprof, chkedprof_cnt)) {
   129 			if (res == 0 && pa->attr != NULL) {
   133 					free_profattr(pa);
   130 				res = _enum_common_p(GETPROF(pa->attr), cb,
   134 					return (1);
   131 				    ctxt, pres, wantattr, pcnt, profs);
   135 				}
       
   136 			}
   132 			}
   137 			free_profattr(pa);
   133 			free_profattr(pa);
   138 		}
   134 		}
   139 	}
   135 		if (res != 0)
   140 	/* authorization not found in any profile */
   136 			return (res);
   141 	return (0);
   137 cont:
       
   138 		continue;
       
   139 	}
       
   140 	return (res);
       
   141 }
       
   142 
       
   143 /*
       
   144  * Enumerate all attributes associated with a username and the profiles
       
   145  * associated with the user.
       
   146  */
       
   147 static int
       
   148 _enum_common(const char *username,
       
   149     int (*cb)(const char *, kva_t *, void *, void *),
       
   150     void *ctxt, void *pres, boolean_t wantattr)
       
   151 {
       
   152 	userattr_t *ua;
       
   153 	int res = 0;
       
   154 	int cnt = 0;
       
   155 	char *profs[MAXPROFS];
       
   156 	kva_t *kattrs;
       
   157 
       
   158 	if (cb == NULL)
       
   159 		return (-1);
       
   160 
       
   161 	ua = getusernam(username);
       
   162 
       
   163 	if (ua != NULL) {
       
   164 		if (ua->attr != NULL) {
       
   165 			if (wantattr)
       
   166 				res = cb(NULL, ua->attr, ctxt, pres);
       
   167 			if (res == 0) {
       
   168 				res = _enum_common_p(GETPROF(ua->attr),
       
   169 				    cb, ctxt, pres, wantattr, &cnt, profs);
       
   170 			}
       
   171 		}
       
   172 		free_userattr(ua);
       
   173 		if (res != 0)
       
   174 			return (res);
       
   175 	}
       
   176 
       
   177 	if ((cnt == 0 || strcmp(profs[cnt-1], PROFILE_STOP) != 0) &&
       
   178 	    (kattrs = get_default_attrs(username)) != NULL) {
       
   179 
       
   180 		res = _enum_common_p(GETCONSPROF(kattrs), cb, ctxt, pres,
       
   181 		    wantattr, &cnt, profs);
       
   182 
       
   183 		if (res == 0) {
       
   184 			res = _enum_common_p(GETPROF(kattrs), cb, ctxt, pres,
       
   185 			    wantattr, &cnt, profs);
       
   186 		}
       
   187 
       
   188 		if (res == 0 && wantattr)
       
   189 			res = cb(NULL, kattrs, ctxt, pres);
       
   190 
       
   191 		free_default_attrs(kattrs);
       
   192 	}
       
   193 
       
   194 	free_proflist(profs, cnt);
       
   195 
       
   196 	return (res);
       
   197 }
       
   198 
       
   199 /*
       
   200  * Enumerate profiles with a username argument.
       
   201  */
       
   202 int
       
   203 _enum_profs(const char *username,
       
   204     int (*cb)(const char *, kva_t *, void *, void *),
       
   205     void *ctxt, void *pres)
       
   206 {
       
   207 	return (_enum_common(username, cb, ctxt, pres, B_FALSE));
       
   208 }
       
   209 
       
   210 /*
       
   211  * Enumerate attributes with a username argument.
       
   212  */
       
   213 int
       
   214 _enum_attrs(const char *username,
       
   215     int (*cb)(const char *, kva_t *, void *, void *),
       
   216     void *ctxt, void *pres)
       
   217 {
       
   218 	return (_enum_common(username, cb, ctxt, pres, B_TRUE));
       
   219 }
       
   220 
       
   221 
       
   222 /*
       
   223  * Enumerate authorizations in the "auths" argument.
       
   224  */
       
   225 static int
       
   226 _enum_auths_a(const char *cauths, int (*cb)(const char *, void *, void *),
       
   227     void *ctxt, void *pres)
       
   228 {
       
   229 	char *auth, *last, *auths;
       
   230 	int res = 0;
       
   231 
       
   232 	if (cauths == NULL || cb == NULL)
       
   233 		return (0);
       
   234 
       
   235 	COPYTOSTACK(auths, cauths)
       
   236 
       
   237 	while (auth = strtok_r(auths, KV_SEPSTR, &last)) {
       
   238 		auths = NULL;		/* For next iterations of strtok_r */
       
   239 
       
   240 		res = cb(auth, ctxt, pres);
       
   241 
       
   242 		if (res != 0)
       
   243 			return (res);
       
   244 	}
       
   245 	return (res);
       
   246 }
       
   247 
       
   248 /*
       
   249  * Magic struct and function to allow using the _enum_attrs functions to
       
   250  * enumerate the authorizations.
       
   251  */
       
   252 typedef struct ccomm2auth {
       
   253 	int (*cb)(const char *, void *, void *);
       
   254 	void *ctxt;
       
   255 } ccomm2auth;
       
   256 
       
   257 /*ARGSUSED*/
       
   258 static int
       
   259 comm2auth(const char *name, kva_t *attr, void *ctxt, void *pres)
       
   260 {
       
   261 	ccomm2auth *ca = ctxt;
       
   262 	char *auths;
       
   263 
       
   264 	/* Note: PROFATTR_AUTHS_KW is equal to USERATTR_AUTHS_KW */
       
   265 	auths = kva_match(attr, PROFATTR_AUTHS_KW);
       
   266 	return (_enum_auths_a(auths, ca->cb, ca->ctxt, pres));
       
   267 }
       
   268 
       
   269 /*
       
   270  * Enumerate authorizations for username.
       
   271  */
       
   272 int
       
   273 _enum_auths(const char *username,
       
   274     int (*cb)(const char *, void *, void *),
       
   275     void *ctxt, void *pres)
       
   276 {
       
   277 	ccomm2auth c2a;
       
   278 
       
   279 	if (cb == NULL)
       
   280 		return (-1);
       
   281 
       
   282 	c2a.cb = cb;
       
   283 	c2a.ctxt = ctxt;
       
   284 
       
   285 	return (_enum_common(username, comm2auth, &c2a, pres, B_TRUE));
   142 }
   286 }
   143 
   287 
   144 int
   288 int
   145 _auth_match(const char *pattern, const char *auth)
   289 _auth_match(const char *pattern, const char *auth)
   146 {
   290 {
   147 	size_t len;
   291 	size_t len;
   148 	char wildcard = KV_WILDCHAR;
       
   149 	char *grant;
   292 	char *grant;
   150 
   293 
   151 	len = strlen(pattern);
   294 	len = strlen(pattern);
   152 
   295 
   153 	/*
   296 	/*
   154 	 * If the wildcard is not in the last position in the string, don't
   297 	 * If the wildcard is not in the last position in the string, don't
   155 	 * match against it.
   298 	 * match against it.
   156 	 */
   299 	 */
   157 	if (pattern[len-1] != wildcard)
   300 	if (pattern[len-1] != KV_WILDCHAR)
   158 		return (0);
   301 		return (0);
   159 
   302 
   160 	/*
   303 	/*
   161 	 * If the strings are identical up to the wildcard and auth does not
   304 	 * If the strings are identical up to the wildcard and auth does not
   162 	 * end in "grant", then we have a match.
   305 	 * end in "grant", then we have a match.
   171 
   314 
   172 	return (0);
   315 	return (0);
   173 }
   316 }
   174 
   317 
   175 static int
   318 static int
   176 _is_authorized(const char *authname, char *auths)
   319 _is_authorized(const char *auth, void *authname, void *res)
   177 {
   320 {
   178 	int	found = 0;	/* have we got a match, yet */
   321 	int *resp = res;
   179 	char	wildcard = '*';
   322 
   180 	char	*auth;		/* current authorization being compared */
   323 	if (strcmp(authname, auth) == 0 ||
   181 	char	*buf;
   324 	    (strchr(auth, KV_WILDCHAR) != NULL &&
   182 	char	*lasts;
   325 	    _auth_match(auth, authname))) {
   183 
   326 		*resp = 1;
   184 	buf = strdup(auths);
   327 		return (1);
   185 	for (auth = strtok_r(auths, ",", &lasts); auth != NULL && !found;
   328 	}
   186 	    auth = strtok_r(NULL, ",", &lasts)) {
   329 
   187 		if (strcmp((char *)authname, auth) == 0) {
   330 	return (0);
   188 			/* Exact match.  We're done. */
   331 }
   189 			found = 1;
   332 
   190 		} else if (strchr(auth, wildcard) != NULL) {
   333 int
   191 			if (_auth_match(auth, authname)) {
   334 chkauthattr(const char *authname, const char *username)
   192 				found = 1;
   335 {
   193 				break;
   336 	int		auth_granted = 0;
   194 			}
   337 
   195 		}
   338 	if (authname == NULL || username == NULL)
   196 	}
   339 		return (0);
   197 
   340 
   198 	free(buf);
   341 	(void) _enum_auths(username, _is_authorized, (char *)authname,
   199 
   342 	    &auth_granted);
   200 	return (found);
   343 
   201 }
   344 	return (auth_granted);
   202 
       
   203 
       
   204 /*
       
   205  * read /etc/security/policy.conf for AUTHS_GRANTED.
       
   206  * return 1 if found matching authname.
       
   207  * Otherwise, read PROFS_GRANTED to see if authname exists in any
       
   208  * default profiles.
       
   209  */
       
   210 static int
       
   211 _chk_policy_auth(const char *authname, const char *username, char **chkedprof,
       
   212     int *chkedprof_cnt)
       
   213 {
       
   214 	char	*auths = NULL;
       
   215 	char	*profs = NULL;
       
   216 	int	ret = 1;
       
   217 
       
   218 	if (_get_user_defs(username, &auths, &profs) != 0)
       
   219 		return (0);
       
   220 
       
   221 	if (auths != NULL) {
       
   222 		if (_is_authorized(authname, auths))
       
   223 			goto exit;
       
   224 	}
       
   225 
       
   226 	if (profs != NULL) {
       
   227 		if (_chkprof_for_auth(profs, authname, chkedprof,
       
   228 		    chkedprof_cnt))
       
   229 			goto exit;
       
   230 	}
       
   231 	ret = 0;
       
   232 
       
   233 exit:
       
   234 	_free_user_defs(auths, profs);
       
   235 	return (ret);
       
   236 }
   345 }
   237 
   346 
   238 #define	CONSOLE_USER_LINK "/dev/vt/console_user"
   347 #define	CONSOLE_USER_LINK "/dev/vt/console_user"
   239 
   348 
   240 static int
   349 static int
   255 	}
   364 	}
   256 
   365 
   257 	return (pw.pw_uid == cons.st_uid);
   366 	return (pw.pw_uid == cons.st_uid);
   258 }
   367 }
   259 
   368 
   260 
   369 static void
   261 int
   370 free_default_attrs(kva_t *kva)
   262 _get_user_defs(const char *user, char **def_auth, char **def_prof)
   371 {
   263 {
   372 	int i;
   264 	char *cp;
   373 
   265 	char *profs;
   374 	for (i = 0; i < kva->length; i++)
   266 	void	*defp;
   375 		free(kva->data[i].value);
   267 
   376 
   268 	if ((defp = defopen_r(AUTH_POLICY)) == NULL) {
   377 	free(kva);
   269 		if (def_auth != NULL) {
   378 }
   270 			*def_auth = NULL;
   379 
   271 		}
   380 /*
   272 		if (def_prof != NULL) {
   381  * Return the default attributes; this are ignored when a STOP profile
   273 			*def_prof = NULL;
   382  * was found.
   274 		}
   383  */
   275 		return (-1);
   384 static kva_t *
   276 	}
   385 get_default_attrs(const char *user)
   277 
   386 {
   278 	if (def_auth != NULL) {
   387 	void *defp;
   279 		if ((cp = defread_r(DEF_AUTH, defp)) != NULL) {
   388 	kva_t *kva;
   280 			if ((*def_auth = strdup(cp)) == NULL) {
   389 	int i;
   281 				defclose_r(defp);
   390 
   282 				return (-1);
   391 	kva = malloc(sizeof (kva_t) + sizeof (kv_t) * NDFLTPLY);
   283 			}
   392 
   284 		} else {
   393 	if (kva == NULL)
   285 			*def_auth = NULL;
   394 		return (NULL);
   286 		}
   395 
   287 	}
   396 	kva->data = (kv_t *)(void *)&kva[1];
   288 	if (def_prof != NULL) {
   397 	kva->length = 0;
   289 		if (is_cons_user(user) &&
   398 
   290 		    (cp = defread_r(DEF_CONSUSER, defp)) != NULL) {
   399 	if ((defp = defopen_r(AUTH_POLICY)) == NULL)
   291 			if ((*def_prof = strdup(cp)) == NULL) {
   400 		goto return_null;
   292 				defclose_r(defp);
   401 
   293 				return (-1);
   402 	for (i = is_cons_user(user) ? 0 : 1; i < NDFLTPLY; i++) {
   294 			}
   403 		char *cp = defread_r(dfltply[i].defkw, defp);
   295 		}
   404 
   296 		if ((cp = defread_r(DEF_PROF, defp)) != NULL) {
   405 		if (cp == NULL)
   297 			int	prof_len;
   406 			continue;
   298 
   407 		if ((cp = strdup(cp)) == NULL)
   299 			if (*def_prof == NULL) {
   408 			goto return_null;
   300 				if ((*def_prof = strdup(cp)) == NULL) {
   409 
   301 					defclose_r(defp);
   410 		kva->data[kva->length].key = dfltply[i].attr;
   302 					return (-1);
   411 		kva->data[kva->length++].value = cp;
   303 				}
   412 	}
   304 				defclose_r(defp);
   413 
   305 				return (0);
   414 	(void) defclose_r(defp);
   306 			}
   415 	return (kva);
   307 
   416 
   308 			/* concatenate def profs with "," separator */
   417 return_null:
   309 			prof_len = strlen(*def_prof) + strlen(cp) + 2;
   418 	if (defp != NULL)
   310 			if ((profs = malloc(prof_len)) == NULL) {
   419 		(void) defclose_r(defp);
   311 				free(*def_prof);
   420 
   312 				*def_prof = NULL;
   421 	free_default_attrs(kva);
   313 				defclose_r(defp);
   422 	return (NULL);
   314 				return (-1);
   423 }
   315 			}
       
   316 			(void) snprintf(profs, prof_len, "%s,%s", *def_prof,
       
   317 			    cp);
       
   318 			free(*def_prof);
       
   319 			*def_prof = profs;
       
   320 		}
       
   321 	}
       
   322 
       
   323 	defclose_r(defp);
       
   324 	return (0);
       
   325 }
       
   326 
       
   327 
       
   328 void
       
   329 _free_user_defs(char *def_auth, char *def_prof)
       
   330 {
       
   331 	free(def_auth);
       
   332 	free(def_prof);
       
   333 }