Index: b/dirmngr/crlcache.c =================================================================== --- b/dirmngr/crlcache.c +++ b/dirmngr/crlcache.c @@ -2437,10 +2437,13 @@ char *issuer = NULL; ksba_name_t distpoint = NULL; ksba_name_t issuername = NULL; + ksba_crl_reason_t reason = KSBA_CRLREASON_UNSPECIFIED; char *distpoint_uri = NULL; char *issuername_uri = NULL; int any_dist_point = 0; + int any_full_list_obtained = 0; int seq; + gpg_error_t last_err = 0; /* Loop over all distribution points, get the CRLs and put them into the cache. */ @@ -2449,10 +2452,9 @@ seq = 0; while ( !(err = ksba_cert_get_crl_dist_point (cert, seq++, &distpoint, - &issuername, NULL ))) + &issuername, &reason)) ) { int name_seq; - gpg_error_t last_err = 0; if (!distpoint && !issuername) { @@ -2513,14 +2515,23 @@ continue; /* with the next name. */ } last_err = 0; + if (reason == KSBA_CRLREASON_UNSPECIFIED) + { + /* We now have obtained a CRL for this certificate that includes + recovcations for all reasons. No need to check the other + crlDPs. + + From RFC 5280 Section 4.2.1.13: + If the DistributionPoint omits the reasons field, the CRL MUST + include revocation information for all reasons. This profile + RECOMMENDS against segmenting CRLs by reason code. When a conforming + CA includes a cRLDistributionPoints extension in a certificate, it + MUST include at least one DistributionPoint that points to a CRL that + covers the certificate for all reasons. */ + any_full_list_obtained = 1; + } break; /* Ready. */ } - if (last_err) - { - err = last_err; - goto leave; - } - ksba_name_release (distpoint); distpoint = NULL; /* We don't do anything with issuername_uri yet but we keep the @@ -2531,7 +2542,20 @@ /* Close the reader. */ crl_close_reader (reader); reader = NULL; + + /* We have fetched a CRL that should contain all certificates. No + reason to look at any more crlDP's. */ + if (any_full_list_obtained) + break; + } + /* Hard failure in case a crlDP was provided but we were unable + to obtain a full CRL for this. */ + if (any_dist_point && !any_full_list_obtained) + { + err = last_err; + goto leave; } + if (gpg_err_code (err) == GPG_ERR_EOF) err = 0;