fixed compiler warning
[strongswan.git] / src / charon / credentials / auth_info.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2007 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19
20 #include "auth_info.h"
21
22 #include <daemon.h>
23 #include <utils/linked_list.h>
24 #include <utils/identification.h>
25 #include <credentials/certificates/certificate.h>
26
27 ENUM(auth_item_names, AUTHN_CA_CERT, AUTHZ_AC_GROUP,
28 "AUTHN_AUTH_CLASS",
29 "AUTHN_EAP_TYPE",
30 "AUTHN_EAP_VENDOR",
31 "AUTHN_EAP_IDENTITY",
32 "AUTHN_CA_CERT",
33 "AUTHN_CA_CERT_KEYID",
34 "AUTHN_CA_CERT_NAME",
35 "AUTHN_IM_CERT",
36 "AUTHN_SUBJECT_CERT",
37 "AUTHN_IM_HASH_URL",
38 "AUTHN_SUBJECT_HASH_URL",
39 "AUTHZ_PUBKEY",
40 "AUTHZ_PSK",
41 "AUTHZ_EAP",
42 "AUTHZ_CA_CERT",
43 "AUTHZ_CA_CERT_NAME",
44 "AUTHZ_IM_CERT",
45 "AUTHZ_SUBJECT_CERT",
46 "AUTHZ_CRL_VALIDATION",
47 "AUTHZ_OCSP_VALIDATION",
48 "AUTHZ_AC_GROUP",
49 );
50
51 typedef struct private_auth_info_t private_auth_info_t;
52
53 /**
54 * private data of item_set
55 */
56 struct private_auth_info_t {
57
58 /**
59 * public functions
60 */
61 auth_info_t public;
62
63 /**
64 * list of item_t's
65 */
66 linked_list_t *items;
67 };
68
69 typedef struct item_t item_t;
70
71 struct item_t {
72 /** type of this item */
73 auth_item_t type;
74 /** associated privlege value, if any */
75 void *value;
76 };
77
78 /**
79 * enumerator for auth_info_wrapper_t.create_cert_enumerator()
80 */
81 typedef struct {
82 /** implements enumerator_t */
83 enumerator_t public;
84 /** inner enumerator from linked_list_t */
85 enumerator_t *inner;
86 /** the current item */
87 item_t *item;
88 } item_enumerator_t;
89
90 /**
91 * enumerate function for item_enumerator_t
92 */
93 static bool enumerate(item_enumerator_t *this, auth_item_t *type, void **value)
94 {
95 if (this->inner->enumerate(this->inner, &this->item))
96 {
97 *type = this->item->type;
98 *value = this->item->value;
99 return TRUE;
100 }
101 return FALSE;
102 }
103
104 /**
105 * destroy function for item_enumerator_t
106 */
107 static void item_enumerator_destroy(item_enumerator_t *this)
108 {
109 this->inner->destroy(this->inner);
110 free(this);
111 }
112
113 /**
114 * Implementation of auth_info_t.create_item_enumerator.
115 */
116 static enumerator_t* create_item_enumerator(private_auth_info_t *this)
117 {
118 item_enumerator_t *enumerator;
119
120 enumerator = malloc_thing(item_enumerator_t);
121 enumerator->item = NULL;
122 enumerator->inner = this->items->create_enumerator(this->items);
123 enumerator->public.enumerate = (void*)enumerate;
124 enumerator->public.destroy = (void*)item_enumerator_destroy;
125 return &enumerator->public;
126 }
127
128 static void destroy_item_value(item_t *item);
129
130 /**
131 * Implementation of auth_info_t.replace_item.
132 */
133 static void replace_item(item_enumerator_t *enumerator, auth_item_t type, void *value)
134 {
135 destroy_item_value(enumerator->item);
136 enumerator->item->type = type;
137 enumerator->item->value = value;
138 }
139
140 /**
141 * Implementation of auth_info_t.get_item.
142 */
143 static bool get_item(private_auth_info_t *this, auth_item_t type, void** value)
144 {
145 enumerator_t *enumerator;
146 void *current_value;
147 auth_item_t current_type;
148 bool found = FALSE;
149
150 enumerator = create_item_enumerator(this);
151 while (enumerator->enumerate(enumerator, &current_type, &current_value))
152 {
153 if (type == current_type)
154 {
155 *value = current_value;
156 found = TRUE;
157 break;
158 }
159 }
160 enumerator->destroy(enumerator);
161 return found;
162 }
163
164 /**
165 * Implementation of auth_info_t.add_item.
166 */
167 static void add_item(private_auth_info_t *this, auth_item_t type, void *value)
168 {
169 item_t *item = malloc_thing(item_t);
170
171 item->type = type;
172 switch (type)
173 {
174 case AUTHZ_PUBKEY:
175 {
176 public_key_t *key = (public_key_t*)value;
177
178 item->value = key->get_ref(key);
179 break;
180 }
181 case AUTHZ_PSK:
182 {
183 shared_key_t *key = (shared_key_t*)value;
184
185 item->value = key->get_ref(key);
186 break;
187 }
188 case AUTHN_IM_HASH_URL:
189 case AUTHN_SUBJECT_HASH_URL:
190 {
191 item->value = strdup(value);
192 break;
193 }
194 case AUTHN_CA_CERT:
195 case AUTHN_IM_CERT:
196 case AUTHN_SUBJECT_CERT:
197 case AUTHZ_CA_CERT:
198 case AUTHZ_IM_CERT:
199 case AUTHZ_SUBJECT_CERT:
200 {
201 certificate_t *cert = (certificate_t*)value;
202
203 item->value = cert->get_ref(cert);
204 break;
205 }
206 case AUTHZ_CRL_VALIDATION:
207 case AUTHZ_OCSP_VALIDATION:
208 {
209 cert_validation_t *validation = malloc_thing(cert_validation_t);
210
211 *validation = *(cert_validation_t*)value;
212 item->value = validation;
213 break;
214 }
215 case AUTHN_AUTH_CLASS:
216 case AUTHN_EAP_TYPE:
217 case AUTHN_EAP_VENDOR:
218 case AUTHZ_EAP:
219 {
220 u_int *intval = malloc_thing(u_int);
221
222 *intval = *(u_int*)value;
223 item->value = intval;
224 break;
225 }
226 case AUTHN_EAP_IDENTITY:
227 case AUTHN_CA_CERT_KEYID:
228 case AUTHN_CA_CERT_NAME:
229 case AUTHZ_CA_CERT_NAME:
230 case AUTHZ_AC_GROUP:
231 {
232 identification_t *id = (identification_t*)value;
233
234 item->value = id->clone(id);
235 break;
236 }
237 }
238 this->items->insert_last(this->items, item);
239 }
240
241
242 /**
243 * Implementation of auth_info_t.complies.
244 */
245 static bool complies(private_auth_info_t *this, auth_info_t *constraints)
246 {
247 enumerator_t *enumerator;
248 bool success = TRUE;
249 auth_item_t t1, t2;
250 void *value;
251
252 enumerator = constraints->create_item_enumerator(constraints);
253 while (enumerator->enumerate(enumerator, &t1, &value))
254 {
255 switch (t1)
256 {
257 case AUTHN_AUTH_CLASS:
258 case AUTHN_EAP_TYPE:
259 case AUTHN_EAP_VENDOR:
260 case AUTHN_EAP_IDENTITY:
261 case AUTHN_CA_CERT_KEYID:
262 case AUTHN_CA_CERT:
263 case AUTHN_CA_CERT_NAME:
264 case AUTHN_IM_CERT:
265 case AUTHN_SUBJECT_CERT:
266 case AUTHN_IM_HASH_URL:
267 case AUTHN_SUBJECT_HASH_URL:
268 { /* skip non-authorization tokens */
269 continue;
270 }
271 case AUTHZ_CRL_VALIDATION:
272 case AUTHZ_OCSP_VALIDATION:
273 {
274 cert_validation_t *valid;
275
276 /* OCSP validation is also sufficient for CRL constraint, but
277 * not vice-versa */
278 if (!get_item(this, t1, (void**)&valid) &&
279 t1 == AUTHZ_CRL_VALIDATION &&
280 !get_item(this, AUTHZ_OCSP_VALIDATION, (void**)&valid))
281 {
282 DBG1(DBG_CFG, "constraint check failed: %N requires at "
283 "least %N, but no check done", auth_item_names, t1,
284 cert_validation_names, *(cert_validation_t*)value);
285 success = FALSE;
286 break;
287 }
288 switch (*(cert_validation_t*)value)
289 {
290 case VALIDATION_SKIPPED:
291 if (*valid == VALIDATION_SKIPPED)
292 {
293 break;
294 } /* FALL */
295 case VALIDATION_GOOD:
296 if (*valid == VALIDATION_GOOD)
297 {
298 break;
299 } /* FALL */
300 default:
301 DBG1(DBG_CFG, "constraint check failed: %N is %N, but "
302 "requires at least %N", auth_item_names, t1,
303 cert_validation_names, *valid,
304 cert_validation_names, *(cert_validation_t*)value);
305 success = FALSE;
306 break;
307 }
308 break;
309 }
310 case AUTHZ_CA_CERT:
311 {
312 enumerator_t *enumerator;
313 certificate_t *c1, *c2;
314
315 c1 = (certificate_t*)value;
316
317 success = FALSE;
318 enumerator = create_item_enumerator(this);
319 while (enumerator->enumerate(enumerator, &t2, &c2))
320 {
321 if ((t2 == AUTHZ_CA_CERT || t2 == AUTHZ_IM_CERT) &&
322 c1->equals(c1, c2))
323 {
324 success = TRUE;
325 }
326 }
327 enumerator->destroy(enumerator);
328 if (!success)
329 {
330 DBG1(DBG_CFG, "constraint check failed: peer not "
331 "authenticated by CA '%D'.", c1->get_subject(c1));
332 }
333 break;
334 }
335 case AUTHZ_CA_CERT_NAME:
336 {
337 enumerator_t *enumerator;
338 certificate_t *cert;
339 identification_t *id;
340
341 id = (identification_t*)value;
342 success = FALSE;
343 enumerator = create_item_enumerator(this);
344 while (enumerator->enumerate(enumerator, &t2, &cert))
345 {
346 if ((t2 == AUTHZ_CA_CERT || t2 == AUTHZ_IM_CERT) &&
347 cert->has_subject(cert, id))
348 {
349 success = TRUE;
350 }
351 }
352 enumerator->destroy(enumerator);
353 if (!success)
354 {
355 DBG1(DBG_CFG, "constraint check failed: peer not "
356 "authenticated by CA '%D'.", id);
357 }
358 break;
359 }
360 case AUTHZ_PUBKEY:
361 case AUTHZ_PSK:
362 case AUTHZ_IM_CERT:
363 case AUTHZ_SUBJECT_CERT:
364 case AUTHZ_EAP:
365 case AUTHZ_AC_GROUP:
366 {
367 DBG1(DBG_CFG, "constraint check %N not implemented!",
368 auth_item_names, t1);
369 success = FALSE;
370 break;
371 }
372 }
373 if (!success)
374 {
375 break;
376 }
377 }
378 enumerator->destroy(enumerator);
379 return success;
380 }
381
382 /**
383 * Implementation of auth_info_t.merge.
384 */
385 static void merge(private_auth_info_t *this, private_auth_info_t *other)
386 {
387 item_t *item;
388
389 while (other->items->remove_first(other->items, (void**)&item) == SUCCESS)
390 {
391 this->items->insert_last(this->items, item);
392 }
393 }
394
395 /**
396 * Implementation of auth_info_t.equals.
397 */
398 static bool equals(private_auth_info_t *this, private_auth_info_t *other)
399 {
400 enumerator_t *e1, *e2;
401 item_t *i1, *i2;
402 bool equal = TRUE, found;
403
404 e1 = this->items->create_enumerator(this->items);
405 while (e1->enumerate(e1, &i1))
406 {
407 found = FALSE;
408 e2 = other->items->create_enumerator(other->items);
409 while (e2->enumerate(e2, &i2))
410 {
411 if (i1->type == i2->type)
412 {
413 switch (i1->type)
414 {
415 case AUTHZ_CRL_VALIDATION:
416 case AUTHZ_OCSP_VALIDATION:
417 {
418 cert_validation_t c1, c2;
419
420 c1 = *(cert_validation_t*)i1->value;
421 c2 = *(cert_validation_t*)i2->value;
422
423 if (c1 == c2)
424 {
425 found = TRUE;
426 break;
427 }
428 continue;
429 }
430 case AUTHN_IM_HASH_URL:
431 case AUTHN_SUBJECT_HASH_URL:
432 {
433 if (streq(i1->value, i2->value))
434 {
435 found = TRUE;
436 break;
437 }
438 continue;
439 }
440 case AUTHN_CA_CERT:
441 case AUTHN_IM_CERT:
442 case AUTHN_SUBJECT_CERT:
443 case AUTHZ_CA_CERT:
444 case AUTHZ_IM_CERT:
445 case AUTHZ_SUBJECT_CERT:
446 {
447 certificate_t *c1, *c2;
448
449 c1 = (certificate_t*)i1->value;
450 c2 = (certificate_t*)i2->value;
451
452 if (c1->equals(c1, c2))
453 {
454 found = TRUE;
455 break;
456 }
457 continue;
458 }
459 case AUTHN_EAP_IDENTITY:
460 case AUTHN_CA_CERT_KEYID:
461 case AUTHN_CA_CERT_NAME:
462 case AUTHZ_CA_CERT_NAME:
463 {
464 identification_t *c1, *c2;
465
466 c1 = (identification_t*)i1->value;
467 c2 = (identification_t*)i2->value;
468
469 if (c1->equals(c1, c2))
470 {
471 found = TRUE;
472 break;
473 }
474 continue;
475 }
476 case AUTHN_AUTH_CLASS:
477 case AUTHN_EAP_TYPE:
478 case AUTHN_EAP_VENDOR:
479 {
480 if (*(u_int*)i1->value == *(u_int*)i2->value)
481 {
482 found = TRUE;
483 break;
484 }
485 }
486 case AUTHZ_PUBKEY:
487 case AUTHZ_PSK:
488 case AUTHZ_EAP:
489 case AUTHZ_AC_GROUP:
490 /* TODO: implement value comparison */
491 break;
492 }
493 break;
494 }
495 }
496 e2->destroy(e2);
497 if (!found)
498 {
499 equal = FALSE;
500 break;
501 }
502 }
503 e1->destroy(e1);
504 return equal;
505 }
506
507 /**
508 * Destroy the value associated with an item
509 */
510 static void destroy_item_value(item_t *item)
511 {
512 switch (item->type)
513 {
514 case AUTHZ_PUBKEY:
515 {
516 public_key_t *key = (public_key_t*)item->value;
517 key->destroy(key);
518 break;
519 }
520 case AUTHZ_PSK:
521 {
522 shared_key_t *key = (shared_key_t*)item->value;
523 key->destroy(key);
524 break;
525 }
526 case AUTHN_CA_CERT:
527 case AUTHN_IM_CERT:
528 case AUTHN_SUBJECT_CERT:
529 case AUTHZ_CA_CERT:
530 case AUTHZ_IM_CERT:
531 case AUTHZ_SUBJECT_CERT:
532 {
533 certificate_t *cert = (certificate_t*)item->value;
534 cert->destroy(cert);
535 break;
536 }
537 case AUTHN_AUTH_CLASS:
538 case AUTHN_EAP_TYPE:
539 case AUTHN_EAP_VENDOR:
540 case AUTHN_IM_HASH_URL:
541 case AUTHN_SUBJECT_HASH_URL:
542 case AUTHZ_CRL_VALIDATION:
543 case AUTHZ_OCSP_VALIDATION:
544 case AUTHZ_EAP:
545 {
546 free(item->value);
547 break;
548 }
549 case AUTHN_EAP_IDENTITY:
550 case AUTHN_CA_CERT_KEYID:
551 case AUTHN_CA_CERT_NAME:
552 case AUTHZ_CA_CERT_NAME:
553 case AUTHZ_AC_GROUP:
554 {
555 identification_t *id = (identification_t*)item->value;
556 id->destroy(id);
557 break;
558 }
559 }
560 }
561
562 /**
563 * Implementation of auth_info_t.destroy
564 */
565 static void destroy(private_auth_info_t *this)
566 {
567 item_t *item;
568
569 while (this->items->remove_last(this->items, (void**)&item) == SUCCESS)
570 {
571 destroy_item_value(item);
572 free(item);
573 }
574 this->items->destroy(this->items);
575 free(this);
576 }
577
578 /*
579 * see header file
580 */
581 auth_info_t *auth_info_create()
582 {
583 private_auth_info_t *this = malloc_thing(private_auth_info_t);
584
585 this->public.add_item = (void(*)(auth_info_t*, auth_item_t type, void *value))add_item;
586 this->public.get_item = (bool(*)(auth_info_t*, auth_item_t type, void **value))get_item;
587 this->public.replace_item = (void(*)(enumerator_t*,auth_item_t,void*))replace_item;
588 this->public.create_item_enumerator = (enumerator_t*(*)(auth_info_t*))create_item_enumerator;
589 this->public.complies = (bool(*)(auth_info_t*, auth_info_t *))complies;
590 this->public.merge = (void(*)(auth_info_t*, auth_info_t *other))merge;
591 this->public.equals = (bool(*)(auth_info_t*, auth_info_t *other))equals;
592 this->public.destroy = (void(*)(auth_info_t*))destroy;
593
594 this->items = linked_list_create();
595
596 return &this->public;
597 }
598