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