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