commit b10e5ac7b86c459a62cfc316c8be87143d2a87e4 Author: Nick Mathewson nickm@torproject.org Date: Mon Nov 3 14:02:47 2014 -0500
Check descriptor ID in addition to HS ID when saving a v2 hs descriptor
Fixes bug 13214; reported by 'special'. --- changes/bug13214 | 7 +++++++ src/or/directory.c | 3 ++- src/or/rendcommon.c | 19 +++++++++++++++++++ src/or/rendcommon.h | 1 + 4 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/changes/bug13214 b/changes/bug13214 new file mode 100644 index 0000000..5b9758b --- /dev/null +++ b/changes/bug13214 @@ -0,0 +1,7 @@ + o Minor bugfixes (hidden services): + - When fetching hidden service descriptors, check not only for + whether we got the hidden service we had in mind, but also + whether we got the particular descriptors we wanted. This + prevents a class of inefficient but annoying DoS attacks by + hidden service directories. Fixes bug 13214; bugfix on + 0.2.1.6-alpha. Reported by "special". diff --git a/src/or/directory.c b/src/or/directory.c index 298271f..d429b7b 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2082,7 +2082,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn) (int)body_len, status_code, escaped(reason)); switch (status_code) { case 200: - switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) { + switch (rend_cache_store_v2_desc_as_client(body, + conn->requested_resource, conn->rend_data)) { case RCS_BADDESC: case RCS_NOTDIR: /* Impossible */ log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. " diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index a664b5d..e95cf48 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -1034,10 +1034,14 @@ rend_cache_store_v2_desc_as_dir(const char *desc) * If the descriptor's service ID does not match * <b>rend_query</b>->onion_address, reject it. * + * If the descriptor's descriptor ID doesn't match <b>desc_id_base32</b>, + * reject it. + * * Return an appropriate rend_cache_store_status_t. */ rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc, + const char *desc_id_base32, const rend_data_t *rend_query) { /*XXXX this seems to have a bit of duplicate code with @@ -1064,10 +1068,19 @@ rend_cache_store_v2_desc_as_client(const char *desc, time_t now = time(NULL); char key[REND_SERVICE_ID_LEN_BASE32+2]; char service_id[REND_SERVICE_ID_LEN_BASE32+1]; + char want_desc_id[DIGEST_LEN]; rend_cache_entry_t *e; rend_cache_store_status_t retval = RCS_BADDESC; tor_assert(rend_cache); tor_assert(desc); + tor_assert(desc_id_base32); + memset(want_desc_id, 0, sizeof(want_desc_id)); + if (base32_decode(want_desc_id, sizeof(want_desc_id), + desc_id_base32, strlen(desc_id_base32)) != 0) { + log_warn(LD_BUG, "Couldn't decode base32 %s for descriptor id.", + escaped_safe_str_client(desc_id_base32)); + goto err; + } /* Parse the descriptor. */ if (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content, &intro_size, &encoded_size, @@ -1086,6 +1099,12 @@ rend_cache_store_v2_desc_as_client(const char *desc, service_id, safe_str(rend_query->onion_address)); goto err; } + if (tor_memneq(desc_id, want_desc_id, DIGEST_LEN)) { + log_warn(LD_REND, "Received service descriptor for %s with incorrect " + "descriptor ID.", service_id); + goto err; + } + /* Decode/decrypt introduction points. */ if (intro_content) { int n_intro_points; diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h index 07a47ac..42a089a 100644 --- a/src/or/rendcommon.h +++ b/src/or/rendcommon.h @@ -49,6 +49,7 @@ typedef enum {
rend_cache_store_status_t rend_cache_store_v2_desc_as_dir(const char *desc); rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc, + const char *desc_id_base32, const rend_data_t *rend_query);
int rend_encode_v2_descriptors(smartlist_t *descs_out,