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