bc6bfe9ad6f75a2b18de57487c328819b3aae28c
[strongswan.git] / src / pluto / ca.c
1 /* Certification Authority (CA) support for IKE authentication
2 * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <dirent.h>
20 #include <time.h>
21 #include <sys/types.h>
22
23 #include <utils/identification.h>
24
25 #include <freeswan.h>
26
27 #include "constants.h"
28 #include "defs.h"
29 #include "log.h"
30 #include "x509.h"
31 #include "ca.h"
32 #include "certs.h"
33 #include "whack.h"
34 #include "fetch.h"
35 #include "smartcard.h"
36
37 /* chained list of X.509 authority certificates (ca, aa, and ocsp) */
38
39 static x509cert_t *x509authcerts = NULL;
40
41 /* chained list of X.509 certification authority information records */
42
43 static ca_info_t *ca_infos = NULL;
44
45 /*
46 * Checks if CA a is trusted by CA b
47 */
48 bool trusted_ca(chunk_t a, chunk_t b, int *pathlen)
49 {
50 bool match = FALSE;
51
52 /* no CA b specified -> any CA a is accepted */
53 if (b.ptr == NULL)
54 {
55 *pathlen = (a.ptr == NULL)? 0 : MAX_CA_PATH_LEN;
56 return TRUE;
57 }
58
59 /* no CA a specified -> trust cannot be established */
60 if (a.ptr == NULL)
61 {
62 *pathlen = MAX_CA_PATH_LEN;
63 return FALSE;
64 }
65
66 *pathlen = 0;
67
68 /* CA a equals CA b -> we have a match */
69 if (same_dn(a, b))
70 {
71 return TRUE;
72 }
73
74 /* CA a might be a subordinate CA of b */
75 lock_authcert_list("trusted_ca");
76
77 while ((*pathlen)++ < MAX_CA_PATH_LEN)
78 {
79 certificate_t *certificate;
80 identification_t *issuer;
81 chunk_t issuer_dn;
82 x509cert_t *cacert;
83
84 cacert = get_authcert(a, chunk_empty, AUTH_CA);
85 if (cacert == NULL)
86 {
87 break;
88 }
89 certificate = cacert->cert;
90
91 /* is the certificate self-signed? */
92 {
93 x509_t *x509 = (x509_t*)certificate;
94
95 if (x509->get_flags(x509) & X509_SELF_SIGNED)
96 {
97 break;
98 }
99 }
100
101 /* does the issuer of CA a match CA b? */
102 issuer = certificate->get_issuer(certificate);
103 issuer_dn = issuer->get_encoding(issuer);
104 match = same_dn(issuer_dn, b);
105
106 /* we have a match and exit the loop */
107 if (match)
108 {
109 break;
110 }
111 /* go one level up in the CA chain */
112 a = issuer_dn;
113 }
114
115 unlock_authcert_list("trusted_ca");
116 return match;
117 }
118
119 /*
120 * does our CA match one of the requested CAs?
121 */
122 bool match_requested_ca(generalName_t *requested_ca, chunk_t our_ca,
123 int *our_pathlen)
124 {
125 /* if no ca is requested than any ca will match */
126 if (requested_ca == NULL)
127 {
128 *our_pathlen = 0;
129 return TRUE;
130 }
131
132 *our_pathlen = MAX_CA_PATH_LEN + 1;
133
134 while (requested_ca != NULL)
135 {
136 int pathlen;
137
138 if (trusted_ca(our_ca, requested_ca->name, &pathlen)
139 && pathlen < *our_pathlen)
140 {
141 *our_pathlen = pathlen;
142 }
143 requested_ca = requested_ca->next;
144 }
145
146 if (*our_pathlen > MAX_CA_PATH_LEN)
147 {
148 *our_pathlen = MAX_CA_PATH_LEN;
149 return FALSE;
150 }
151 else
152 {
153 return TRUE;
154 }
155 }
156
157 /*
158 * free the first authority certificate in the chain
159 */
160 static void free_first_authcert(void)
161 {
162 x509cert_t *first = x509authcerts;
163 x509authcerts = first->next;
164 free_x509cert(first);
165 }
166
167 /*
168 * free all CA certificates
169 */
170 void free_authcerts(void)
171 {
172 lock_authcert_list("free_authcerts");
173
174 while (x509authcerts != NULL)
175 free_first_authcert();
176
177 unlock_authcert_list("free_authcerts");
178 }
179
180 /*
181 * get a X.509 authority certificate with a given subject or keyid
182 */
183 x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags)
184 {
185 x509cert_t *cert, *prev_cert = NULL;
186
187 /* the authority certificate list is empty */
188 if (x509authcerts == NULL)
189 {
190 return NULL;
191 }
192
193 for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next)
194 {
195 certificate_t *certificate = cert->cert;
196 identification_t *cert_subject;
197 chunk_t cert_subject_dn;
198
199 /* skip non-matching types of authority certificates */
200 if (!(cert->authority_flags & auth_flags))
201 {
202 continue;
203 }
204
205 /* compare the keyid with the certificate's subjectKeyIdentifier */
206 if (keyid.ptr)
207 {
208 x509_t *x509 = (x509_t*)certificate;
209 chunk_t subjectKeyId;
210
211 subjectKeyId = x509->get_subjectKeyIdentifier(x509);
212 if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
213 {
214 continue;
215 }
216 }
217
218 /* compare the subjectDistinguishedNames */
219 cert_subject = certificate->get_subject(certificate);
220 cert_subject_dn = cert_subject->get_encoding(cert_subject);
221 if (!same_dn(subject, cert_subject_dn))
222 {
223 continue;
224 }
225
226 /* found the authcert */
227 if (cert != x509authcerts)
228 {
229 /* bring the certificate up front */
230 prev_cert->next = cert->next;
231 cert->next = x509authcerts;
232 x509authcerts = cert;
233 }
234 return cert;
235 }
236 return NULL;
237 }
238
239 /*
240 * add an authority certificate to the chained list
241 */
242 x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags)
243 {
244 certificate_t *certificate = cert->cert;
245 x509_t *x509 = (x509_t*)certificate;
246 identification_t *cert_subject = certificate->get_subject(certificate);
247 chunk_t cert_subject_dn = cert_subject->get_encoding(cert_subject);
248 x509cert_t *old_cert;
249
250 /* set authority flags */
251 cert->authority_flags |= auth_flags;
252
253 lock_authcert_list("add_authcert");
254
255 old_cert = get_authcert(cert_subject_dn,
256 x509->get_subjectKeyIdentifier(x509),
257 auth_flags);
258 if (old_cert != NULL)
259 {
260 if (certificate->equals(certificate, old_cert->cert))
261 {
262 /* cert is already present, just add additional authority flags */
263 old_cert->authority_flags |= cert->authority_flags;
264 DBG(DBG_CONTROL | DBG_PARSING ,
265 DBG_log(" authcert is already present and identical")
266 )
267 unlock_authcert_list("add_authcert");
268
269 free_x509cert(cert);
270 return old_cert;
271 }
272 else
273 {
274 /* cert is already present but will be replaced by new cert */
275 free_first_authcert();
276 DBG(DBG_CONTROL | DBG_PARSING ,
277 DBG_log(" existing authcert deleted")
278 )
279 }
280 }
281
282 /* add new authcert to chained list */
283 cert->next = x509authcerts;
284 x509authcerts = cert;
285 share_x509cert(cert); /* set count to one */
286 DBG(DBG_CONTROL | DBG_PARSING,
287 DBG_log(" authcert inserted")
288 )
289 unlock_authcert_list("add_authcert");
290 return cert;
291 }
292
293 /*
294 * Loads authority certificates
295 */
296 void load_authcerts(const char *type, const char *path, u_char auth_flags)
297 {
298 struct dirent **filelist;
299 u_char buf[BUF_LEN];
300 u_char *save_dir;
301 int n;
302
303 /* change directory to specified path */
304 save_dir = getcwd(buf, BUF_LEN);
305
306 if (chdir(path))
307 {
308 plog("Could not change to directory '%s'", path);
309 }
310 else
311 {
312 plog("Changing to directory '%s'", path);
313 n = scandir(path, &filelist, file_select, alphasort);
314
315 if (n < 0)
316 plog(" scandir() error");
317 else
318 {
319 while (n--)
320 {
321 cert_t cert;
322
323 if (load_cert(filelist[n]->d_name, type, &cert))
324 add_authcert(cert.u.x509, auth_flags);
325
326 free(filelist[n]);
327 }
328 free(filelist);
329 }
330 }
331 /* restore directory path */
332 ignore_result(chdir(save_dir));
333 }
334
335 /*
336 * list all X.509 authcerts with given auth flags in a chained list
337 */
338 void list_authcerts(const char *caption, u_char auth_flags, bool utc)
339 {
340 lock_authcert_list("list_authcerts");
341 list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
342 unlock_authcert_list("list_authcerts");
343 }
344
345 /*
346 * get a cacert with a given subject or keyid from an alternative list
347 */
348 static const x509cert_t* get_alt_cacert(chunk_t subject, chunk_t keyid,
349 const x509cert_t *cert)
350 {
351 if (cert == NULL)
352 {
353 return NULL;
354 }
355
356 for (; cert != NULL; cert = cert->next)
357 {
358 certificate_t *certificate = cert->cert;
359 identification_t *cert_subject;
360 chunk_t cert_subject_dn;
361
362 /* compare the keyid with the certificate's subjectKeyIdentifier */
363 if (keyid.ptr)
364 {
365 x509_t *x509 = (x509_t*)certificate;
366 chunk_t subjectKeyId;
367
368 subjectKeyId = x509->get_subjectKeyIdentifier(x509);
369 if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
370 {
371 continue;
372 }
373 }
374
375 /* compare the subjectDistinguishedNames */
376 cert_subject = certificate->get_subject(certificate);
377 cert_subject_dn = cert_subject->get_encoding(cert_subject);
378 if (!same_dn(subject, cert_subject_dn))
379 {
380 continue;
381 }
382
383 /* we found the cacert */
384 return cert;
385 }
386 return NULL;
387 }
388
389 /* establish trust into a candidate authcert by going up the trust chain.
390 * validity and revocation status are not checked.
391 */
392 bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
393 {
394 int pathlen;
395
396 lock_authcert_list("trust_authcert_candidate");
397
398 for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
399 {
400 certificate_t *certificate = cert->cert;
401 x509_t *x509 = (x509_t*)certificate;
402 identification_t *subject = certificate->get_subject(certificate);
403 identification_t *issuer = certificate->get_issuer(certificate);
404 chunk_t issuer_dn = issuer->get_encoding(issuer);
405 chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
406 const x509cert_t *authcert = NULL;
407
408 DBG(DBG_CONTROL,
409 DBG_log("subject: '%Y'", subject);
410 DBG_log("issuer: '%Y'", issuer);
411 if (authKeyID.ptr != NULL)
412 {
413 DBG_log("authkey: %#B", &authKeyID);
414 }
415 )
416
417 /* search in alternative chain first */
418 authcert = get_alt_cacert(issuer_dn, authKeyID, alt_chain);
419
420 if (authcert != NULL)
421 {
422 DBG(DBG_CONTROL,
423 DBG_log("issuer cacert found in alternative chain")
424 )
425 }
426 else
427 {
428 /* search in trusted chain */
429 authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA);
430
431 if (authcert != NULL)
432 {
433 DBG(DBG_CONTROL,
434 DBG_log("issuer cacert found")
435 )
436 }
437 else
438 {
439 plog("issuer cacert not found");
440 unlock_authcert_list("trust_authcert_candidate");
441 return FALSE;
442 }
443 }
444
445 if (!certificate->issued_by(certificate, authcert->cert))
446 {
447 plog("certificate signature is invalid");
448 unlock_authcert_list("trust_authcert_candidate");
449 return FALSE;
450 }
451 DBG(DBG_CONTROL,
452 DBG_log("certificate signature is valid")
453 )
454
455 /* check if cert is a self-signed root ca */
456 if (pathlen > 0 && (x509->get_flags(x509) & X509_SELF_SIGNED))
457 {
458 DBG(DBG_CONTROL,
459 DBG_log("reached self-signed root ca")
460 )
461 unlock_authcert_list("trust_authcert_candidate");
462 return TRUE;
463 }
464
465 /* go up one step in the trust chain */
466 cert = authcert;
467 }
468 plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
469 unlock_authcert_list("trust_authcert_candidate");
470 return FALSE;
471 }
472
473 /*
474 * get a CA info record with a given authName or authKeyID
475 */
476 ca_info_t* get_ca_info(chunk_t authname, chunk_t keyid)
477 {
478 ca_info_t *ca= ca_infos;
479
480 while (ca!= NULL)
481 {
482 if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID)
483 : same_dn(authname, ca->authName))
484 {
485 return ca;
486 }
487 ca = ca->next;
488 }
489 return NULL;
490 }
491
492
493 /*
494 * free the dynamic memory used by a ca_info record
495 */
496 static void
497 free_ca_info(ca_info_t* ca_info)
498 {
499 if (ca_info == NULL)
500 {
501 return;
502 }
503 ca_info->crluris->destroy_function(ca_info->crluris, free);
504 free(ca_info->name);
505 free(ca_info->ldaphost);
506 free(ca_info->ldapbase);
507 free(ca_info->ocspuri);
508 free(ca_info->authName.ptr);
509 free(ca_info->authKeyID.ptr);
510 free(ca_info);
511 }
512
513 /*
514 * free all CA certificates
515 */
516 void free_ca_infos(void)
517 {
518 while (ca_infos != NULL)
519 {
520 ca_info_t *ca = ca_infos;
521
522 ca_infos = ca_infos->next;
523 free_ca_info(ca);
524 }
525 }
526
527 /*
528 * find a CA information record by name and optionally delete it
529 */
530 bool find_ca_info_by_name(const char *name, bool delete)
531 {
532 ca_info_t **ca_p = &ca_infos;
533 ca_info_t *ca = *ca_p;
534
535 while (ca != NULL)
536 {
537 /* is there already an entry? */
538 if (streq(name, ca->name))
539 {
540 if (delete)
541 {
542 lock_ca_info_list("find_ca_info_by_name");
543 *ca_p = ca->next;
544 free_ca_info(ca);
545 plog("deleting ca description \"%s\"", name);
546 unlock_ca_info_list("find_ca_info_by_name");
547 }
548 return TRUE;
549 }
550 ca_p = &ca->next;
551 ca = *ca_p;
552 }
553 return FALSE;
554 }
555
556 /*
557 * Create an empty ca_info_t record
558 */
559 ca_info_t* create_ca_info(void)
560 {
561 ca_info_t *ca_info = malloc_thing(ca_info_t);
562
563 memset(ca_info, 0, sizeof(ca_info_t));
564 ca_info->crluris = linked_list_create();
565
566 return ca_info;
567 }
568
569 /**
570 * Adds a CA description to a chained list
571 */
572 void add_ca_info(const whack_message_t *msg)
573 {
574 smartcard_t *sc = NULL;
575 cert_t cert;
576 bool valid_cert = FALSE;
577 bool cached_cert = FALSE;
578
579 if (find_ca_info_by_name(msg->name, FALSE))
580 {
581 loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name);
582 return;
583 }
584
585 if (scx_on_smartcard(msg->cacert))
586 {
587 /* load CA cert from smartcard */
588 valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert);
589 }
590 else
591 {
592 /* load CA cert from file */
593 valid_cert = load_ca_cert(msg->cacert, &cert);
594 }
595
596 if (valid_cert)
597 {
598 x509cert_t *cacert = cert.u.x509;
599 certificate_t *certificate = cacert->cert;
600 x509_t *x509 = (x509_t*)certificate;
601 identification_t *subject = certificate->get_subject(certificate);
602 chunk_t subject_dn = subject->get_encoding(subject);
603 chunk_t subjectKeyID = x509->get_subjectKeyIdentifier(x509);
604 ca_info_t *ca = NULL;
605
606 /* does the authname already exist? */
607 ca = get_ca_info(subject_dn, subjectKeyID);
608
609 if (ca != NULL)
610 {
611 /* ca_info is already present */
612 loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found,"
613 "ignoring \"%s\"", ca->name, msg->name);
614 free_x509cert(cacert);
615 return;
616 }
617
618 plog("added ca description \"%s\"", msg->name);
619
620 /* create and initialize new ca_info record */
621 ca = create_ca_info();
622
623 /* name */
624 ca->name = clone_str(msg->name);
625
626 /* authName */
627 ca->authName = chunk_clone(subject_dn);
628 DBG(DBG_CONTROL,
629 DBG_log("authname: '%Y'", subject)
630 )
631
632 /* authKeyID */
633 if (subjectKeyID.ptr)
634 {
635 ca->authKeyID = chunk_clone(subjectKeyID);
636 DBG(DBG_CONTROL | DBG_PARSING ,
637 DBG_log("authkey: %#B", &subjectKeyID)
638 )
639 }
640
641 /* ldaphost */
642 ca->ldaphost = clone_str(msg->ldaphost);
643
644 /* ldapbase */
645 ca->ldapbase = clone_str(msg->ldapbase);
646
647 /* ocspuri */
648 if (msg->ocspuri != NULL)
649 {
650 if (strncasecmp(msg->ocspuri, "http", 4) == 0)
651 ca->ocspuri = clone_str(msg->ocspuri);
652 else
653 plog(" ignoring ocspuri with unkown protocol");
654 }
655
656 /* add crl uris */
657 add_distribution_point(ca->crluris, msg->crluri);
658 add_distribution_point(ca->crluris, msg->crluri2);
659
660 /* strictrlpolicy */
661 ca->strictcrlpolicy = msg->whack_strict;
662
663 /* insert ca_info record into the chained list */
664 lock_ca_info_list("add_ca_info");
665
666 ca->next = ca_infos;
667 ca_infos = ca;
668 ca->installed = time(NULL);
669
670 unlock_ca_info_list("add_ca_info");
671
672 /* add cacert to list of authcerts */
673 cacert = add_authcert(cacert, AUTH_CA);
674 if (!cached_cert && sc != NULL)
675 {
676 if (sc->last_cert.type == CERT_X509_SIGNATURE)
677 sc->last_cert.u.x509->count--;
678 sc->last_cert.u.x509 = cacert;
679 share_cert(sc->last_cert);
680 }
681 if (sc != NULL)
682 time(&sc->last_load);
683 }
684 }
685
686 /*
687 * list all ca_info records in the chained list
688 */
689 void list_ca_infos(bool utc)
690 {
691 ca_info_t *ca = ca_infos;
692
693 if (ca != NULL)
694 {
695 whack_log(RC_COMMENT, " ");
696 whack_log(RC_COMMENT, "List of X.509 CA Information Records:");
697 whack_log(RC_COMMENT, " ");
698 }
699
700 while (ca != NULL)
701 {
702 u_char buf[BUF_LEN];
703
704 /* strictpolicy per CA not supported yet
705 *
706 whack_log(RC_COMMENT, "%T, \"%s\", strictcrlpolicy: %s"
707 , &ca->installed, utc, ca->name
708 , ca->strictcrlpolicy? "yes":"no");
709 */
710 whack_log(RC_COMMENT, "%T, \"%s\"", &ca->installed, utc, ca->name);
711 dntoa(buf, BUF_LEN, ca->authName);
712 whack_log(RC_COMMENT, " authname: '%s'", buf);
713 if (ca->ldaphost != NULL)
714 whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost);
715 if (ca->ldapbase != NULL)
716 whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase);
717 if (ca->ocspuri != NULL)
718 whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri);
719
720 list_distribution_points(ca->crluris);
721
722 if (ca->authKeyID.ptr != NULL)
723 {
724 datatot(ca->authKeyID.ptr, ca->authKeyID.len, ':'
725 , buf, BUF_LEN);
726 whack_log(RC_COMMENT, " authkey: %s", buf);
727 }
728 ca = ca->next;
729 }
730 }
731
732