Merge remote-tracking branch 'public/bug11454_11457'

This commit is contained in:
Nick Mathewson 2015-02-20 01:08:12 -05:00
commit 8a9d86bf05
4 changed files with 68 additions and 27 deletions

6
changes/bug11454 Normal file
View file

@ -0,0 +1,6 @@
o Minor bugfixes:
- Remove any old authority certificates that have been superseded
for at least two days. Previously, we would keep superseded
certificates until they expired, if they were published close
in time to the certificate that superseded them.
Fixes bug 11454; bugfix on 0.2.1.8-alpha.

5
changes/bug11457 Normal file
View file

@ -0,0 +1,5 @@
o Minor bugfixes:
- If an authority operator accidentally makes a signing certificate with
a future publication time, do not discard its real signing
certificates. Fixes bug 11457; bugfix on 0.2.0.3-alpha.

View file

@ -246,6 +246,17 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
--var ## _sl_len; \
STMT_END
/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
* with the variable <b>var</b>, remove the current element in a way that
* won't confuse the loop. */
#define SMARTLIST_DEL_CURRENT_KEEPORDER(sl, var) \
STMT_BEGIN \
smartlist_del_keeporder(sl, var ## _sl_idx); \
--var ## _sl_idx; \
--var ## _sl_len; \
STMT_END
/** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
* with the variable <b>var</b>, replace the current element with <b>val</b>.
* Does not deallocate the current value of <b>var</b>.

View file

@ -449,6 +449,19 @@ trusted_dirs_flush_certs_to_disk(void)
trusted_dir_servers_certs_changed = 0;
}
static int
compare_certs_by_pubdates(const void **_a, const void **_b)
{
const authority_cert_t *cert1 = *_a, *cert2=*_b;
if (cert1->cache_info.published_on < cert2->cache_info.published_on)
return -1;
else if (cert1->cache_info.published_on > cert2->cache_info.published_on)
return 1;
else
return 0;
}
/** Remove all expired v3 authority certificates that have been superseded for
* more than 48 hours or, if not expired, that were published more than 7 days
* before being superseded. (If the most recent cert was published more than 48
@ -459,38 +472,44 @@ trusted_dirs_remove_old_certs(void)
{
time_t now = time(NULL);
#define DEAD_CERT_LIFETIME (2*24*60*60)
#define OLD_CERT_LIFETIME (7*24*60*60)
#define SUPERSEDED_CERT_LIFETIME (2*24*60*60)
if (!trusted_dir_certs)
return;
DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
authority_cert_t *newest = NULL;
SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
if (!newest || (cert->cache_info.published_on >
newest->cache_info.published_on))
newest = cert);
if (newest) {
const time_t newest_published = newest->cache_info.published_on;
SMARTLIST_FOREACH_BEGIN(cl->certs, authority_cert_t *, cert) {
int expired;
time_t cert_published;
if (newest == cert)
continue;
/* resolve spurious clang shallow analysis null pointer errors */
tor_assert(cert);
expired = now > cert->expires;
cert_published = cert->cache_info.published_on;
/* Store expired certs for 48 hours after a newer arrives;
/* Sort the list from first-published to last-published */
smartlist_sort(cl->certs, compare_certs_by_pubdates);
SMARTLIST_FOREACH_BEGIN(cl->certs, authority_cert_t *, cert) {
if (cert_sl_idx == smartlist_len(cl->certs) - 1) {
/* This is the most recently published cert. Keep it. */
continue;
}
authority_cert_t *next_cert = smartlist_get(cl->certs, cert_sl_idx+1);
const time_t next_cert_published = next_cert->cache_info.published_on;
if (next_cert_published > now) {
/* All later certs are published in the future. Keep everything
* we didn't discard. */
break;
}
int should_remove = 0;
if (cert->expires + DEAD_CERT_LIFETIME < now) {
/* Certificate has been expired for at least DEAD_CERT_LIFETIME.
* Remove it. */
should_remove = 1;
} else if (next_cert_published + SUPERSEDED_CERT_LIFETIME < now) {
/* Certificate has been superseded for OLD_CERT_LIFETIME.
* Remove it.
*/
if (expired ?
(newest_published + DEAD_CERT_LIFETIME < now) :
(cert_published + OLD_CERT_LIFETIME < newest_published)) {
SMARTLIST_DEL_CURRENT(cl->certs, cert);
authority_cert_free(cert);
trusted_dir_servers_certs_changed = 1;
}
} SMARTLIST_FOREACH_END(cert);
}
should_remove = 1;
}
if (should_remove) {
SMARTLIST_DEL_CURRENT_KEEPORDER(cl->certs, cert);
authority_cert_free(cert);
trusted_dir_servers_certs_changed = 1;
}
} SMARTLIST_FOREACH_END(cert);
} DIGESTMAP_FOREACH_END;
#undef DEAD_CERT_LIFETIME
#undef OLD_CERT_LIFETIME