xref: /illumos-gate/usr/src/lib/libsecdb/common/chkauthattr.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
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 2004 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 <string.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <sys/mman.h>
36 #include <limits.h>
37 #include <deflt.h>
38 #include <auth_attr.h>
39 #include <prof_attr.h>
40 #include <user_attr.h>
41 
42 
43 static int _is_authorized(const char *, char *);
44 static int _chk_policy_auth(const char *, char **, int *);
45 static int _chkprof_for_auth(const char *, const char *, char **, int *);
46 
47 
48 int
49 chkauthattr(const char *authname, const char *username)
50 {
51 	int		auth_granted = 0;
52 	char		*auths;
53 	char		*profiles;
54 	userattr_t	*user;
55 	char		*chkedprof[MAXPROFS];
56 	int		chkedprof_cnt = 0;
57 	int		i;
58 
59 	if (authname == NULL || username == NULL)
60 		return (0);
61 
62 	auth_granted = _chk_policy_auth(authname, chkedprof, &chkedprof_cnt);
63 	if (auth_granted) {
64 		return (1);
65 	}
66 	if ((user = getusernam(username)) == NULL)
67 		return (0);
68 
69 	if ((auths = kva_match(user->attr, USERATTR_AUTHS_KW)) != NULL) {
70 		if (_is_authorized(authname, auths)) {
71 			free_userattr(user);
72 			return (1);
73 		}
74 	}
75 
76 	if ((profiles = kva_match(user->attr, USERATTR_PROFILES_KW)) == NULL) {
77 		free_userattr(user);
78 		return (0);
79 	}
80 
81 	auth_granted = _chkprof_for_auth(profiles, authname,
82 	    chkedprof, &chkedprof_cnt);
83 
84 	/* free memory allocated for checked array */
85 	for (i = 0; i < chkedprof_cnt; i++) {
86 		free(chkedprof[i]);
87 	}
88 
89 	free_userattr(user);
90 
91 	return (auth_granted);
92 }
93 
94 static int
95 _chkprof_for_auth(const char *profs, const char *authname,
96     char **chkedprof, int *chkedprof_cnt)
97 {
98 
99 	char *prof, *lasts, *auths, *profiles;
100 	profattr_t	*pa;
101 	int		i;
102 	int		checked = 0;
103 
104 	for (prof = strtok_r((char *)profs, ",", &lasts); prof != NULL;
105 	    prof = strtok_r(NULL, ",", &lasts)) {
106 
107 		checked = 0;
108 		/* check if this profile has been checked */
109 		for (i = 0; i < *chkedprof_cnt; i++) {
110 			if (strcmp(chkedprof[i], prof) == 0) {
111 				checked = 1;
112 				break;
113 			}
114 		}
115 
116 		if (!checked) {
117 
118 			chkedprof[*chkedprof_cnt] = strdup(prof);
119 			*chkedprof_cnt = *chkedprof_cnt + 1;
120 
121 			if ((pa = getprofnam(prof)) == NULL)
122 				continue;
123 
124 			if ((auths = kva_match(pa->attr,
125 			    PROFATTR_AUTHS_KW)) != NULL) {
126 				if (_is_authorized(authname, auths)) {
127 					free_profattr(pa);
128 					return (1);
129 				}
130 			}
131 			if ((profiles =
132 			    kva_match(pa->attr, PROFATTR_PROFS_KW)) != NULL) {
133 				/* Check for authorization in subprofiles */
134 				if (_chkprof_for_auth(profiles, authname,
135 				    chkedprof, chkedprof_cnt)) {
136 					free_profattr(pa);
137 					return (1);
138 				}
139 			}
140 			free_profattr(pa);
141 		}
142 	}
143 	/* authorization not found in any profile */
144 	return (0);
145 }
146 
147 int
148 _auth_match(const char *pattern, const char *auth)
149 {
150 	size_t len;
151 	char wildcard = KV_WILDCHAR;
152 	char *grant;
153 
154 	len = strlen(pattern);
155 
156 	/*
157 	 * If the wildcard is not in the last position in the string, don't
158 	 * match against it.
159 	 */
160 	if (pattern[len-1] != wildcard)
161 		return (0);
162 
163 	/*
164 	 * If the strings are identical up to the wildcard and auth does not
165 	 * end in "grant", then we have a match.
166 	 */
167 	if (strncmp(pattern, auth, len-1) == 0) {
168 		grant = strrchr(auth, '.');
169 		if (grant != NULL) {
170 			if (strncmp(grant + 1, "grant", 5) != NULL)
171 				return (1);
172 		}
173 	}
174 
175 	return (0);
176 }
177 
178 static int
179 _is_authorized(const char *authname, char *auths)
180 {
181 	int	found = 0;	/* have we got a match, yet */
182 	char	wildcard = '*';
183 	char	*auth;		/* current authorization being compared */
184 	char	*buf;
185 	char	*lasts;
186 
187 	buf = strdup(auths);
188 	for (auth = strtok_r(auths, ",", &lasts); auth != NULL && !found;
189 	    auth = strtok_r(NULL, ",", &lasts)) {
190 		if (strcmp((char *)authname, auth) == 0) {
191 			/* Exact match.  We're done. */
192 			found = 1;
193 		} else if (strchr(auth, wildcard) != NULL) {
194 			if (_auth_match(auth, authname)) {
195 				found = 1;
196 				break;
197 			}
198 		}
199 	}
200 
201 	free(buf);
202 
203 	return (found);
204 }
205 
206 
207 int
208 _get_auth_policy(char **def_auth, char **def_prof)
209 {
210 	char *cp;
211 
212 	if (defopen(AUTH_POLICY) != 0)
213 		return (-1);
214 
215 	cp = defread(DEF_AUTH);
216 	if (cp != NULL) {
217 		*def_auth = strdup(cp);
218 		if (*def_auth == NULL)
219 			return (-1);
220 	} else {
221 		*def_auth = NULL;
222 	}
223 
224 	cp = defread(DEF_PROF);
225 	if (cp != NULL) {
226 		*def_prof = strdup(cp);
227 		if (*def_prof == NULL) {
228 			free(*def_auth);
229 			return (-1);
230 		}
231 	} else {
232 		*def_prof = NULL;
233 	}
234 
235 	(void) defopen(NULL);
236 	return (0);
237 }
238 
239 /*
240  * read /etc/security/policy.conf for AUTHS_GRANTED.
241  * return 1 if found matching authname.
242  * Otherwise, read PROFS_GRANTED to see if authname exists in any
243  * default profiles.
244  */
245 static int
246 _chk_policy_auth(const char *authname, char **chkedprof, int *chkedprof_cnt)
247 {
248 	char	*auths, *profs;
249 	int	ret = 1;
250 
251 	if (_get_auth_policy(&auths, &profs) != 0)
252 		return (0);
253 
254 	if (auths != NULL) {
255 		if (_is_authorized(authname, auths))
256 			goto exit;
257 	}
258 
259 	if (profs != NULL) {
260 		if (_chkprof_for_auth(profs, authname, chkedprof,
261 		    chkedprof_cnt))
262 			goto exit;
263 	}
264 	ret = 0;
265 
266 exit:
267 	free(auths);
268 	free(profs);
269 	return (ret);
270 }
271