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