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. |