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