Check descriptor ID in addition to HS ID when saving a v2 hs descriptor

Fixes bug 13214; reported by 'special'.
This commit is contained in:
Nick Mathewson 2014-11-03 14:02:47 -05:00
parent 9e2608b0d3
commit b10e5ac7b8
4 changed files with 29 additions and 1 deletions

7
changes/bug13214 Normal file
View File

@ -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".

View File

@ -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. "

View File

@ -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;

View File

@ -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,