added EAP_TTLS method
[strongswan.git] / src / libstrongswan / credentials / auth_cfg.c
1 /*
2 * Copyright (C) 2007-2009 Martin Willi
3 * Copyright (C) 2008 Tobias Brunner
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
17 #include "auth_cfg.h"
18
19 #include <library.h>
20 #include <debug.h>
21 #include <utils/linked_list.h>
22 #include <utils/identification.h>
23 #include <credentials/certificates/certificate.h>
24
25 ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP,
26 "any",
27 "public key",
28 "pre-shared key",
29 "EAP",
30 );
31
32 ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_GTC,
33 "EAP_IDENTITY",
34 "EAP_NOTIFICATION",
35 "EAP_NAK",
36 "EAP_MD5",
37 "EAP_OTP",
38 "EAP_GTC");
39 ENUM_NEXT(eap_type_names, EAP_TLS, EAP_TLS, EAP_GTC,
40 "EAP_TLS");
41 ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_TLS,
42 "EAP_SIM");
43 ENUM_NEXT(eap_type_names, EAP_TTLS, EAP_TTLS, EAP_SIM,
44 "EAP_TTLS");
45 ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_TTLS,
46 "EAP_AKA");
47 ENUM_NEXT(eap_type_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
48 "EAP_MSCHAPV2");
49 ENUM_NEXT(eap_type_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
50 "EAP_RADIUS",
51 "EAP_EXPANDED",
52 "EAP_EXPERIMENTAL");
53 ENUM_END(eap_type_names, EAP_EXPERIMENTAL);
54
55 ENUM_BEGIN(eap_type_short_names, EAP_IDENTITY, EAP_GTC,
56 "ID",
57 "NTF",
58 "NAK",
59 "MD5",
60 "OTP",
61 "GTC");
62 ENUM_NEXT(eap_type_short_names, EAP_TLS, EAP_TLS, EAP_GTC,
63 "TLS");
64 ENUM_NEXT(eap_type_short_names, EAP_SIM, EAP_SIM, EAP_TLS,
65 "SIM");
66 ENUM_NEXT(eap_type_short_names, EAP_AKA, EAP_AKA, EAP_SIM,
67 "AKA");
68 ENUM_NEXT(eap_type_short_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
69 "MSCHAPV2");
70 ENUM_NEXT(eap_type_short_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
71 "RAD",
72 "EXP",
73 "XP");
74 ENUM_END(eap_type_short_names, EAP_EXPERIMENTAL);
75
76 ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_SUBJECT_HASH_URL,
77 "RULE_IDENTITY",
78 "RULE_AUTH_CLASS",
79 "RULE_EAP_IDENTITY",
80 "RULE_EAP_TYPE",
81 "RULE_EAP_VENDOR",
82 "RULE_CA_CERT",
83 "RULE_IM_CERT",
84 "RULE_SUBJECT_CERT",
85 "RULE_CRL_VALIDATION",
86 "RULE_OCSP_VALIDATION",
87 "RULE_GROUP",
88 "HELPER_IM_CERT",
89 "HELPER_SUBJECT_CERT",
90 "HELPER_IM_HASH_URL",
91 "HELPER_SUBJECT_HASH_URL",
92 );
93
94 typedef struct private_auth_cfg_t private_auth_cfg_t;
95
96 /**
97 * private data of item_set
98 */
99 struct private_auth_cfg_t {
100
101 /**
102 * public functions
103 */
104 auth_cfg_t public;
105
106 /**
107 * list of entry_t
108 */
109 linked_list_t *entries;
110 };
111
112 typedef struct entry_t entry_t;
113
114 struct entry_t {
115 /** rule type */
116 auth_rule_t type;
117 /** associated value */
118 void *value;
119 };
120
121 /**
122 * enumerator for auth_cfg_t.create_enumerator()
123 */
124 typedef struct {
125 /** implements enumerator_t */
126 enumerator_t public;
127 /** inner enumerator from linked_list_t */
128 enumerator_t *inner;
129 /** current entry */
130 entry_t *current;
131 } entry_enumerator_t;
132
133 /**
134 * enumerate function for item_enumerator_t
135 */
136 static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value)
137 {
138 entry_t *entry;
139
140 if (this->inner->enumerate(this->inner, &entry))
141 {
142 this->current = entry;
143 *type = entry->type;
144 *value = entry->value;
145 return TRUE;
146 }
147 return FALSE;
148 }
149
150 /**
151 * destroy function for item_enumerator_t
152 */
153 static void entry_enumerator_destroy(entry_enumerator_t *this)
154 {
155 this->inner->destroy(this->inner);
156 free(this);
157 }
158
159 /**
160 * Implementation of auth_cfg_t.create_enumerator.
161 */
162 static enumerator_t* create_enumerator(private_auth_cfg_t *this)
163 {
164 entry_enumerator_t *enumerator;
165
166 enumerator = malloc_thing(entry_enumerator_t);
167 enumerator->inner = this->entries->create_enumerator(this->entries);
168 enumerator->public.enumerate = (void*)enumerate;
169 enumerator->public.destroy = (void*)entry_enumerator_destroy;
170 enumerator->current = NULL;
171 return &enumerator->public;
172 }
173
174 /**
175 * Destroy the value associated with an entry
176 */
177 static void destroy_entry_value(entry_t *entry)
178 {
179 switch (entry->type)
180 {
181 case AUTH_RULE_IDENTITY:
182 case AUTH_RULE_EAP_IDENTITY:
183 case AUTH_RULE_GROUP:
184 {
185 identification_t *id = (identification_t*)entry->value;
186 id->destroy(id);
187 break;
188 }
189 case AUTH_RULE_CA_CERT:
190 case AUTH_RULE_IM_CERT:
191 case AUTH_RULE_SUBJECT_CERT:
192 case AUTH_HELPER_IM_CERT:
193 case AUTH_HELPER_SUBJECT_CERT:
194 {
195 certificate_t *cert = (certificate_t*)entry->value;
196 cert->destroy(cert);
197 break;
198 }
199 case AUTH_HELPER_IM_HASH_URL:
200 case AUTH_HELPER_SUBJECT_HASH_URL:
201 {
202 free(entry->value);
203 break;
204 }
205 case AUTH_RULE_AUTH_CLASS:
206 case AUTH_RULE_EAP_TYPE:
207 case AUTH_RULE_EAP_VENDOR:
208 case AUTH_RULE_CRL_VALIDATION:
209 case AUTH_RULE_OCSP_VALIDATION:
210 break;
211 }
212 }
213
214 /**
215 * Implementation of auth_cfg_t.replace.
216 */
217 static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator,
218 auth_rule_t type, ...)
219 {
220 if (enumerator->current)
221 {
222 va_list args;
223
224 va_start(args, type);
225
226 destroy_entry_value(enumerator->current);
227 enumerator->current->type = type;
228 switch (type)
229 {
230 case AUTH_RULE_AUTH_CLASS:
231 case AUTH_RULE_EAP_TYPE:
232 case AUTH_RULE_EAP_VENDOR:
233 case AUTH_RULE_CRL_VALIDATION:
234 case AUTH_RULE_OCSP_VALIDATION:
235 /* integer type */
236 enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int);
237 break;
238 case AUTH_RULE_IDENTITY:
239 case AUTH_RULE_EAP_IDENTITY:
240 case AUTH_RULE_GROUP:
241 case AUTH_RULE_CA_CERT:
242 case AUTH_RULE_IM_CERT:
243 case AUTH_RULE_SUBJECT_CERT:
244 case AUTH_HELPER_IM_CERT:
245 case AUTH_HELPER_SUBJECT_CERT:
246 case AUTH_HELPER_IM_HASH_URL:
247 case AUTH_HELPER_SUBJECT_HASH_URL:
248 /* pointer type */
249 enumerator->current->value = va_arg(args, void*);
250 break;
251 }
252 va_end(args);
253 }
254 }
255
256 /**
257 * Implementation of auth_cfg_t.get.
258 */
259 static void* get(private_auth_cfg_t *this, auth_rule_t type)
260 {
261 enumerator_t *enumerator;
262 void *current_value, *best_value = NULL;
263 auth_rule_t current_type;
264 bool found = FALSE;
265
266 enumerator = create_enumerator(this);
267 while (enumerator->enumerate(enumerator, &current_type, &current_value))
268 {
269 if (type == current_type)
270 {
271 if (type == AUTH_RULE_CRL_VALIDATION ||
272 type == AUTH_RULE_OCSP_VALIDATION)
273 { /* for CRL/OCSP validation, always get() the highest value */
274 if (!found || current_value > best_value)
275 {
276 best_value = current_value;
277 }
278 found = TRUE;
279 continue;
280 }
281 best_value = current_value;
282 found = TRUE;
283 break;
284 }
285 }
286 enumerator->destroy(enumerator);
287 if (found)
288 {
289 return best_value;
290 }
291 switch (type)
292 {
293 /* use some sane defaults if we don't find an entry */
294 case AUTH_RULE_AUTH_CLASS:
295 return (void*)AUTH_CLASS_ANY;
296 case AUTH_RULE_EAP_TYPE:
297 return (void*)EAP_NAK;
298 case AUTH_RULE_EAP_VENDOR:
299 return (void*)0;
300 case AUTH_RULE_CRL_VALIDATION:
301 case AUTH_RULE_OCSP_VALIDATION:
302 return (void*)VALIDATION_FAILED;
303 case AUTH_RULE_IDENTITY:
304 case AUTH_RULE_EAP_IDENTITY:
305 case AUTH_RULE_GROUP:
306 case AUTH_RULE_CA_CERT:
307 case AUTH_RULE_IM_CERT:
308 case AUTH_RULE_SUBJECT_CERT:
309 case AUTH_HELPER_IM_CERT:
310 case AUTH_HELPER_SUBJECT_CERT:
311 case AUTH_HELPER_IM_HASH_URL:
312 case AUTH_HELPER_SUBJECT_HASH_URL:
313 default:
314 return NULL;
315 }
316 }
317
318 /**
319 * Implementation of auth_cfg_t.add.
320 */
321 static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
322 {
323 entry_t *entry = malloc_thing(entry_t);
324 va_list args;
325
326 va_start(args, type);
327 entry->type = type;
328 switch (type)
329 {
330 case AUTH_RULE_AUTH_CLASS:
331 case AUTH_RULE_EAP_TYPE:
332 case AUTH_RULE_EAP_VENDOR:
333 case AUTH_RULE_CRL_VALIDATION:
334 case AUTH_RULE_OCSP_VALIDATION:
335 /* integer type */
336 entry->value = (void*)(uintptr_t)va_arg(args, u_int);
337 break;
338 case AUTH_RULE_IDENTITY:
339 case AUTH_RULE_EAP_IDENTITY:
340 case AUTH_RULE_GROUP:
341 case AUTH_RULE_CA_CERT:
342 case AUTH_RULE_IM_CERT:
343 case AUTH_RULE_SUBJECT_CERT:
344 case AUTH_HELPER_IM_CERT:
345 case AUTH_HELPER_SUBJECT_CERT:
346 case AUTH_HELPER_IM_HASH_URL:
347 case AUTH_HELPER_SUBJECT_HASH_URL:
348 /* pointer type */
349 entry->value = va_arg(args, void*);
350 break;
351 }
352 va_end(args);
353 this->entries->insert_last(this->entries, entry);
354 }
355
356 /**
357 * Implementation of auth_cfg_t.complies.
358 */
359 static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints,
360 bool log_error)
361 {
362 enumerator_t *e1, *e2;
363 bool success = TRUE, has_group = FALSE, group_match = FALSE;
364 auth_rule_t t1, t2;
365 void *value;
366
367 e1 = constraints->create_enumerator(constraints);
368 while (e1->enumerate(e1, &t1, &value))
369 {
370 switch (t1)
371 {
372 case AUTH_RULE_CA_CERT:
373 case AUTH_RULE_IM_CERT:
374 {
375 certificate_t *c1, *c2;
376
377 c1 = (certificate_t*)value;
378
379 success = FALSE;
380 e2 = create_enumerator(this);
381 while (e2->enumerate(e2, &t2, &c2))
382 {
383 if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
384 c1->equals(c1, c2))
385 {
386 success = TRUE;
387 }
388 }
389 e2->destroy(e2);
390 if (!success && log_error)
391 {
392 DBG1(DBG_CFG, "constraint check failed: peer not "
393 "authenticated by CA '%Y'.", c1->get_subject(c1));
394 }
395 break;
396 }
397 case AUTH_RULE_SUBJECT_CERT:
398 {
399 certificate_t *c1, *c2;
400
401 c1 = (certificate_t*)value;
402 c2 = get(this, AUTH_RULE_SUBJECT_CERT);
403 if (!c2 || !c1->equals(c1, c2))
404 {
405 success = FALSE;
406 if (log_error)
407 {
408 DBG1(DBG_CFG, "constraint check failed: peer not "
409 "authenticated with peer cert '%Y'.",
410 c1->get_subject(c1));
411 }
412 }
413 break;
414 }
415 case AUTH_RULE_CRL_VALIDATION:
416 case AUTH_RULE_OCSP_VALIDATION:
417 {
418 cert_validation_t validated, required;
419
420 required = (uintptr_t)value;
421 validated = (uintptr_t)get(this, t1);
422 switch (required)
423 {
424 case VALIDATION_FAILED:
425 /* no constraint */
426 break;
427 case VALIDATION_SKIPPED:
428 if (validated == VALIDATION_SKIPPED)
429 {
430 break;
431 }
432 /* FALL */
433 case VALIDATION_GOOD:
434 if (validated == VALIDATION_GOOD)
435 {
436 break;
437 }
438 /* FALL */
439 default:
440 success = FALSE;
441 if (log_error)
442 {
443 DBG1(DBG_CFG, "constraint check failed: %N is %N, "
444 "but requires at least %N", auth_rule_names,
445 t1, cert_validation_names, validated,
446 cert_validation_names, required);
447 }
448 break;
449 }
450 break;
451 }
452 case AUTH_RULE_IDENTITY:
453 case AUTH_RULE_EAP_IDENTITY:
454 {
455 identification_t *id1, *id2;
456
457 id1 = (identification_t*)value;
458 id2 = get(this, t1);
459 if (!id2 || !id2->matches(id2, id1))
460 {
461 success = FALSE;
462 if (log_error)
463 {
464 DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
465 " required ", t1 == AUTH_RULE_IDENTITY ? "" :
466 "EAP ", id1);
467 }
468 }
469 break;
470 }
471 case AUTH_RULE_AUTH_CLASS:
472 {
473 if ((uintptr_t)value != AUTH_CLASS_ANY &&
474 (uintptr_t)value != (uintptr_t)get(this, t1))
475 {
476 success = FALSE;
477 if (log_error)
478 {
479 DBG1(DBG_CFG, "constraint requires %N authentication, "
480 "but %N was used", auth_class_names, (uintptr_t)value,
481 auth_class_names, (uintptr_t)get(this, t1));
482 }
483 }
484 break;
485 }
486 case AUTH_RULE_EAP_TYPE:
487 {
488 if ((uintptr_t)value != (uintptr_t)get(this, t1))
489 {
490 success = FALSE;
491 if (log_error)
492 {
493 DBG1(DBG_CFG, "constraint requires %N, "
494 "but %N was used", eap_type_names, (uintptr_t)value,
495 eap_type_names, (uintptr_t)get(this, t1));
496 }
497 }
498 break;
499 }
500 case AUTH_RULE_EAP_VENDOR:
501 {
502 if ((uintptr_t)value != (uintptr_t)get(this, t1))
503 {
504 success = FALSE;
505 if (log_error)
506 {
507 DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
508 "but %d was used", (uintptr_t)value,
509 (uintptr_t)get(this, t1));
510 }
511 }
512 break;
513 }
514 case AUTH_RULE_GROUP:
515 {
516 identification_t *id1, *id2;
517
518 /* for groups, a match of a single group is sufficient */
519 has_group = TRUE;
520 id1 = (identification_t*)value;
521 e2 = create_enumerator(this);
522 while (e2->enumerate(e2, &t2, &id2))
523 {
524 if (t2 == AUTH_RULE_GROUP && id2->matches(id2, id1))
525 {
526 group_match = TRUE;
527 }
528 }
529 e2->destroy(e2);
530 break;
531 }
532 case AUTH_HELPER_IM_CERT:
533 case AUTH_HELPER_SUBJECT_CERT:
534 case AUTH_HELPER_IM_HASH_URL:
535 case AUTH_HELPER_SUBJECT_HASH_URL:
536 /* skip helpers */
537 continue;
538 }
539 if (!success)
540 {
541 break;
542 }
543 }
544 e1->destroy(e1);
545
546 if (has_group && !group_match)
547 {
548 if (log_error)
549 {
550 DBG1(DBG_CFG, "constraint check failed: group membership required");
551 }
552 return FALSE;
553 }
554 return success;
555 }
556
557 /**
558 * Implementation of auth_cfg_t.merge.
559 */
560 static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
561 {
562 if (!other)
563 { /* nothing to merge */
564 return;
565 }
566 if (copy)
567 {
568 enumerator_t *enumerator;
569 auth_rule_t type;
570 void *value;
571
572 enumerator = create_enumerator(other);
573 while (enumerator->enumerate(enumerator, &type, &value))
574 {
575 switch (type)
576 {
577 case AUTH_RULE_CA_CERT:
578 case AUTH_RULE_IM_CERT:
579 case AUTH_RULE_SUBJECT_CERT:
580 case AUTH_HELPER_IM_CERT:
581 case AUTH_HELPER_SUBJECT_CERT:
582 {
583 certificate_t *cert = (certificate_t*)value;
584
585 add(this, type, cert->get_ref(cert));
586 break;
587 }
588 case AUTH_RULE_CRL_VALIDATION:
589 case AUTH_RULE_OCSP_VALIDATION:
590 case AUTH_RULE_AUTH_CLASS:
591 case AUTH_RULE_EAP_TYPE:
592 case AUTH_RULE_EAP_VENDOR:
593 {
594 add(this, type, (uintptr_t)value);
595 break;
596 }
597 case AUTH_RULE_IDENTITY:
598 case AUTH_RULE_EAP_IDENTITY:
599 case AUTH_RULE_GROUP:
600 {
601 identification_t *id = (identification_t*)value;
602
603 add(this, type, id->clone(id));
604 break;
605 }
606 case AUTH_HELPER_IM_HASH_URL:
607 case AUTH_HELPER_SUBJECT_HASH_URL:
608 {
609 add(this, type, strdup((char*)value));
610 break;
611 }
612 }
613 }
614 enumerator->destroy(enumerator);
615 }
616 else
617 {
618 entry_t *entry;
619
620 while (other->entries->remove_first(other->entries,
621 (void**)&entry) == SUCCESS)
622 {
623 this->entries->insert_last(this->entries, entry);
624 }
625 }
626 }
627
628 /**
629 * Implementation of auth_cfg_t.equals.
630 */
631 static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
632 {
633 enumerator_t *e1, *e2;
634 entry_t *i1, *i2;
635 bool equal = TRUE, found;
636
637 if (this->entries->get_count(this->entries) !=
638 other->entries->get_count(other->entries))
639 {
640 return FALSE;
641 }
642 e1 = this->entries->create_enumerator(this->entries);
643 while (e1->enumerate(e1, &i1))
644 {
645 found = FALSE;
646 e2 = other->entries->create_enumerator(other->entries);
647 while (e2->enumerate(e2, &i2))
648 {
649 if (i1->type == i2->type)
650 {
651 switch (i1->type)
652 {
653 case AUTH_RULE_AUTH_CLASS:
654 case AUTH_RULE_EAP_TYPE:
655 case AUTH_RULE_EAP_VENDOR:
656 case AUTH_RULE_CRL_VALIDATION:
657 case AUTH_RULE_OCSP_VALIDATION:
658 {
659 if (i1->value == i2->value)
660 {
661 found = TRUE;
662 break;
663 }
664 continue;
665 }
666 case AUTH_RULE_CA_CERT:
667 case AUTH_RULE_IM_CERT:
668 case AUTH_RULE_SUBJECT_CERT:
669 case AUTH_HELPER_IM_CERT:
670 case AUTH_HELPER_SUBJECT_CERT:
671 {
672 certificate_t *c1, *c2;
673
674 c1 = (certificate_t*)i1->value;
675 c2 = (certificate_t*)i2->value;
676
677 if (c1->equals(c1, c2))
678 {
679 found = TRUE;
680 break;
681 }
682 continue;
683 }
684 case AUTH_RULE_IDENTITY:
685 case AUTH_RULE_EAP_IDENTITY:
686 case AUTH_RULE_GROUP:
687 {
688 identification_t *id1, *id2;
689
690 id1 = (identification_t*)i1->value;
691 id2 = (identification_t*)i2->value;
692
693 if (id1->equals(id1, id2))
694 {
695 found = TRUE;
696 break;
697 }
698 continue;
699 }
700 case AUTH_HELPER_IM_HASH_URL:
701 case AUTH_HELPER_SUBJECT_HASH_URL:
702 {
703 if (streq(i1->value, i2->value))
704 {
705 found = TRUE;
706 break;
707 }
708 continue;
709 }
710 }
711 break;
712 }
713 }
714 e2->destroy(e2);
715 if (!found)
716 {
717 equal = FALSE;
718 break;
719 }
720 }
721 e1->destroy(e1);
722 return equal;
723 }
724
725 /**
726 * Implementation of auth_cfg_t.purge
727 */
728 static void purge(private_auth_cfg_t *this, bool keep_ca)
729 {
730 entry_t *entry;
731 linked_list_t *cas;
732
733 cas = linked_list_create();
734 while (this->entries->remove_last(this->entries, (void**)&entry) == SUCCESS)
735 {
736 if (keep_ca && entry->type == AUTH_RULE_CA_CERT)
737 {
738 cas->insert_first(cas, entry);
739 }
740 else
741 {
742 destroy_entry_value(entry);
743 free(entry);
744 }
745 }
746 while (cas->remove_last(cas, (void**)&entry) == SUCCESS)
747 {
748 this->entries->insert_first(this->entries, entry);
749 }
750 cas->destroy(cas);
751 }
752
753 /**
754 * Implementation of auth_cfg_t.clone
755 */
756 static auth_cfg_t* clone_(private_auth_cfg_t *this)
757 {
758 enumerator_t *enumerator;
759 auth_cfg_t *clone;
760 entry_t *entry;
761
762 clone = auth_cfg_create();
763 enumerator = this->entries->create_enumerator(this->entries);
764 while (enumerator->enumerate(enumerator, &entry))
765 {
766 switch (entry->type)
767 {
768 case AUTH_RULE_IDENTITY:
769 case AUTH_RULE_EAP_IDENTITY:
770 case AUTH_RULE_GROUP:
771 {
772 identification_t *id = (identification_t*)entry->value;
773 clone->add(clone, entry->type, id->clone(id));
774 break;
775 }
776 case AUTH_RULE_CA_CERT:
777 case AUTH_RULE_IM_CERT:
778 case AUTH_RULE_SUBJECT_CERT:
779 case AUTH_HELPER_IM_CERT:
780 case AUTH_HELPER_SUBJECT_CERT:
781 {
782 certificate_t *cert = (certificate_t*)entry->value;
783 clone->add(clone, entry->type, cert->get_ref(cert));
784 break;
785 }
786 case AUTH_HELPER_IM_HASH_URL:
787 case AUTH_HELPER_SUBJECT_HASH_URL:
788 {
789 clone->add(clone, entry->type, strdup(entry->value));
790 break;
791 }
792 case AUTH_RULE_AUTH_CLASS:
793 case AUTH_RULE_EAP_TYPE:
794 case AUTH_RULE_EAP_VENDOR:
795 case AUTH_RULE_CRL_VALIDATION:
796 case AUTH_RULE_OCSP_VALIDATION:
797 clone->add(clone, entry->type, (uintptr_t)entry->value);
798 break;
799 }
800 }
801 enumerator->destroy(enumerator);
802 return clone;
803 }
804
805 /**
806 * Implementation of auth_cfg_t.destroy
807 */
808 static void destroy(private_auth_cfg_t *this)
809 {
810 purge(this, FALSE);
811 this->entries->destroy(this->entries);
812 free(this);
813 }
814
815 /*
816 * see header file
817 */
818 auth_cfg_t *auth_cfg_create()
819 {
820 private_auth_cfg_t *this = malloc_thing(private_auth_cfg_t);
821
822 this->public.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add;
823 this->public.get = (void*(*)(auth_cfg_t*, auth_rule_t type))get;
824 this->public.create_enumerator = (enumerator_t*(*)(auth_cfg_t*))create_enumerator;
825 this->public.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace;
826 this->public.complies = (bool(*)(auth_cfg_t*, auth_cfg_t *,bool))complies;
827 this->public.merge = (void(*)(auth_cfg_t*, auth_cfg_t *other,bool))merge;
828 this->public.purge = (void(*)(auth_cfg_t*,bool))purge;
829 this->public.equals = (bool(*)(auth_cfg_t*, auth_cfg_t *other))equals;
830 this->public.clone = (auth_cfg_t*(*)(auth_cfg_t*))clone_;
831 this->public.destroy = (void(*)(auth_cfg_t*))destroy;
832
833 this->entries = linked_list_create();
834
835 return &this->public;
836 }