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