Skip to content

Commit df6977d

Browse files
martinwillitobiasbrunner
authored andcommitted
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.
1 parent 330a7d1 commit df6977d

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

src/libstrongswan/plugins/revocation/revocation_fetcher.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
#include <credentials/certificates/ocsp_request.h>
2727
#include <credentials/certificates/ocsp_response.h>
2828

29+
/* number of fetch timeouts to degrade a CRL fetch after a failure */
30+
#define CRL_DEGRADATION_TIMES 3
31+
2932
typedef struct private_revocation_fetcher_t private_revocation_fetcher_t;
3033

3134
/**
@@ -71,6 +74,11 @@ struct crl_fetch_t {
7174
*/
7275
u_int fetchers;
7376

77+
/**
78+
* Has the previous fetch failed, until when is this URL degraded?
79+
*/
80+
time_t failing;
81+
7482
/**
7583
* CRL received in the currently active fetch.
7684
*/
@@ -119,6 +127,14 @@ static certificate_t *start_crl_fetch(private_revocation_fetcher_t *this,
119127
crl = do_crl_fetch(this, fetch->url, timeout);
120128
this->mutex->lock(this->mutex);
121129
fetch->crl = crl;
130+
if (crl)
131+
{
132+
fetch->failing = 0;
133+
}
134+
else
135+
{
136+
fetch->failing = time_monotonic(NULL) + timeout * CRL_DEGRADATION_TIMES;
137+
}
122138
while (fetch->fetchers > 1)
123139
{
124140
fetch->condvar->signal(fetch->condvar);
@@ -137,6 +153,12 @@ static certificate_t *wait_for_crl(private_revocation_fetcher_t *this,
137153
{
138154
certificate_t *crl = NULL;
139155

156+
if (fetch->failing && fetch->failing > time_monotonic(NULL))
157+
{
158+
DBG1(DBG_CFG, " crl fetch from '%s' recently failed, skipping",
159+
fetch->url);
160+
return NULL;
161+
}
140162
DBG1(DBG_CFG, " waiting for crl fetch from '%s' ...", fetch->url);
141163
if (fetch->crl)
142164
{

0 commit comments

Comments
 (0)