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