From a1d866edc9af82c2134590f7ee3c4e18156a655c Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Thu, 2 Jun 2011 02:24:18 -0700 Subject: [PATCH 1/4] Make last_hid_serv_requests functions less fragile Previously, Tor would dereference a NULL pointer and crash if lookup_last_hid_serv_request were called before the first call to directory_clean_last_hid_serv_requests. As far as I can tell, that's currently impossible, but I want that undocumented invariant to go away in case I^Wwe break it someday. --- src/or/rendclient.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 29b9d260ed..ec6e3f2bed 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -377,7 +377,17 @@ rend_client_introduction_acked(origin_circuit_t *circ, * certain queries; keys are strings consisting of base32-encoded * hidden service directory identities and base32-encoded descriptor IDs; * values are pointers to timestamps of the last requests. */ -static strmap_t *last_hid_serv_requests = NULL; +static strmap_t *last_hid_serv_requests_ = NULL; + +/** Returns last_hid_serv_requests_, initializing it to a new strmap if + * necessary. */ +static strmap_t * +get_last_hid_serv_requests(void) +{ + if (!last_hid_serv_requests_) + last_hid_serv_requests_ = strmap_new(); + return last_hid_serv_requests_; +} /** Look up the last request time to hidden service directory hs_dir * for descriptor ID desc_id_base32. If set is non-zero, @@ -391,6 +401,7 @@ lookup_last_hid_serv_request(routerstatus_t *hs_dir, char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1]; time_t *last_request_ptr; + strmap_t *last_hid_serv_requests = get_last_hid_serv_requests(); base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32), hs_dir->identity_digest, DIGEST_LEN); tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s", @@ -416,8 +427,7 @@ directory_clean_last_hid_serv_requests(void) { strmap_iter_t *iter; time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD; - if (!last_hid_serv_requests) - last_hid_serv_requests = strmap_new(); + strmap_t *last_hid_serv_requests = get_last_hid_serv_requests(); for (iter = strmap_iter_init(last_hid_serv_requests); !strmap_iter_done(iter); ) { const char *key; From b0e7925c0205a68d730025cc8832110c1675cfd7 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Thu, 2 Jun 2011 02:46:04 -0700 Subject: [PATCH 2/4] Clear last_hid_serv_requests on SIGNAL NEWNYM Fixes bug #3309. --- changes/bug3309 | 9 +++++++++ src/or/main.c | 1 + src/or/rendclient.c | 19 +++++++++++++++++++ src/or/rendclient.h | 1 + 4 files changed, 30 insertions(+) create mode 100644 changes/bug3309 diff --git a/changes/bug3309 b/changes/bug3309 new file mode 100644 index 0000000000..5df0d9d348 --- /dev/null +++ b/changes/bug3309 @@ -0,0 +1,9 @@ + o Minor bugfixes: + - Clear the table recording the time of the last request for each + hidden service descriptor from each HS directory on SIGNAL + NEWNYM. Previously, we would clear our HS descriptor cache on + SIGNAL NEWNYM, but if we had previously retrieved a descriptor + (or tried to) from every directory responsible for it, we would + refuse to fetch it again for up to 15 minutes. Bugfix on + 0.2.2.25-alpha; fixes bug 3309. + diff --git a/src/or/main.c b/src/or/main.c index adbde9044f..3c84ddaa64 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -855,6 +855,7 @@ signewnym_impl(time_t now) addressmap_clear_transient(); rend_cache_purge(); rend_client_cancel_descriptor_fetches(); + rend_client_purge_last_hid_serv_requests(); time_of_last_signewnym = now; signewnym_is_pending = 0; } diff --git a/src/or/rendclient.c b/src/or/rendclient.c index ec6e3f2bed..12b54df0d6 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -444,6 +444,25 @@ directory_clean_last_hid_serv_requests(void) } } +/** Purge the history of request times to hidden service directories, + * so that future lookups of an HS descriptor will not fail because we + * accessed all of the HSDir relays responsible for the descriptor + * recently. */ +void +rend_client_purge_last_hid_serv_requests(void) +{ + /* Don't create the table if it doesn't exist yet (and it may very + * well not exist if the user hasn't accessed any HSes)... */ + strmap_t *old_last_hid_serv_requests = last_hid_serv_requests_; + /* ... and let get_last_hid_serv_requests re-create it for us if + * necessary. */ + last_hid_serv_requests_ = NULL; + + if (old_last_hid_serv_requests != NULL) { + strmap_free(old_last_hid_serv_requests, _tor_free); + } +} + /** Determine the responsible hidden service directories for desc_id * and fetch the descriptor belonging to that ID from one of them. Only * send a request to hidden service directories that we did not try within diff --git a/src/or/rendclient.h b/src/or/rendclient.h index 6910c1a97b..2bfc850ad5 100644 --- a/src/or/rendclient.h +++ b/src/or/rendclient.h @@ -19,6 +19,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ, size_t request_len); void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query); void rend_client_cancel_descriptor_fetches(void); +void rend_client_purge_last_hid_serv_requests(void); int rend_client_remove_intro_point(extend_info_t *failed_intro, const rend_data_t *rend_query); int rend_client_rendezvous_acked(origin_circuit_t *circ, From d7af8a2f076a38d8be32798d34049ce150c8dda0 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Thu, 2 Jun 2011 02:57:29 -0700 Subject: [PATCH 3/4] Refactor HS client state-clearing code into a separate function --- src/or/main.c | 4 +--- src/or/rendclient.c | 10 ++++++++++ src/or/rendclient.h | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/or/main.c b/src/or/main.c index 3c84ddaa64..bc639dbdd8 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -853,9 +853,7 @@ signewnym_impl(time_t now) circuit_expire_all_dirty_circs(); addressmap_clear_transient(); - rend_cache_purge(); - rend_client_cancel_descriptor_fetches(); - rend_client_purge_last_hid_serv_requests(); + rend_client_purge_state(); time_of_last_signewnym = now; signewnym_is_pending = 0; } diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 12b54df0d6..329b2567d6 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -27,6 +27,16 @@ static extend_info_t *rend_client_get_random_intro_impl( const rend_cache_entry_t *rend_query, const int strict, const int warnings); +/** Purge all potentially remotely-detectable state held in the hidden + * service client code. Called on SIGNAL NEWNYM. */ +void +rend_client_purge_state(void) +{ + rend_cache_purge(); + rend_client_cancel_descriptor_fetches(); + rend_client_purge_last_hid_serv_requests(); +} + /** Called when we've established a circuit to an introduction point: * send the introduction request. */ void diff --git a/src/or/rendclient.h b/src/or/rendclient.h index 2bfc850ad5..c6cf82b3dd 100644 --- a/src/or/rendclient.h +++ b/src/or/rendclient.h @@ -12,6 +12,8 @@ #ifndef _TOR_RENDCLIENT_H #define _TOR_RENDCLIENT_H +void rend_client_purge_state(void); + void rend_client_introcirc_has_opened(origin_circuit_t *circ); void rend_client_rendcirc_has_opened(origin_circuit_t *circ); int rend_client_introduction_acked(origin_circuit_t *circ, From fc4158dad706a76acbfd3adae8b505495f1004e5 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Thu, 2 Jun 2011 03:07:09 -0700 Subject: [PATCH 4/4] Add info-level log messages during HS-client-state purge I hope these will never be useful, but having them and not needing them is better than needing them and not having them. --- changes/bug3309 | 4 ++++ src/or/rendclient.c | 1 + src/or/rendcommon.c | 4 +++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/changes/bug3309 b/changes/bug3309 index 5df0d9d348..104056d8e3 100644 --- a/changes/bug3309 +++ b/changes/bug3309 @@ -7,3 +7,7 @@ refuse to fetch it again for up to 15 minutes. Bugfix on 0.2.2.25-alpha; fixes bug 3309. + o Minor features: + - Log (at info level) when purging pieces of hidden-service-client + state on SIGNAL NEWNYM. + diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 329b2567d6..533dfb8a97 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -469,6 +469,7 @@ rend_client_purge_last_hid_serv_requests(void) last_hid_serv_requests_ = NULL; if (old_last_hid_serv_requests != NULL) { + log_info(LD_REND, "Purging client last-HS-desc-request-time table"); strmap_free(old_last_hid_serv_requests, _tor_free); } } diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 4d4a90f61a..683e11ad24 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -839,8 +839,10 @@ rend_cache_clean(void) void rend_cache_purge(void) { - if (rend_cache) + if (rend_cache) { + log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache"); strmap_free(rend_cache, _rend_cache_entry_free); + } rend_cache = strmap_new(); }