From: Martin Willi Date: Wed, 29 Oct 2025 09:35:10 +0000 (+0100) Subject: revocation: Block only one thread per URL after a previous CRL fetch failed X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Frevocation-fetcher;p=thirdparty%2Fstrongswan.git revocation: Block only one thread per URL after a previous CRL fetch failed If a CRL server is unresponsive, all threads trying to fetch this CRL will block execution. If a recent previous attempt to fetch the CRL failed, it is likely that it will fail again. While it makes sense to retry fetching the CRL on demand with one thread, it hardly does to block additional threads while the first one is blocked during the fetch. So remember the timestamp of the last CRL fetch failure per URL, and do not block more than one thread in the CRL fetch for some time. This time is a multiple of the configured fetch timeout, so that it works well for any configured value. With the default configuration, a failing CRL fetch will impact concurrent CRL fetches for the same URL for 30s. --- diff --git a/src/libstrongswan/plugins/revocation/revocation_fetcher.c b/src/libstrongswan/plugins/revocation/revocation_fetcher.c index 8d0cd602bc..36c74921ea 100644 --- a/src/libstrongswan/plugins/revocation/revocation_fetcher.c +++ b/src/libstrongswan/plugins/revocation/revocation_fetcher.c @@ -26,6 +26,9 @@ #include #include +/* number of fetch timeouts to degrade a CRL fetch after a failure */ +#define CRL_DEGRADATION_TIMES 3 + typedef struct private_revocation_fetcher_t private_revocation_fetcher_t; /** @@ -71,6 +74,11 @@ struct crl_fetch_t { */ u_int fetchers; + /** + * Has the previous fetch failed, until when is this URL degraded? + */ + time_t failing; + /** * CRL received in the currently active fetch. */ @@ -119,6 +127,14 @@ static certificate_t *start_crl_fetch(private_revocation_fetcher_t *this, crl = do_crl_fetch(this, fetch->url, timeout); this->mutex->lock(this->mutex); fetch->crl = crl; + if (crl) + { + fetch->failing = 0; + } + else + { + fetch->failing = time_monotonic(NULL) + timeout * CRL_DEGRADATION_TIMES; + } while (fetch->fetchers > 1) { fetch->condvar->signal(fetch->condvar); @@ -137,6 +153,12 @@ static certificate_t *wait_for_crl(private_revocation_fetcher_t *this, { certificate_t *crl = NULL; + if (fetch->failing && fetch->failing > time_monotonic(NULL)) + { + DBG1(DBG_CFG, " crl fetch from '%s' recently failed, skipping", + fetch->url); + return NULL; + } DBG1(DBG_CFG, " waiting for crl fetch from '%s' ...", fetch->url); if (fetch->crl) {