1148473ee5cc01079b9810f6e5ff0a4a99c47d19
[strongswan.git] / src / charon / credentials / auth_info.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18
19 #include "auth_info.h"
20
21 #include <daemon.h>
22 #include <utils/linked_list.h>
23 #include <utils/identification.h>
24 #include <credentials/certificates/certificate.h>
25
26 ENUM(auth_item_names, AUTHN_CA_CERT, AUTHZ_AC_GROUP,
27 "AUTHN_CA_CERT",
28 "AUTHN_CA_CERT_KEYID",
29 "AUTHN_IM_CERT",
30 "AUTHN_SUBJECT_CERT",
31 "AUTHZ_PUBKEY",
32 "AUTHZ_PSK",
33 "AUTHZ_EAP",
34 "AUTHZ_CA_CERT",
35 "AUTHZ_IM_CERT",
36 "AUTHZ_SUBJECT_CERT",
37 "AUTHZ_CRL_VALIDATION",
38 "AUTHZ_OCSP_VALIDATION",
39 "AUTHZ_AC_GROUP",
40 );
41
42 typedef struct private_auth_info_t private_auth_info_t;
43
44 /**
45 * private data of item_set
46 */
47 struct private_auth_info_t {
48
49 /**
50 * public functions
51 */
52 auth_info_t public;
53
54 /**
55 * list of item_t's
56 */
57 linked_list_t *items;
58 };
59
60 typedef struct item_t item_t;
61
62 struct item_t {
63 /** type of this item */
64 auth_item_t type;
65 /** associated privlege value, if any */
66 void *value;
67 };
68
69 /**
70 * implements item_enumerator_t.enumerate
71 */
72 static bool item_filter(void *data, item_t **item, auth_item_t *type,
73 void *unused, void **value)
74 {
75 *type = (*item)->type;
76 *value = (*item)->value;
77 return TRUE;
78 }
79
80 /**
81 * Implementation of auth_info_t.create_item_enumerator.
82 */
83 static enumerator_t* create_item_enumerator(private_auth_info_t *this)
84 {
85 return enumerator_create_filter(this->items->create_enumerator(this->items),
86 (void*)item_filter, NULL, NULL);
87 }
88
89 /**
90 * Implementation of auth_info_t.get_item.
91 */
92 static bool get_item(private_auth_info_t *this, auth_item_t type, void** value)
93 {
94 enumerator_t *enumerator;
95 void *current_value;
96 auth_item_t current_type;
97 bool found = FALSE;
98
99 enumerator = create_item_enumerator(this);
100 while (enumerator->enumerate(enumerator, &current_type, &current_value))
101 {
102 if (type == current_type)
103 {
104 *value = current_value;
105 found = TRUE;
106 break;
107 }
108 }
109 enumerator->destroy(enumerator);
110 return found;
111 }
112
113 /**
114 * Implementation of auth_info_t.add_item.
115 */
116 static void add_item(private_auth_info_t *this, auth_item_t type, void *value)
117 {
118 item_t *item = malloc_thing(item_t);
119
120 item->type = type;
121 switch (type)
122 {
123 case AUTHZ_PUBKEY:
124 {
125 public_key_t *key = (public_key_t*)value;
126
127 item->value = key->get_ref(key);
128 break;
129 }
130 case AUTHZ_PSK:
131 {
132 shared_key_t *key = (shared_key_t*)value;
133
134 item->value = key->get_ref(key);
135 break;
136 }
137 case AUTHN_CA_CERT:
138 case AUTHN_IM_CERT:
139 case AUTHN_SUBJECT_CERT:
140 case AUTHZ_CA_CERT:
141 case AUTHZ_IM_CERT:
142 case AUTHZ_SUBJECT_CERT:
143 {
144 certificate_t *cert = (certificate_t*)value;
145
146 item->value = cert->get_ref(cert);
147 break;
148 }
149 case AUTHZ_CRL_VALIDATION:
150 case AUTHZ_OCSP_VALIDATION:
151 {
152 cert_validation_t *validation = malloc_thing(cert_validation_t);
153
154 *validation = *(cert_validation_t*)value;
155 item->value = validation;
156 break;
157 }
158 case AUTHZ_EAP:
159 {
160 eap_method_t *method = malloc_thing(eap_method_t);
161
162 *method = *(eap_method_t*)value;
163 item->value = method;
164 break;
165 }
166 case AUTHN_CA_CERT_KEYID:
167 case AUTHZ_AC_GROUP:
168 {
169 identification_t *id = (identification_t*)value;
170
171 item->value = id->clone(id);
172 break;
173 }
174 }
175 this->items->insert_last(this->items, item);
176 }
177
178
179 /**
180 * Implementation of auth_info_t.complies.
181 */
182 static bool complies(private_auth_info_t *this, auth_info_t *constraints)
183 {
184 enumerator_t *enumerator;
185 bool success = TRUE;
186 auth_item_t type;
187 void *value;
188
189 enumerator = constraints->create_item_enumerator(constraints);
190 while (enumerator->enumerate(enumerator, &type, &value))
191 {
192 switch (type)
193 {
194 case AUTHN_CA_CERT_KEYID:
195 case AUTHN_CA_CERT:
196 case AUTHN_IM_CERT:
197 case AUTHN_SUBJECT_CERT:
198 { /* skip non-authorization tokens */
199 continue;
200 }
201 case AUTHZ_CRL_VALIDATION:
202 case AUTHZ_OCSP_VALIDATION:
203 {
204 cert_validation_t *valid;
205
206 /* OCSP validation is also sufficient for CRL constraint, but
207 * not vice-versa */
208 if (!get_item(this, type, (void**)&valid) &&
209 type == AUTHZ_CRL_VALIDATION &&
210 !get_item(this, AUTHZ_OCSP_VALIDATION, (void**)&valid))
211 {
212 DBG1(DBG_CFG, "constraint check failed: %N requires at "
213 "least %N, but no check done", auth_item_names, type,
214 cert_validation_names, *(cert_validation_t*)value);
215 success = FALSE;
216 break;
217 }
218 switch (*(cert_validation_t*)value)
219 {
220 case VALIDATION_SKIPPED:
221 if (*valid == VALIDATION_SKIPPED)
222 {
223 break;
224 } /* FALL */
225 case VALIDATION_GOOD:
226 if (*valid == VALIDATION_GOOD)
227 {
228 break;
229 } /* FALL */
230 default:
231 DBG1(DBG_CFG, "constraint check failed: %N is %N, but "
232 "requires at least %N", auth_item_names, type,
233 cert_validation_names, *valid,
234 cert_validation_names, *(cert_validation_t*)value);
235 success = FALSE;
236 break;
237 }
238 break;
239 }
240 case AUTHZ_PUBKEY:
241 case AUTHZ_PSK:
242 case AUTHZ_IM_CERT:
243 case AUTHZ_SUBJECT_CERT:
244 case AUTHZ_EAP:
245 case AUTHZ_AC_GROUP:
246 DBG1(DBG_CFG, "constraint check %N not implemented!",
247 auth_item_names, type);
248 success = FALSE;
249 break;
250 case AUTHZ_CA_CERT:
251 {
252 certificate_t *cert;
253
254 if (!get_item(this, AUTHZ_CA_CERT, (void**)&cert) ||
255 !cert->equals(cert, (certificate_t*)value))
256 {
257 cert = (certificate_t*)value;
258 DBG1(DBG_CFG, "constraint check failed: peer not "
259 "authenticated by CA '%D'.", cert->get_issuer(cert));
260 success = FALSE;
261 }
262 break;
263 }
264 }
265 if (!success)
266 {
267 break;
268 }
269 }
270 enumerator->destroy(enumerator);
271 return success;
272 }
273
274 /**
275 * Implementation of auth_info_t.merge.
276 */
277 static void merge(private_auth_info_t *this, private_auth_info_t *other)
278 {
279 item_t *item;
280
281 while (other->items->remove_first(other->items, (void**)&item) == SUCCESS)
282 {
283 this->items->insert_last(this->items, item);
284 }
285 }
286
287 /**
288 * Implementation of auth_info_t.destroy
289 */
290 static void destroy(private_auth_info_t *this)
291 {
292 item_t *item;
293
294 while (this->items->remove_last(this->items, (void**)&item) == SUCCESS)
295 {
296 switch (item->type)
297 {
298 case AUTHZ_PUBKEY:
299 {
300 public_key_t *key = (public_key_t*)item->value;
301 key->destroy(key);
302 break;
303 }
304 case AUTHZ_PSK:
305 {
306 shared_key_t *key = (shared_key_t*)item->value;
307 key->destroy(key);
308 break;
309 }
310 case AUTHN_CA_CERT:
311 case AUTHN_IM_CERT:
312 case AUTHN_SUBJECT_CERT:
313 case AUTHZ_CA_CERT:
314 case AUTHZ_IM_CERT:
315 case AUTHZ_SUBJECT_CERT:
316 {
317 certificate_t *cert = (certificate_t*)item->value;
318 cert->destroy(cert);
319 break;
320 }
321 case AUTHZ_CRL_VALIDATION:
322 case AUTHZ_OCSP_VALIDATION:
323 case AUTHZ_EAP:
324 {
325 free(item->value);
326 break;
327 }
328 case AUTHN_CA_CERT_KEYID:
329 case AUTHZ_AC_GROUP:
330 {
331 identification_t *id = (identification_t*)item->value;
332 id->destroy(id);
333 break;
334 }
335 }
336 free(item);
337 }
338 this->items->destroy(this->items);
339 free(this);
340 }
341
342 /*
343 * see header file
344 */
345 auth_info_t *auth_info_create()
346 {
347 private_auth_info_t *this = malloc_thing(private_auth_info_t);
348
349 this->public.add_item = (void(*)(auth_info_t*, auth_item_t type, void *value))add_item;
350 this->public.get_item = (bool(*)(auth_info_t*, auth_item_t type, void **value))get_item;
351 this->public.create_item_enumerator = (enumerator_t*(*)(auth_info_t*))create_item_enumerator;
352 this->public.complies = (bool(*)(auth_info_t*, auth_info_t *))complies;
353 this->public.merge = (void(*)(auth_info_t*, auth_info_t *other))merge;
354 this->public.destroy = (void(*)(auth_info_t*))destroy;
355
356 this->items = linked_list_create();
357
358 return &this->public;
359 }
360