daemon: Flush shunts before unloading plugins
[strongswan.git] / src / libstrongswan / credentials / auth_cfg.c
1 /*
2 * Copyright (C) 2008-2015 Tobias Brunner
3 * Copyright (C) 2007-2009 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
17 #include "auth_cfg.h"
18
19 #include <library.h>
20 #include <utils/debug.h>
21 #include <collections/array.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_AC_CERT,
35 "RULE_IDENTITY",
36 "RULE_IDENTITY_LOOSE",
37 "RULE_AUTH_CLASS",
38 "RULE_AAA_IDENTITY",
39 "RULE_EAP_IDENTITY",
40 "RULE_EAP_TYPE",
41 "RULE_EAP_VENDOR",
42 "RULE_XAUTH_BACKEND",
43 "RULE_XAUTH_IDENTITY",
44 "RULE_CA_CERT",
45 "RULE_IM_CERT",
46 "RULE_SUBJECT_CERT",
47 "RULE_CRL_VALIDATION",
48 "RULE_OCSP_VALIDATION",
49 "RULE_GROUP",
50 "RULE_RSA_STRENGTH",
51 "RULE_ECDSA_STRENGTH",
52 "RULE_BLISS_STRENGTH",
53 "RULE_SIGNATURE_SCHEME",
54 "RULE_CERT_POLICY",
55 "HELPER_IM_CERT",
56 "HELPER_SUBJECT_CERT",
57 "HELPER_IM_HASH_URL",
58 "HELPER_SUBJECT_HASH_URL",
59 "HELPER_REVOCATION_CERT",
60 "HELPER_AC_CERT",
61 );
62
63 /**
64 * Check if the given rule is a rule for which there may be multiple values.
65 */
66 static inline bool is_multi_value_rule(auth_rule_t type)
67 {
68 switch (type)
69 {
70 case AUTH_RULE_AUTH_CLASS:
71 case AUTH_RULE_EAP_TYPE:
72 case AUTH_RULE_EAP_VENDOR:
73 case AUTH_RULE_RSA_STRENGTH:
74 case AUTH_RULE_ECDSA_STRENGTH:
75 case AUTH_RULE_BLISS_STRENGTH:
76 case AUTH_RULE_IDENTITY:
77 case AUTH_RULE_IDENTITY_LOOSE:
78 case AUTH_RULE_EAP_IDENTITY:
79 case AUTH_RULE_AAA_IDENTITY:
80 case AUTH_RULE_XAUTH_IDENTITY:
81 case AUTH_RULE_XAUTH_BACKEND:
82 case AUTH_HELPER_SUBJECT_CERT:
83 case AUTH_HELPER_SUBJECT_HASH_URL:
84 case AUTH_RULE_MAX:
85 return FALSE;
86 case AUTH_RULE_OCSP_VALIDATION:
87 case AUTH_RULE_CRL_VALIDATION:
88 case AUTH_RULE_GROUP:
89 case AUTH_RULE_SUBJECT_CERT:
90 case AUTH_RULE_CA_CERT:
91 case AUTH_RULE_IM_CERT:
92 case AUTH_RULE_CERT_POLICY:
93 case AUTH_RULE_SIGNATURE_SCHEME:
94 case AUTH_HELPER_IM_CERT:
95 case AUTH_HELPER_IM_HASH_URL:
96 case AUTH_HELPER_REVOCATION_CERT:
97 case AUTH_HELPER_AC_CERT:
98 return TRUE;
99 }
100 return FALSE;
101 }
102
103 typedef struct private_auth_cfg_t private_auth_cfg_t;
104
105 /**
106 * private data of item_set
107 */
108 struct private_auth_cfg_t {
109
110 /**
111 * public functions
112 */
113 auth_cfg_t public;
114
115 /**
116 * Array of entry_t
117 */
118 array_t *entries;
119 };
120
121 typedef struct entry_t entry_t;
122
123 struct entry_t {
124 /** rule type */
125 auth_rule_t type;
126 /** associated value */
127 void *value;
128 };
129
130 /**
131 * enumerator for auth_cfg_t.create_enumerator()
132 */
133 typedef struct {
134 /** implements enumerator_t */
135 enumerator_t public;
136 /** inner enumerator from linked_list_t */
137 enumerator_t *inner;
138 /** current entry */
139 entry_t *current;
140 /** types we have already enumerated */
141 bool enumerated[AUTH_RULE_MAX];
142 } entry_enumerator_t;
143
144 /**
145 * enumerate function for item_enumerator_t
146 */
147 static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value)
148 {
149 entry_t *entry;
150
151 while (this->inner->enumerate(this->inner, &entry))
152 {
153 if (!is_multi_value_rule(entry->type) && this->enumerated[entry->type])
154 {
155 continue;
156 }
157 this->enumerated[entry->type] = TRUE;
158 this->current = entry;
159 if (type)
160 {
161 *type = entry->type;
162 }
163 if (value)
164 {
165 *value = entry->value;
166 }
167 return TRUE;
168 }
169 return FALSE;
170 }
171
172 /**
173 * destroy function for item_enumerator_t
174 */
175 static void entry_enumerator_destroy(entry_enumerator_t *this)
176 {
177 this->inner->destroy(this->inner);
178 free(this);
179 }
180
181 METHOD(auth_cfg_t, create_enumerator, enumerator_t*,
182 private_auth_cfg_t *this)
183 {
184 entry_enumerator_t *enumerator;
185
186 INIT(enumerator,
187 .public = {
188 .enumerate = (void*)enumerate,
189 .destroy = (void*)entry_enumerator_destroy,
190 },
191 .inner = array_create_enumerator(this->entries),
192 );
193 return &enumerator->public;
194 }
195
196 /**
197 * Initialize an entry.
198 */
199 static void init_entry(entry_t *this, auth_rule_t type, va_list args)
200 {
201 this->type = type;
202 switch (type)
203 {
204 case AUTH_RULE_IDENTITY_LOOSE:
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 case AUTH_RULE_RSA_STRENGTH:
211 case AUTH_RULE_ECDSA_STRENGTH:
212 case AUTH_RULE_BLISS_STRENGTH:
213 case AUTH_RULE_SIGNATURE_SCHEME:
214 /* integer type */
215 this->value = (void*)(uintptr_t)va_arg(args, u_int);
216 break;
217 case AUTH_RULE_IDENTITY:
218 case AUTH_RULE_EAP_IDENTITY:
219 case AUTH_RULE_AAA_IDENTITY:
220 case AUTH_RULE_XAUTH_BACKEND:
221 case AUTH_RULE_XAUTH_IDENTITY:
222 case AUTH_RULE_GROUP:
223 case AUTH_RULE_CA_CERT:
224 case AUTH_RULE_IM_CERT:
225 case AUTH_RULE_SUBJECT_CERT:
226 case AUTH_RULE_CERT_POLICY:
227 case AUTH_HELPER_IM_CERT:
228 case AUTH_HELPER_SUBJECT_CERT:
229 case AUTH_HELPER_IM_HASH_URL:
230 case AUTH_HELPER_SUBJECT_HASH_URL:
231 case AUTH_HELPER_REVOCATION_CERT:
232 case AUTH_HELPER_AC_CERT:
233 /* pointer type */
234 this->value = va_arg(args, void*);
235 break;
236 case AUTH_RULE_MAX:
237 this->value = NULL;
238 break;
239 }
240 }
241
242 /**
243 * Compare two entries for equality.
244 */
245 static bool entry_equals(entry_t *e1, entry_t *e2)
246 {
247 if (e1->type != e2->type)
248 {
249 return FALSE;
250 }
251 switch (e1->type)
252 {
253 case AUTH_RULE_IDENTITY_LOOSE:
254 case AUTH_RULE_AUTH_CLASS:
255 case AUTH_RULE_EAP_TYPE:
256 case AUTH_RULE_EAP_VENDOR:
257 case AUTH_RULE_CRL_VALIDATION:
258 case AUTH_RULE_OCSP_VALIDATION:
259 case AUTH_RULE_RSA_STRENGTH:
260 case AUTH_RULE_ECDSA_STRENGTH:
261 case AUTH_RULE_BLISS_STRENGTH:
262 case AUTH_RULE_SIGNATURE_SCHEME:
263 {
264 return e1->value == e2->value;
265 }
266 case AUTH_RULE_CA_CERT:
267 case AUTH_RULE_IM_CERT:
268 case AUTH_RULE_SUBJECT_CERT:
269 case AUTH_HELPER_IM_CERT:
270 case AUTH_HELPER_SUBJECT_CERT:
271 case AUTH_HELPER_REVOCATION_CERT:
272 case AUTH_HELPER_AC_CERT:
273 {
274 certificate_t *c1, *c2;
275
276 c1 = (certificate_t*)e1->value;
277 c2 = (certificate_t*)e2->value;
278
279 return c1->equals(c1, c2);
280 }
281 case AUTH_RULE_IDENTITY:
282 case AUTH_RULE_EAP_IDENTITY:
283 case AUTH_RULE_AAA_IDENTITY:
284 case AUTH_RULE_XAUTH_IDENTITY:
285 case AUTH_RULE_GROUP:
286 {
287 identification_t *id1, *id2;
288
289 id1 = (identification_t*)e1->value;
290 id2 = (identification_t*)e2->value;
291
292 return id1->equals(id1, id2);
293 }
294 case AUTH_RULE_CERT_POLICY:
295 case AUTH_RULE_XAUTH_BACKEND:
296 case AUTH_HELPER_IM_HASH_URL:
297 case AUTH_HELPER_SUBJECT_HASH_URL:
298 {
299 return streq(e1->value, e2->value);
300 }
301 case AUTH_RULE_MAX:
302 break;
303 }
304 return FALSE;
305 }
306
307 /**
308 * Destroy the value associated with an entry
309 */
310 static void destroy_entry_value(entry_t *entry)
311 {
312 switch (entry->type)
313 {
314 case AUTH_RULE_IDENTITY:
315 case AUTH_RULE_EAP_IDENTITY:
316 case AUTH_RULE_AAA_IDENTITY:
317 case AUTH_RULE_GROUP:
318 case AUTH_RULE_XAUTH_IDENTITY:
319 {
320 identification_t *id = (identification_t*)entry->value;
321 id->destroy(id);
322 break;
323 }
324 case AUTH_RULE_CA_CERT:
325 case AUTH_RULE_IM_CERT:
326 case AUTH_RULE_SUBJECT_CERT:
327 case AUTH_HELPER_IM_CERT:
328 case AUTH_HELPER_SUBJECT_CERT:
329 case AUTH_HELPER_REVOCATION_CERT:
330 case AUTH_HELPER_AC_CERT:
331 {
332 certificate_t *cert = (certificate_t*)entry->value;
333 cert->destroy(cert);
334 break;
335 }
336 case AUTH_RULE_CERT_POLICY:
337 case AUTH_RULE_XAUTH_BACKEND:
338 case AUTH_HELPER_IM_HASH_URL:
339 case AUTH_HELPER_SUBJECT_HASH_URL:
340 {
341 free(entry->value);
342 break;
343 }
344 case AUTH_RULE_IDENTITY_LOOSE:
345 case AUTH_RULE_AUTH_CLASS:
346 case AUTH_RULE_EAP_TYPE:
347 case AUTH_RULE_EAP_VENDOR:
348 case AUTH_RULE_CRL_VALIDATION:
349 case AUTH_RULE_OCSP_VALIDATION:
350 case AUTH_RULE_RSA_STRENGTH:
351 case AUTH_RULE_ECDSA_STRENGTH:
352 case AUTH_RULE_BLISS_STRENGTH:
353 case AUTH_RULE_SIGNATURE_SCHEME:
354 case AUTH_RULE_MAX:
355 break;
356 }
357 }
358
359 /**
360 * Implementation of auth_cfg_t.replace.
361 */
362 static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
363 auth_rule_t type, ...)
364 {
365 if (enumerator->current)
366 {
367 entry_t *entry;
368 va_list args;
369
370 va_start(args, type);
371 entry = enumerator->current;
372 destroy_entry_value(entry);
373 entry->type = type;
374 switch (type)
375 {
376 case AUTH_RULE_IDENTITY_LOOSE:
377 case AUTH_RULE_AUTH_CLASS:
378 case AUTH_RULE_EAP_TYPE:
379 case AUTH_RULE_EAP_VENDOR:
380 case AUTH_RULE_CRL_VALIDATION:
381 case AUTH_RULE_OCSP_VALIDATION:
382 case AUTH_RULE_RSA_STRENGTH:
383 case AUTH_RULE_ECDSA_STRENGTH:
384 case AUTH_RULE_BLISS_STRENGTH:
385 case AUTH_RULE_SIGNATURE_SCHEME:
386 /* integer type */
387 entry->value = (void*)(uintptr_t)va_arg(args, u_int);
388 break;
389 case AUTH_RULE_IDENTITY:
390 case AUTH_RULE_EAP_IDENTITY:
391 case AUTH_RULE_AAA_IDENTITY:
392 case AUTH_RULE_XAUTH_BACKEND:
393 case AUTH_RULE_XAUTH_IDENTITY:
394 case AUTH_RULE_GROUP:
395 case AUTH_RULE_CA_CERT:
396 case AUTH_RULE_IM_CERT:
397 case AUTH_RULE_SUBJECT_CERT:
398 case AUTH_RULE_CERT_POLICY:
399 case AUTH_HELPER_IM_CERT:
400 case AUTH_HELPER_SUBJECT_CERT:
401 case AUTH_HELPER_IM_HASH_URL:
402 case AUTH_HELPER_SUBJECT_HASH_URL:
403 case AUTH_HELPER_REVOCATION_CERT:
404 case AUTH_HELPER_AC_CERT:
405 /* pointer type */
406 entry->value = va_arg(args, void*);
407 break;
408 case AUTH_RULE_MAX:
409 entry->value = NULL;
410 break;
411 }
412 va_end(args);
413 }
414 }
415
416 METHOD(auth_cfg_t, get, void*,
417 private_auth_cfg_t *this, auth_rule_t type)
418 {
419 enumerator_t *enumerator;
420 void *current_value, *best_value = NULL;
421 auth_rule_t current_type;
422 bool found = FALSE;
423
424 enumerator = create_enumerator(this);
425 while (enumerator->enumerate(enumerator, &current_type, &current_value))
426 {
427 if (type == current_type)
428 {
429 if (type == AUTH_RULE_CRL_VALIDATION ||
430 type == AUTH_RULE_OCSP_VALIDATION)
431 { /* for CRL/OCSP validation, always get() the highest value */
432 if (!found || current_value > best_value)
433 {
434 best_value = current_value;
435 }
436 found = TRUE;
437 continue;
438 }
439 best_value = current_value;
440 found = TRUE;
441 break;
442 }
443 }
444 enumerator->destroy(enumerator);
445 if (found)
446 {
447 return best_value;
448 }
449 switch (type)
450 {
451 /* use some sane defaults if we don't find an entry */
452 case AUTH_RULE_AUTH_CLASS:
453 return (void*)AUTH_CLASS_ANY;
454 case AUTH_RULE_EAP_TYPE:
455 return (void*)EAP_NAK;
456 case AUTH_RULE_EAP_VENDOR:
457 case AUTH_RULE_RSA_STRENGTH:
458 case AUTH_RULE_ECDSA_STRENGTH:
459 case AUTH_RULE_BLISS_STRENGTH:
460 return (void*)0;
461 case AUTH_RULE_SIGNATURE_SCHEME:
462 return (void*)HASH_UNKNOWN;
463 case AUTH_RULE_CRL_VALIDATION:
464 case AUTH_RULE_OCSP_VALIDATION:
465 return (void*)VALIDATION_FAILED;
466 case AUTH_RULE_IDENTITY_LOOSE:
467 return (void*)FALSE;
468 case AUTH_RULE_IDENTITY:
469 case AUTH_RULE_EAP_IDENTITY:
470 case AUTH_RULE_AAA_IDENTITY:
471 case AUTH_RULE_XAUTH_BACKEND:
472 case AUTH_RULE_XAUTH_IDENTITY:
473 case AUTH_RULE_GROUP:
474 case AUTH_RULE_CA_CERT:
475 case AUTH_RULE_IM_CERT:
476 case AUTH_RULE_SUBJECT_CERT:
477 case AUTH_RULE_CERT_POLICY:
478 case AUTH_HELPER_IM_CERT:
479 case AUTH_HELPER_SUBJECT_CERT:
480 case AUTH_HELPER_IM_HASH_URL:
481 case AUTH_HELPER_SUBJECT_HASH_URL:
482 case AUTH_HELPER_REVOCATION_CERT:
483 case AUTH_HELPER_AC_CERT:
484 case AUTH_RULE_MAX:
485 break;
486 }
487 return NULL;
488 }
489
490 /**
491 * Implementation of auth_cfg_t.add.
492 */
493 static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
494 {
495 entry_t entry;
496 va_list args;
497
498 va_start(args, type);
499 init_entry(&entry, type, args);
500 va_end(args);
501
502 if (is_multi_value_rule(type))
503 { /* insert rules that may occur multiple times at the end */
504 array_insert(this->entries, ARRAY_TAIL, &entry);
505 }
506 else
507 { /* insert rules we expect only once at the front (get() will return
508 * the latest value) */
509 array_insert(this->entries, ARRAY_HEAD, &entry);
510 }
511 }
512
513 METHOD(auth_cfg_t, complies, bool,
514 private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error)
515 {
516 enumerator_t *e1, *e2;
517 bool success = TRUE, group_match = FALSE, cert_match = FALSE;
518 identification_t *require_group = NULL;
519 certificate_t *require_cert = NULL;
520 signature_scheme_t scheme = SIGN_UNKNOWN;
521 u_int strength = 0;
522 auth_rule_t t1, t2;
523 char *key_type;
524 void *value;
525
526 e1 = constraints->create_enumerator(constraints);
527 while (e1->enumerate(e1, &t1, &value))
528 {
529 switch (t1)
530 {
531 case AUTH_RULE_CA_CERT:
532 case AUTH_RULE_IM_CERT:
533 {
534 certificate_t *c1, *c2;
535
536 c1 = (certificate_t*)value;
537
538 success = FALSE;
539 e2 = create_enumerator(this);
540 while (e2->enumerate(e2, &t2, &c2))
541 {
542 if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
543 c1->equals(c1, c2))
544 {
545 success = TRUE;
546 }
547 }
548 e2->destroy(e2);
549 if (!success && log_error)
550 {
551 DBG1(DBG_CFG, "constraint check failed: peer not "
552 "authenticated by CA '%Y'.", c1->get_subject(c1));
553 }
554 break;
555 }
556 case AUTH_RULE_SUBJECT_CERT:
557 {
558 certificate_t *cert;
559
560 /* for certs, a match of a single cert is sufficient */
561 require_cert = (certificate_t*)value;
562
563 e2 = create_enumerator(this);
564 while (e2->enumerate(e2, &t2, &cert))
565 {
566 if (t2 == AUTH_RULE_SUBJECT_CERT &&
567 cert->equals(cert, require_cert))
568 {
569 cert_match = TRUE;
570 }
571 }
572 e2->destroy(e2);
573 break;
574 }
575 case AUTH_RULE_CRL_VALIDATION:
576 case AUTH_RULE_OCSP_VALIDATION:
577 {
578 uintptr_t validated;
579
580 e2 = create_enumerator(this);
581 while (e2->enumerate(e2, &t2, &validated))
582 {
583 if (t2 == t1)
584 {
585 switch ((uintptr_t)value)
586 {
587 case VALIDATION_FAILED:
588 /* no constraint */
589 break;
590 case VALIDATION_SKIPPED:
591 if (validated == VALIDATION_SKIPPED)
592 {
593 break;
594 }
595 /* FALL */
596 case VALIDATION_GOOD:
597 if (validated == VALIDATION_GOOD)
598 {
599 break;
600 }
601 /* FALL */
602 default:
603 success = FALSE;
604 if (log_error)
605 {
606 DBG1(DBG_CFG, "constraint check failed: "
607 "%N is %N, but requires at least %N",
608 auth_rule_names, t1,
609 cert_validation_names, validated,
610 cert_validation_names, (uintptr_t)value);
611 }
612 break;
613 }
614 }
615 }
616 e2->destroy(e2);
617 break;
618 }
619 case AUTH_RULE_IDENTITY:
620 case AUTH_RULE_EAP_IDENTITY:
621 case AUTH_RULE_AAA_IDENTITY:
622 case AUTH_RULE_XAUTH_IDENTITY:
623 {
624 identification_t *id1, *id2;
625
626 id1 = (identification_t*)value;
627 id2 = get(this, t1);
628 if (!id2 || !id2->matches(id2, id1))
629 {
630 if (t1 == AUTH_RULE_IDENTITY &&
631 constraints->get(constraints, AUTH_RULE_IDENTITY_LOOSE))
632 { /* also verify identity against subjectAltNames */
633 certificate_t *cert;
634
635 cert = get(this, AUTH_HELPER_SUBJECT_CERT);
636 if (cert && cert->has_subject(cert, id1))
637 {
638 break;
639 }
640 }
641 success = FALSE;
642 if (log_error)
643 {
644 DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
645 " required ", t1 == AUTH_RULE_IDENTITY ? "" :
646 "EAP ", id1);
647 }
648 }
649 break;
650 }
651 case AUTH_RULE_AUTH_CLASS:
652 {
653 if ((uintptr_t)value != AUTH_CLASS_ANY &&
654 (uintptr_t)value != (uintptr_t)get(this, t1))
655 {
656 success = FALSE;
657 if (log_error)
658 {
659 DBG1(DBG_CFG, "constraint requires %N authentication, "
660 "but %N was used", auth_class_names, (uintptr_t)value,
661 auth_class_names, (uintptr_t)get(this, t1));
662 }
663 }
664 break;
665 }
666 case AUTH_RULE_EAP_TYPE:
667 {
668 if ((uintptr_t)value != (uintptr_t)get(this, t1))
669 {
670 success = FALSE;
671 if (log_error)
672 {
673 DBG1(DBG_CFG, "constraint requires %N, "
674 "but %N was used", eap_type_names, (uintptr_t)value,
675 eap_type_names, (uintptr_t)get(this, t1));
676 }
677 }
678 break;
679 }
680 case AUTH_RULE_EAP_VENDOR:
681 {
682 if ((uintptr_t)value != (uintptr_t)get(this, t1))
683 {
684 success = FALSE;
685 if (log_error)
686 {
687 DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
688 "but %d was used", (uintptr_t)value,
689 (uintptr_t)get(this, t1));
690 }
691 }
692 break;
693 }
694 case AUTH_RULE_GROUP:
695 {
696 identification_t *group;
697
698 /* for groups, a match of a single group is sufficient */
699 require_group = (identification_t*)value;
700 e2 = create_enumerator(this);
701 while (e2->enumerate(e2, &t2, &group))
702 {
703 if (t2 == AUTH_RULE_GROUP &&
704 group->matches(group, require_group))
705 {
706 group_match = TRUE;
707 }
708 }
709 e2->destroy(e2);
710 break;
711 }
712 case AUTH_RULE_RSA_STRENGTH:
713 case AUTH_RULE_ECDSA_STRENGTH:
714 case AUTH_RULE_BLISS_STRENGTH:
715 {
716 strength = (uintptr_t)value;
717 break;
718 }
719 case AUTH_RULE_SIGNATURE_SCHEME:
720 {
721 scheme = (uintptr_t)value;
722 break;
723 }
724 case AUTH_RULE_CERT_POLICY:
725 {
726 char *oid1, *oid2;
727
728 oid1 = (char*)value;
729 success = FALSE;
730 e2 = create_enumerator(this);
731 while (e2->enumerate(e2, &t2, &oid2))
732 {
733 if (t2 == t1 && streq(oid1, oid2))
734 {
735 success = TRUE;
736 break;
737 }
738 }
739 e2->destroy(e2);
740 if (!success && log_error)
741 {
742 DBG1(DBG_CFG, "constraint requires cert policy %s", oid1);
743 }
744 break;
745 }
746 case AUTH_RULE_IDENTITY_LOOSE:
747 /* just an indication when verifying AUTH_RULE_IDENTITY */
748 case AUTH_RULE_XAUTH_BACKEND:
749 /* not enforced, just a hint for local authentication */
750 case AUTH_HELPER_IM_CERT:
751 case AUTH_HELPER_SUBJECT_CERT:
752 case AUTH_HELPER_IM_HASH_URL:
753 case AUTH_HELPER_SUBJECT_HASH_URL:
754 case AUTH_HELPER_REVOCATION_CERT:
755 case AUTH_HELPER_AC_CERT:
756 case AUTH_RULE_MAX:
757 /* skip helpers */
758 continue;
759 }
760 if (!success)
761 {
762 break;
763 }
764 }
765 e1->destroy(e1);
766
767 /* Check if we have a matching constraint (or none at all) for used
768 * signature schemes. */
769 if (success && scheme != SIGN_UNKNOWN)
770 {
771 e2 = create_enumerator(this);
772 while (e2->enumerate(e2, &t2, &scheme))
773 {
774 if (t2 == AUTH_RULE_SIGNATURE_SCHEME)
775 {
776 success = FALSE;
777 e1 = constraints->create_enumerator(constraints);
778 while (e1->enumerate(e1, &t1, &value))
779 {
780 if (t1 == AUTH_RULE_SIGNATURE_SCHEME &&
781 (uintptr_t)value == scheme)
782 {
783 success = TRUE;
784 break;
785 }
786 }
787 e1->destroy(e1);
788 if (!success)
789 {
790 if (log_error)
791 {
792 DBG1(DBG_CFG, "signature scheme %N not acceptable",
793 signature_scheme_names, (int)scheme);
794 }
795 break;
796 }
797 }
798 }
799 e2->destroy(e2);
800 }
801
802 /* Check if we have a matching constraint (or none at all) for used
803 * public key strength */
804 if (success && strength)
805 {
806 e2 = create_enumerator(this);
807 while (e2->enumerate(e2, &t2, &strength))
808 {
809 switch (t2)
810 {
811 default:
812 continue;
813 case AUTH_RULE_RSA_STRENGTH:
814 key_type = "RSA";
815 break;
816 case AUTH_RULE_ECDSA_STRENGTH:
817 key_type = "ECDSA";
818 break;
819 case AUTH_RULE_BLISS_STRENGTH:
820 key_type = "BLISS";
821 break;
822 }
823 success = FALSE;
824 e1 = constraints->create_enumerator(constraints);
825 while (e1->enumerate(e1, &t1, &value))
826 {
827 if (t1 == t2 && (uintptr_t)value <= strength)
828 {
829 success = TRUE;
830 break;
831 }
832 }
833 e1->destroy(e1);
834 if (!success)
835 {
836 if (log_error)
837 {
838 DBG1(DBG_CFG, "%s-%d signatures not acceptable",
839 key_type, strength);
840 }
841 break;
842 }
843 }
844 e2->destroy(e2);
845 }
846
847 if (require_group && !group_match)
848 {
849 if (log_error)
850 {
851 DBG1(DBG_CFG, "constraint check failed: group membership to "
852 "'%Y' required", require_group);
853 }
854 return FALSE;
855 }
856
857 if (require_cert && !cert_match)
858 {
859 if (log_error)
860 {
861 DBG1(DBG_CFG, "constraint check failed: peer not "
862 "authenticated with peer cert '%Y'.",
863 require_cert->get_subject(require_cert));
864 }
865 return FALSE;
866 }
867 return success;
868 }
869
870 /**
871 * Implementation of auth_cfg_t.merge.
872 */
873 static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
874 {
875 if (!other)
876 { /* nothing to merge */
877 return;
878 }
879 if (copy)
880 {
881 enumerator_t *enumerator;
882 auth_rule_t type;
883 void *value;
884
885 /* this enumerator skips duplicates for rules we expect only once */
886 enumerator = create_enumerator(other);
887 while (enumerator->enumerate(enumerator, &type, &value))
888 {
889 switch (type)
890 {
891 case AUTH_RULE_CA_CERT:
892 case AUTH_RULE_IM_CERT:
893 case AUTH_RULE_SUBJECT_CERT:
894 case AUTH_HELPER_IM_CERT:
895 case AUTH_HELPER_SUBJECT_CERT:
896 case AUTH_HELPER_REVOCATION_CERT:
897 case AUTH_HELPER_AC_CERT:
898 {
899 certificate_t *cert = (certificate_t*)value;
900
901 add(this, type, cert->get_ref(cert));
902 break;
903 }
904 case AUTH_RULE_IDENTITY_LOOSE:
905 case AUTH_RULE_CRL_VALIDATION:
906 case AUTH_RULE_OCSP_VALIDATION:
907 case AUTH_RULE_AUTH_CLASS:
908 case AUTH_RULE_EAP_TYPE:
909 case AUTH_RULE_EAP_VENDOR:
910 case AUTH_RULE_RSA_STRENGTH:
911 case AUTH_RULE_ECDSA_STRENGTH:
912 case AUTH_RULE_BLISS_STRENGTH:
913 case AUTH_RULE_SIGNATURE_SCHEME:
914 {
915 add(this, type, (uintptr_t)value);
916 break;
917 }
918 case AUTH_RULE_IDENTITY:
919 case AUTH_RULE_EAP_IDENTITY:
920 case AUTH_RULE_AAA_IDENTITY:
921 case AUTH_RULE_GROUP:
922 case AUTH_RULE_XAUTH_IDENTITY:
923 {
924 identification_t *id = (identification_t*)value;
925
926 add(this, type, id->clone(id));
927 break;
928 }
929 case AUTH_RULE_XAUTH_BACKEND:
930 case AUTH_RULE_CERT_POLICY:
931 case AUTH_HELPER_IM_HASH_URL:
932 case AUTH_HELPER_SUBJECT_HASH_URL:
933 {
934 add(this, type, strdup((char*)value));
935 break;
936 }
937 case AUTH_RULE_MAX:
938 break;
939 }
940 }
941 enumerator->destroy(enumerator);
942 }
943 else
944 {
945 entry_t entry;
946
947 while (array_remove(other->entries, ARRAY_HEAD, &entry))
948 {
949 array_insert(this->entries, ARRAY_TAIL, &entry);
950 }
951 array_compress(other->entries);
952 }
953 }
954
955 /**
956 * Compare two auth_cfg_t objects for equality.
957 */
958 static bool auth_cfg_equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
959 {
960 enumerator_t *e1, *e2;
961 entry_t *i1, *i2;
962 bool equal = TRUE, found;
963
964 /* the rule count does not have to be equal for the two, as we only compare
965 * the first value found for some rules */
966 e1 = array_create_enumerator(this->entries);
967 while (e1->enumerate(e1, &i1))
968 {
969 found = FALSE;
970
971 e2 = array_create_enumerator(other->entries);
972 while (e2->enumerate(e2, &i2))
973 {
974 if (entry_equals(i1, i2))
975 {
976 found = TRUE;
977 break;
978 }
979 else if (i1->type == i2->type && !is_multi_value_rule(i1->type))
980 { /* we continue our search, only for multi valued rules */
981 break;
982 }
983 }
984 e2->destroy(e2);
985 if (!found)
986 {
987 equal = FALSE;
988 break;
989 }
990 }
991 e1->destroy(e1);
992 return equal;
993 }
994
995 /**
996 * Implementation of auth_cfg_t.equals.
997 */
998 static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
999 {
1000 if (auth_cfg_equals(this, other))
1001 {
1002 /* as 'other' might contain entries that 'this' doesn't we also check
1003 * the other way around */
1004 return auth_cfg_equals(other, this);
1005 }
1006 return FALSE;
1007 }
1008
1009 METHOD(auth_cfg_t, purge, void,
1010 private_auth_cfg_t *this, bool keep_ca)
1011 {
1012 enumerator_t *enumerator;
1013 entry_t *entry;
1014
1015 enumerator = array_create_enumerator(this->entries);
1016 while (enumerator->enumerate(enumerator, &entry))
1017 {
1018 if (!keep_ca || entry->type != AUTH_RULE_CA_CERT)
1019 {
1020 destroy_entry_value(entry);
1021 array_remove_at(this->entries, enumerator);
1022 }
1023 }
1024 enumerator->destroy(enumerator);
1025
1026 array_compress(this->entries);
1027 }
1028
1029 METHOD(auth_cfg_t, clone_, auth_cfg_t*,
1030 private_auth_cfg_t *this)
1031 {
1032 enumerator_t *enumerator;
1033 auth_cfg_t *clone;
1034 auth_rule_t type;
1035 void *value;
1036
1037 clone = auth_cfg_create();
1038 /* this enumerator skips duplicates for rules we expect only once */
1039 enumerator = create_enumerator(this);
1040 while (enumerator->enumerate(enumerator, &type, &value))
1041 {
1042 switch (type)
1043 {
1044 case AUTH_RULE_IDENTITY:
1045 case AUTH_RULE_EAP_IDENTITY:
1046 case AUTH_RULE_AAA_IDENTITY:
1047 case AUTH_RULE_GROUP:
1048 case AUTH_RULE_XAUTH_IDENTITY:
1049 {
1050 identification_t *id = (identification_t*)value;
1051 clone->add(clone, type, id->clone(id));
1052 break;
1053 }
1054 case AUTH_RULE_CA_CERT:
1055 case AUTH_RULE_IM_CERT:
1056 case AUTH_RULE_SUBJECT_CERT:
1057 case AUTH_HELPER_IM_CERT:
1058 case AUTH_HELPER_SUBJECT_CERT:
1059 case AUTH_HELPER_REVOCATION_CERT:
1060 case AUTH_HELPER_AC_CERT:
1061 {
1062 certificate_t *cert = (certificate_t*)value;
1063 clone->add(clone, type, cert->get_ref(cert));
1064 break;
1065 }
1066 case AUTH_RULE_XAUTH_BACKEND:
1067 case AUTH_RULE_CERT_POLICY:
1068 case AUTH_HELPER_IM_HASH_URL:
1069 case AUTH_HELPER_SUBJECT_HASH_URL:
1070 {
1071 clone->add(clone, type, strdup(value));
1072 break;
1073 }
1074 case AUTH_RULE_IDENTITY_LOOSE:
1075 case AUTH_RULE_AUTH_CLASS:
1076 case AUTH_RULE_EAP_TYPE:
1077 case AUTH_RULE_EAP_VENDOR:
1078 case AUTH_RULE_CRL_VALIDATION:
1079 case AUTH_RULE_OCSP_VALIDATION:
1080 case AUTH_RULE_RSA_STRENGTH:
1081 case AUTH_RULE_ECDSA_STRENGTH:
1082 case AUTH_RULE_BLISS_STRENGTH:
1083 case AUTH_RULE_SIGNATURE_SCHEME:
1084 clone->add(clone, type, (uintptr_t)value);
1085 break;
1086 case AUTH_RULE_MAX:
1087 break;
1088 }
1089 }
1090 enumerator->destroy(enumerator);
1091 return clone;
1092 }
1093
1094 METHOD(auth_cfg_t, destroy, void,
1095 private_auth_cfg_t *this)
1096 {
1097 purge(this, FALSE);
1098 array_destroy(this->entries);
1099 free(this);
1100 }
1101
1102 /*
1103 * see header file
1104 */
1105 auth_cfg_t *auth_cfg_create()
1106 {
1107 private_auth_cfg_t *this;
1108
1109 INIT(this,
1110 .public = {
1111 .add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add,
1112 .get = _get,
1113 .create_enumerator = _create_enumerator,
1114 .replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace,
1115 .complies = _complies,
1116 .merge = (void(*)(auth_cfg_t*,auth_cfg_t*,bool))merge,
1117 .purge = _purge,
1118 .equals = (bool(*)(auth_cfg_t*,auth_cfg_t*))equals,
1119 .clone = _clone_,
1120 .destroy = _destroy,
1121 },
1122 .entries = array_create(sizeof(entry_t), 0),
1123 );
1124
1125 return &this->public;
1126 }