321e98adc0c2f720f1fad0b022d3c02fe3bdd2cb
[strongswan.git] / src / pluto / crl.c
1 /* Support of X.509 certificate revocation lists (CRLs)
2 * Copyright (C) 2000-2009 Andreas Steffen
3 *
4 * HSR 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 <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <dirent.h>
22 #include <time.h>
23 #include <sys/types.h>
24
25 #include <freeswan.h>
26 #include <ipsec_policy.h>
27
28 #include <asn1/asn1.h>
29 #include <asn1/asn1_parser.h>
30 #include <asn1/oid.h>
31
32 #include "constants.h"
33 #include "defs.h"
34 #include "log.h"
35 #include "x509.h"
36 #include "crl.h"
37 #include "ca.h"
38 #include "certs.h"
39 #include "keys.h"
40 #include "whack.h"
41 #include "fetch.h"
42 #include "sha1.h"
43
44 /* chained lists of X.509 crls */
45
46 static x509crl_t *x509crls = NULL;
47
48 /**
49 * ASN.1 definition of an X.509 certificate revocation list
50 */
51 static const asn1Object_t crlObjects[] = {
52 { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
53 { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
54 { 2, "version", ASN1_INTEGER, ASN1_OPT |
55 ASN1_BODY }, /* 2 */
56 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
57 { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */
58 { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
59 { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */
60 { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */
61 { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT |
62 ASN1_LOOP }, /* 8 */
63 { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */
64 { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */
65 { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */
66 { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT |
67 ASN1_LOOP }, /* 12 */
68 { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
69 { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */
70 { 6, "critical", ASN1_BOOLEAN, ASN1_DEF |
71 ASN1_BODY }, /* 15 */
72 { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */
73 { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */
74 { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */
75 { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */
76 { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */
77 { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */
78 { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */
79 { 5, "critical", ASN1_BOOLEAN, ASN1_DEF |
80 ASN1_BODY }, /* 23 */
81 { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
82 { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
83 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
84 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */
85 { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 28 */
86 { 0, "exit", ASN1_EOC, ASN1_EXIT }
87 };
88
89 #define CRL_OBJ_CERTIFICATE_LIST 0
90 #define CRL_OBJ_TBS_CERT_LIST 1
91 #define CRL_OBJ_VERSION 2
92 #define CRL_OBJ_SIG_ALG 4
93 #define CRL_OBJ_ISSUER 5
94 #define CRL_OBJ_THIS_UPDATE 6
95 #define CRL_OBJ_NEXT_UPDATE 7
96 #define CRL_OBJ_USER_CERTIFICATE 10
97 #define CRL_OBJ_REVOCATION_DATE 11
98 #define CRL_OBJ_CRL_ENTRY_EXTN_ID 14
99 #define CRL_OBJ_CRL_ENTRY_CRITICAL 15
100 #define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16
101 #define CRL_OBJ_EXTN_ID 22
102 #define CRL_OBJ_CRITICAL 23
103 #define CRL_OBJ_EXTN_VALUE 24
104 #define CRL_OBJ_ALGORITHM 27
105 #define CRL_OBJ_SIGNATURE 28
106
107 const x509crl_t empty_x509crl = {
108 NULL , /* *next */
109 UNDEFINED_TIME, /* installed */
110 NULL , /* distributionPoints */
111 { NULL, 0 } , /* certificateList */
112 { NULL, 0 } , /* tbsCertList */
113 1 , /* version */
114 OID_UNKNOWN , /* sigAlg */
115 { NULL, 0 } , /* issuer */
116 UNDEFINED_TIME, /* thisUpdate */
117 UNDEFINED_TIME, /* nextUpdate */
118 NULL , /* revokedCertificates */
119 /* crlExtensions */
120 /* extension */
121 /* extnID */
122 /* critical */
123 /* extnValue */
124 { NULL, 0 } , /* authKeyID */
125 { NULL, 0 } , /* authKeySerialNumber */
126 { NULL, 0 } , /* crlNumber */
127 OID_UNKNOWN , /* algorithm */
128 { NULL, 0 } /* signature */
129 };
130
131 /**
132 * Get the X.509 CRL with a given issuer
133 */
134 static x509crl_t* get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid)
135 {
136 x509crl_t *crl = x509crls;
137 x509crl_t *prev_crl = NULL;
138
139 while (crl != NULL)
140 {
141 if ((keyid.ptr != NULL && crl->authKeyID.ptr != NULL)
142 ? same_keyid(keyid, crl->authKeyID)
143 : (same_dn(crl->issuer, issuer) && same_serial(serial, crl->authKeySerialNumber)))
144 {
145 if (crl != x509crls)
146 {
147 /* bring the CRL up front */
148 prev_crl->next = crl->next;
149 crl->next = x509crls;
150 x509crls = crl;
151 }
152 return crl;
153 }
154 prev_crl = crl;
155 crl = crl->next;
156 }
157 return NULL;
158 }
159
160 /**
161 * Free the dynamic memory used to store revoked certificates
162 */
163 static void free_revoked_certs(revokedCert_t* revokedCerts)
164 {
165 while (revokedCerts != NULL)
166 {
167 revokedCert_t * revokedCert = revokedCerts;
168 revokedCerts = revokedCert->next;
169 free(revokedCert);
170 }
171 }
172
173 /**
174 * Free the dynamic memory used to store CRLs
175 */
176 void free_crl(x509crl_t *crl)
177 {
178 free_revoked_certs(crl->revokedCertificates);
179 free_generalNames(crl->distributionPoints, TRUE);
180 free(crl->certificateList.ptr);
181 free(crl);
182 }
183
184 static void free_first_crl(void)
185 {
186 x509crl_t *crl = x509crls;
187
188 x509crls = crl->next;
189 free_crl(crl);
190 }
191
192 void free_crls(void)
193 {
194 lock_crl_list("free_crls");
195
196 while (x509crls != NULL)
197 free_first_crl();
198
199 unlock_crl_list("free_crls");
200 }
201
202 /**
203 * Insert X.509 CRL into chained list
204 */
205 bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl)
206 {
207 x509crl_t *crl = malloc_thing(x509crl_t);
208
209 *crl = empty_x509crl;
210
211 if (parse_x509crl(blob, 0, crl))
212 {
213 x509cert_t *issuer_cert;
214 x509crl_t *oldcrl;
215 bool valid_sig;
216 generalName_t *gn;
217
218 /* add distribution point */
219 gn = malloc_thing(generalName_t);
220 gn->kind = GN_URI;
221 gn->name = crl_uri;
222 gn->next = crl->distributionPoints;
223 crl->distributionPoints = gn;
224
225 lock_authcert_list("insert_crl");
226 /* get the issuer cacert */
227 issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber,
228 crl->authKeyID, AUTH_CA);
229 if (issuer_cert == NULL)
230 {
231 plog("crl issuer cacert not found");
232 free_crl(crl);
233 unlock_authcert_list("insert_crl");
234 return FALSE;
235 }
236 DBG(DBG_CONTROL,
237 DBG_log("crl issuer cacert found")
238 )
239
240 /* check the issuer's signature of the crl */
241 valid_sig = check_signature(crl->tbsCertList, crl->signature
242 , crl->algorithm, crl->algorithm, issuer_cert);
243 unlock_authcert_list("insert_crl");
244
245 if (!valid_sig)
246 {
247 free_crl(crl);
248 return FALSE;
249 }
250 DBG(DBG_CONTROL,
251 DBG_log("crl signature is valid")
252 )
253
254 lock_crl_list("insert_crl");
255 oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber
256 , crl->authKeyID);
257
258 if (oldcrl != NULL)
259 {
260 if (crl->thisUpdate > oldcrl->thisUpdate)
261 {
262 /* keep any known CRL distribution points */
263 add_distribution_points(oldcrl->distributionPoints
264 , &crl->distributionPoints);
265
266 /* now delete the old CRL */
267 free_first_crl();
268 DBG(DBG_CONTROL,
269 DBG_log("thisUpdate is newer - existing crl deleted")
270 )
271 }
272 else
273 {
274 unlock_crl_list("insert_crls");
275 DBG(DBG_CONTROL,
276 DBG_log("thisUpdate is not newer - existing crl not replaced");
277 )
278 free_crl(crl);
279 return oldcrl->nextUpdate - time(NULL) > 2*crl_check_interval;
280 }
281 }
282
283 /* insert new CRL */
284 crl->next = x509crls;
285 x509crls = crl;
286
287 unlock_crl_list("insert_crl");
288
289 /* If crl caching is enabled then the crl is saved locally.
290 * Only http or ldap URIs are cached but not local file URIs.
291 * The issuer's subjectKeyID is used as a unique filename
292 */
293 if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0)
294 {
295 char path[BUF_LEN];
296 char buf[BUF_LEN];
297 char digest_buf[SHA1_DIGEST_SIZE];
298 chunk_t subjectKeyID = { digest_buf, SHA1_DIGEST_SIZE };
299
300 if (issuer_cert->subjectKeyID.ptr == NULL)
301 compute_subjectKeyID(issuer_cert, subjectKeyID);
302 else
303 subjectKeyID = issuer_cert->subjectKeyID;
304
305 datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN);
306 snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf);
307 chunk_write(crl->certificateList, path, "crl", 0022, TRUE);
308 }
309
310 /* is the fetched crl valid? */
311 return crl->nextUpdate - time(NULL) > 2*crl_check_interval;
312 }
313 else
314 {
315 plog(" error in X.509 crl");
316 free_crl(crl);
317 return FALSE;
318 }
319 }
320
321 /**
322 * Loads CRLs
323 */
324 void load_crls(void)
325 {
326 struct dirent **filelist;
327 u_char buf[BUF_LEN];
328 u_char *save_dir;
329 int n;
330
331 /* change directory to specified path */
332 save_dir = getcwd(buf, BUF_LEN);
333 if (chdir(CRL_PATH))
334 {
335 plog("Could not change to directory '%s'", CRL_PATH);
336 }
337 else
338 {
339 plog("Changing to directory '%s'", CRL_PATH);
340 n = scandir(CRL_PATH, &filelist, file_select, alphasort);
341
342 if (n < 0)
343 plog(" scandir() error");
344 else
345 {
346 while (n--)
347 {
348 bool pgp = FALSE;
349 chunk_t blob = chunk_empty;
350 char *filename = filelist[n]->d_name;
351
352 if (load_coded_file(filename, NULL, "crl", &blob, &pgp))
353 {
354 chunk_t crl_uri;
355
356 crl_uri.len = 7 + sizeof(CRL_PATH) + strlen(filename);
357 crl_uri.ptr = malloc(crl_uri.len + 1);
358
359 /* build CRL file URI */
360 snprintf(crl_uri.ptr, crl_uri.len + 1, "file://%s/%s"
361 , CRL_PATH, filename);
362
363 insert_crl(blob, crl_uri, FALSE);
364 }
365 free(filelist[n]);
366 }
367 free(filelist);
368 }
369 }
370 /* restore directory path */
371 ignore_result(chdir(save_dir));
372 }
373
374 /**
375 * Parses a CRL revocation reason code
376 */
377 static crl_reason_t parse_crl_reasonCode(chunk_t object)
378 {
379 crl_reason_t reason = REASON_UNSPECIFIED;
380
381 if (*object.ptr == ASN1_ENUMERATED
382 && asn1_length(&object) == 1)
383 {
384 reason = *object.ptr;
385 }
386
387 DBG(DBG_PARSING,
388 DBG_log(" '%N'", crl_reason_names, reason)
389 )
390 return reason;
391 }
392
393 /*
394 * Parses an X.509 CRL
395 */
396 bool parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl)
397 {
398 u_char buf[BUF_LEN];
399 asn1_parser_t *parser;
400 chunk_t extnID;
401 chunk_t userCertificate = chunk_empty;
402 chunk_t object;
403 int objectID;
404 bool success = FALSE;
405 bool critical;
406
407 parser = asn1_parser_create(crlObjects, blob);
408
409 while (parser->iterate(parser, &objectID, &object))
410 {
411 u_int level = parser->get_level(parser)+1;
412
413 switch (objectID) {
414 case CRL_OBJ_CERTIFICATE_LIST:
415 crl->certificateList = object;
416 break;
417 case CRL_OBJ_TBS_CERT_LIST:
418 crl->tbsCertList = object;
419 break;
420 case CRL_OBJ_VERSION:
421 crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
422 DBG(DBG_PARSING,
423 DBG_log(" v%d", crl->version);
424 )
425 break;
426 case CRL_OBJ_SIG_ALG:
427 crl->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL);
428 break;
429 case CRL_OBJ_ISSUER:
430 crl->issuer = object;
431 DBG(DBG_PARSING,
432 dntoa(buf, BUF_LEN, object);
433 DBG_log(" '%s'",buf)
434 )
435 break;
436 case CRL_OBJ_THIS_UPDATE:
437 crl->thisUpdate = asn1_parse_time(object, level);
438 break;
439 case CRL_OBJ_NEXT_UPDATE:
440 crl->nextUpdate = asn1_parse_time(object, level);
441 break;
442 case CRL_OBJ_USER_CERTIFICATE:
443 userCertificate = object;
444 break;
445 case CRL_OBJ_REVOCATION_DATE:
446 {
447 /* put all the serial numbers and the revocation date in a chained list
448 with revocedCertificates pointing to the first revoked certificate */
449
450 revokedCert_t *revokedCert = malloc_thing(revokedCert_t);
451 revokedCert->userCertificate = userCertificate;
452 revokedCert->revocationDate = asn1_parse_time(object, level);
453 revokedCert->revocationReason = REASON_UNSPECIFIED;
454 revokedCert->next = crl->revokedCertificates;
455 crl->revokedCertificates = revokedCert;
456 }
457 break;
458 case CRL_OBJ_CRL_ENTRY_EXTN_ID:
459 case CRL_OBJ_EXTN_ID:
460 extnID = object;
461 break;
462 case CRL_OBJ_CRL_ENTRY_CRITICAL:
463 case CRL_OBJ_CRITICAL:
464 critical = object.len && *object.ptr;
465 DBG(DBG_PARSING,
466 DBG_log(" %s",(critical)?"TRUE":"FALSE");
467 )
468 break;
469 case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
470 case CRL_OBJ_EXTN_VALUE:
471 {
472 u_int extn_oid = asn1_known_oid(extnID);
473
474 if (extn_oid == OID_CRL_REASON_CODE)
475 {
476 crl->revokedCertificates->revocationReason =
477 parse_crl_reasonCode(object);
478 }
479 else if (extn_oid == OID_AUTHORITY_KEY_ID)
480 {
481 parse_authorityKeyIdentifier(object, level
482 , &crl->authKeyID, &crl->authKeySerialNumber);
483 }
484 else if (extn_oid == OID_CRL_NUMBER)
485 {
486 if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
487 level, "crlNumber"))
488 {
489 goto end;
490 }
491 crl->crlNumber = object;
492 }
493 }
494 break;
495 case CRL_OBJ_ALGORITHM:
496 crl->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
497 break;
498 case CRL_OBJ_SIGNATURE:
499 crl->signature = object;
500 break;
501 default:
502 break;
503 }
504 }
505 success = parser->success(parser);
506 time(&crl->installed);
507
508 end:
509 parser->destroy(parser);
510 return success;
511 }
512
513 /* Checks if the current certificate is revoked. It goes through the
514 * list of revoked certificates of the corresponding crl. Either the
515 * status CERT_GOOD or CERT_REVOKED is returned
516 */
517 static cert_status_t
518 check_revocation(const x509crl_t *crl, chunk_t serial
519 , time_t *revocationDate, crl_reason_t * revocationReason)
520 {
521 revokedCert_t *revokedCert = crl->revokedCertificates;
522
523 *revocationDate = UNDEFINED_TIME;
524 *revocationReason = REASON_UNSPECIFIED;
525
526 DBG(DBG_CONTROL,
527 DBG_dump_chunk("serial number:", serial)
528 )
529
530 while(revokedCert != NULL)
531 {
532 /* compare serial numbers */
533 if (revokedCert->userCertificate.len == serial.len &&
534 memeq(revokedCert->userCertificate.ptr, serial.ptr, serial.len))
535 {
536 *revocationDate = revokedCert->revocationDate;
537 *revocationReason = revokedCert->revocationReason;
538 return CERT_REVOKED;
539 }
540 revokedCert = revokedCert->next;
541 }
542 return CERT_GOOD;
543 }
544
545 /*
546 * check if any crls are about to expire
547 */
548 void
549 check_crls(void)
550 {
551 x509crl_t *crl;
552
553 lock_crl_list("check_crls");
554 crl = x509crls;
555
556 while (crl != NULL)
557 {
558 time_t time_left = crl->nextUpdate - time(NULL);
559 u_char buf[BUF_LEN];
560
561 DBG(DBG_CONTROL,
562 dntoa(buf, BUF_LEN, crl->issuer);
563 DBG_log("issuer: '%s'",buf);
564 if (crl->authKeyID.ptr != NULL)
565 {
566 datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':'
567 , buf, BUF_LEN);
568 DBG_log("authkey: %s", buf);
569 }
570 DBG_log("%ld seconds left", time_left)
571 )
572 if (time_left < 2*crl_check_interval)
573 {
574 fetch_req_t *req = build_crl_fetch_request(crl->issuer
575 , crl->authKeySerialNumber
576 , crl->authKeyID, crl->distributionPoints);
577 add_crl_fetch_request(req);
578 }
579 crl = crl->next;
580 }
581 unlock_crl_list("check_crls");
582 }
583
584 /*
585 * verify if a cert hasn't been revoked by a crl
586 */
587 cert_status_t
588 verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate
589 , crl_reason_t *revocationReason)
590 {
591 x509crl_t *crl;
592
593 ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber
594 , cert->authKeyID);
595
596 generalName_t *crluri = (ca == NULL)? NULL : ca->crluri;
597
598 *revocationDate = UNDEFINED_TIME;
599 *revocationReason = REASON_UNSPECIFIED;
600
601 lock_crl_list("verify_by_crl");
602 crl = get_x509crl(cert->issuer, cert->authKeySerialNumber, cert->authKeyID);
603
604 if (crl == NULL)
605 {
606 unlock_crl_list("verify_by_crl");
607 plog("crl not found");
608
609 if (cert->crlDistributionPoints != NULL)
610 {
611 fetch_req_t *req = build_crl_fetch_request(cert->issuer
612 , cert->authKeySerialNumber
613 , cert->authKeyID, cert->crlDistributionPoints);
614 add_crl_fetch_request(req);
615 }
616
617 if (crluri != NULL)
618 {
619 fetch_req_t *req = build_crl_fetch_request(cert->issuer
620 , cert->authKeySerialNumber
621 , cert->authKeyID, crluri);
622 add_crl_fetch_request(req);
623 }
624
625 if (cert->crlDistributionPoints != 0 || crluri != NULL)
626 {
627 wake_fetch_thread("verify_by_crl");
628 return CERT_UNKNOWN;
629 }
630 else
631 return CERT_UNDEFINED;
632 }
633 else
634 {
635 x509cert_t *issuer_cert;
636 bool valid;
637
638 DBG(DBG_CONTROL,
639 DBG_log("crl found")
640 )
641
642 add_distribution_points(cert->crlDistributionPoints
643 , &crl->distributionPoints);
644
645 add_distribution_points(crluri
646 , &crl->distributionPoints);
647
648 lock_authcert_list("verify_by_crl");
649
650 issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber
651 , crl->authKeyID, AUTH_CA);
652 valid = check_signature(crl->tbsCertList, crl->signature
653 , crl->algorithm, crl->algorithm, issuer_cert);
654
655 unlock_authcert_list("verify_by_crl");
656
657 if (valid)
658 {
659 cert_status_t status;
660
661 DBG(DBG_CONTROL,
662 DBG_log("crl signature is valid")
663 )
664 /* return the expiration date */
665 *until = crl->nextUpdate;
666
667 /* has the certificate been revoked? */
668 status = check_revocation(crl, cert->serialNumber, revocationDate
669 , revocationReason);
670
671 if (*until < time(NULL))
672 {
673 fetch_req_t *req;
674
675 plog("crl update is overdue since %T", until, TRUE);
676
677 /* try to fetch a crl update */
678 req = build_crl_fetch_request(crl->issuer
679 , crl->authKeySerialNumber
680 , crl->authKeyID, crl->distributionPoints);
681 unlock_crl_list("verify_by_crl");
682
683 add_crl_fetch_request(req);
684 wake_fetch_thread("verify_by_crl");
685 }
686 else
687 {
688 unlock_crl_list("verify_by_crl");
689 DBG(DBG_CONTROL,
690 DBG_log("crl is valid")
691 )
692 }
693 return status;
694 }
695 else
696 {
697 unlock_crl_list("verify_by_crl");
698 plog("crl signature is invalid");
699 return CERT_UNKNOWN;
700 }
701 }
702 }
703
704 /*
705 * list all X.509 crls in the chained list
706 */
707 void
708 list_crls(bool utc, bool strict)
709 {
710 x509crl_t *crl;
711
712 lock_crl_list("list_crls");
713 crl = x509crls;
714
715 if (crl != NULL)
716 {
717 whack_log(RC_COMMENT, " ");
718 whack_log(RC_COMMENT, "List of X.509 CRLs:");
719 whack_log(RC_COMMENT, " ");
720 }
721
722 while (crl != NULL)
723 {
724 u_char buf[BUF_LEN];
725 u_int revoked = 0;
726 revokedCert_t *revokedCert = crl->revokedCertificates;
727
728 /* count number of revoked certificates in CRL */
729 while (revokedCert != NULL)
730 {
731 revoked++;
732 revokedCert = revokedCert->next;
733 }
734
735 whack_log(RC_COMMENT, "%T, revoked certs: %d",
736 &crl->installed, utc, revoked);
737 dntoa(buf, BUF_LEN, crl->issuer);
738 whack_log(RC_COMMENT, " issuer: '%s'", buf);
739 if (crl->crlNumber.ptr != NULL)
740 {
741 datatot(crl->crlNumber.ptr, crl->crlNumber.len, ':'
742 , buf, BUF_LEN);
743 whack_log(RC_COMMENT, " crlnumber: %s", buf);
744 }
745 list_distribution_points(crl->distributionPoints);
746
747 whack_log(RC_COMMENT, " updates: this %T",
748 &crl->thisUpdate, utc);
749 whack_log(RC_COMMENT, " next %T %s",
750 &crl->nextUpdate, utc,
751 check_expiry(crl->nextUpdate, CRL_WARNING_INTERVAL, strict));
752 if (crl->authKeyID.ptr != NULL)
753 {
754 datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':'
755 , buf, BUF_LEN);
756 whack_log(RC_COMMENT, " authkey: %s", buf);
757 }
758 if (crl->authKeySerialNumber.ptr != NULL)
759 {
760 datatot(crl->authKeySerialNumber.ptr, crl->authKeySerialNumber.len, ':'
761 , buf, BUF_LEN);
762 whack_log(RC_COMMENT, " aserial: %s", buf);
763 }
764
765 crl = crl->next;
766 }
767 unlock_crl_list("list_crls");
768 }
769