commit 912c11761c5b5b0a80e232bdc96788677300ca67 Author: George Kadianakis desnacked@riseup.net Date: Thu Jun 1 13:48:03 2017 +0300
prop224: Move some rendclient.c code to hs_common.c
Specifically move the pick_hsdir() function and all the HSDir request tracking code. We plan to use all that code both for v2 and v3.
This commit only moves code.
Signed-off-by: David Goulet dgoulet@torproject.org --- src/or/hs_common.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/or/hs_common.h | 11 +++ src/or/rendclient.c | 224 ---------------------------------------------------- src/or/rendclient.h | 1 - 4 files changed, 235 insertions(+), 225 deletions(-)
diff --git a/src/or/hs_common.c b/src/or/hs_common.c index 0529c0cdb..48d5f78bb 100644 --- a/src/or/hs_common.c +++ b/src/or/hs_common.c @@ -22,6 +22,7 @@ #include "rendcommon.h" #include "rendservice.h" #include "router.h" +#include "routerset.h" #include "shared_random.h" #include "shared_random_state.h"
@@ -1320,6 +1321,229 @@ hs_get_responsible_hsdirs(const ed25519_public_key_t *blinded_pk, smartlist_free(sorted_nodes); }
+/*********************** HSDir request tracking ***************************/ + +/** Return the period for which a hidden service directory cannot be queried + * for the same descriptor ID again, taking TestingTorNetwork into account. */ +static time_t +hsdir_requery_period(const or_options_t *options) +{ + tor_assert(options); + + if (options->TestingTorNetwork) { + return REND_HID_SERV_DIR_REQUERY_PERIOD_TESTING; + } else { + return REND_HID_SERV_DIR_REQUERY_PERIOD; + } +} + +/** Contains the last request times to hidden service directories for + * certain queries; each key is a string consisting of the + * concatenation of a base32-encoded HS directory identity digest and + * base32-encoded HS descriptor ID; each value is a pointer to a time_t + * holding the time of the last request for that descriptor ID to that + * HS directory. */ +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_; +} + +#define LAST_HID_SERV_REQUEST_KEY_LEN (REND_DESC_ID_V2_LEN_BASE32 + \ + REND_DESC_ID_V2_LEN_BASE32) + +/** Look up the last request time to hidden service directory <b>hs_dir</b> + * for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero, + * assign the current time <b>now</b> and return that. Otherwise, return the + * most recent request time, or 0 if no such request has been sent before. + */ +static time_t +lookup_last_hid_serv_request(routerstatus_t *hs_dir, + const char *desc_id_base32, + time_t now, int set) +{ + char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; + char hsdir_desc_comb_id[LAST_HID_SERV_REQUEST_KEY_LEN + 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", + hsdir_id_base32, + desc_id_base32); + /* XXX++?? tor_assert(strlen(hsdir_desc_comb_id) == + LAST_HID_SERV_REQUEST_KEY_LEN); */ + if (set) { + time_t *oldptr; + last_request_ptr = tor_malloc_zero(sizeof(time_t)); + *last_request_ptr = now; + oldptr = strmap_set(last_hid_serv_requests, hsdir_desc_comb_id, + last_request_ptr); + tor_free(oldptr); + } else + last_request_ptr = strmap_get_lc(last_hid_serv_requests, + hsdir_desc_comb_id); + return (last_request_ptr) ? *last_request_ptr : 0; +} + +/** Clean the history of request times to hidden service directories, so that + * it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD + * seconds any more. */ +static void +directory_clean_last_hid_serv_requests(time_t now) +{ + strmap_iter_t *iter; + time_t cutoff = now - hsdir_requery_period(get_options()); + 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; + void *val; + time_t *ent; + strmap_iter_get(iter, &key, &val); + ent = (time_t *) val; + if (*ent < cutoff) { + iter = strmap_iter_next_rmv(last_hid_serv_requests, iter); + tor_free(ent); + } else { + iter = strmap_iter_next(last_hid_serv_requests, iter); + } + } +} + +/** Remove all requests related to the descriptor ID <b>desc_id</b> from the + * history of times of requests to hidden service directories. + * <b>desc_id</b> is an unencoded descriptor ID of size DIGEST_LEN. + * + * This is called from rend_client_note_connection_attempt_ended(), which + * must be idempotent, so any future changes to this function must leave it + * idempotent too. */ +void +purge_hid_serv_from_last_hid_serv_requests(const char *desc_id) +{ + strmap_iter_t *iter; + strmap_t *last_hid_serv_requests = get_last_hid_serv_requests(); + char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; + + /* Key is stored with the base32 encoded desc_id. */ + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id, + DIGEST_LEN); + for (iter = strmap_iter_init(last_hid_serv_requests); + !strmap_iter_done(iter); ) { + const char *key; + void *val; + strmap_iter_get(iter, &key, &val); + /* XXX++?? tor_assert(strlen(key) == LAST_HID_SERV_REQUEST_KEY_LEN); */ + if (tor_memeq(key + LAST_HID_SERV_REQUEST_KEY_LEN - + REND_DESC_ID_V2_LEN_BASE32, + desc_id_base32, + REND_DESC_ID_V2_LEN_BASE32)) { + iter = strmap_iter_next_rmv(last_hid_serv_requests, iter); + tor_free(val); + } else { + iter = strmap_iter_next(last_hid_serv_requests, iter); + } + } +} + +/** 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) { + log_info(LD_REND, "Purging client last-HS-desc-request-time table"); + strmap_free(old_last_hid_serv_requests, tor_free_); + } +} + +/***********************************************************************/ + +/** This returns a good valid hs dir that should be used for the given + * descriptor id. + * + * Return NULL on error else the hsdir node pointer. */ +routerstatus_t * +pick_hsdir(const char *desc_id, const char *desc_id_base32) +{ + smartlist_t *responsible_dirs = smartlist_new(); + smartlist_t *usable_responsible_dirs = smartlist_new(); + const or_options_t *options = get_options(); + routerstatus_t *hs_dir; + time_t now = time(NULL); + int excluded_some; + + tor_assert(desc_id); + tor_assert(desc_id_base32); + + /* Determine responsible dirs. Even if we can't get all we want, work with + * the ones we have. If it's empty, we'll notice below. */ + hid_serv_get_responsible_directories(responsible_dirs, desc_id); + + /* Clean request history first. */ + directory_clean_last_hid_serv_requests(now); + + /* Only select those hidden service directories to which we did not send a + * request recently and for which we have a router descriptor here. */ + SMARTLIST_FOREACH_BEGIN(responsible_dirs, routerstatus_t *, dir) { + time_t last = lookup_last_hid_serv_request(dir, desc_id_base32, + 0, 0); + const node_t *node = node_get_by_id(dir->identity_digest); + if (last + hsdir_requery_period(options) >= now || + !node || !node_has_descriptor(node)) { + SMARTLIST_DEL_CURRENT(responsible_dirs, dir); + continue; + } + if (!routerset_contains_node(options->ExcludeNodes, node)) { + smartlist_add(usable_responsible_dirs, dir); + } + } SMARTLIST_FOREACH_END(dir); + + excluded_some = + smartlist_len(usable_responsible_dirs) < smartlist_len(responsible_dirs); + + hs_dir = smartlist_choose(usable_responsible_dirs); + if (!hs_dir && !options->StrictNodes) { + hs_dir = smartlist_choose(responsible_dirs); + } + + smartlist_free(responsible_dirs); + smartlist_free(usable_responsible_dirs); + if (!hs_dir) { + log_info(LD_REND, "Could not pick one of the responsible hidden " + "service directories, because we requested them all " + "recently without success."); + if (options->StrictNodes && excluded_some) { + log_warn(LD_REND, "Could not pick a hidden service directory for the " + "requested hidden service: they are all either down or " + "excluded, and StrictNodes is set."); + } + } else { + /* Remember that we are requesting a descriptor from this hidden service + * directory now. */ + lookup_last_hid_serv_request(hs_dir, desc_id_base32, now, 1); + } + + return hs_dir; +} + +/***********************************************************************/ + /* Initialize the entire HS subsytem. This is called in tor_init() before any * torrc options are loaded. Only for >= v3. */ void diff --git a/src/or/hs_common.h b/src/or/hs_common.h index fd2a1f4e3..aa810c0db 100644 --- a/src/or/hs_common.h +++ b/src/or/hs_common.h @@ -187,6 +187,10 @@ const char *rend_data_get_desc_id(const rend_data_t *rend_data, const uint8_t *rend_data_get_pk_digest(const rend_data_t *rend_data, size_t *len_out);
+void rend_client_purge_last_hid_serv_requests(void); +void purge_hid_serv_from_last_hid_serv_requests(const char *desc_id); +routerstatus_t *pick_hsdir(const char *desc_id, const char *desc_id_base32); + void hs_get_subcredential(const ed25519_public_key_t *identity_pk, const ed25519_public_key_t *blinded_pk, uint8_t *subcred_out); @@ -229,6 +233,13 @@ void hs_dec_rdv_stream_counter(origin_circuit_t *circ);
STATIC void get_disaster_srv(uint64_t time_period_num, uint8_t *srv_out);
+/** The period for which a hidden service directory cannot be queried for + * the same descriptor ID again. */ +#define REND_HID_SERV_DIR_REQUERY_PERIOD (15 * 60) +/** Test networks generate a new consensus every 5 or 10 seconds. + * So allow them to requery HSDirs much faster. */ +#define REND_HID_SERV_DIR_REQUERY_PERIOD_TESTING (5) + #ifdef TOR_UNIT_TESTS
STATIC uint64_t get_time_period_length(void); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index fbfba27a2..28e02a65e 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -465,230 +465,6 @@ rend_client_introduction_acked(origin_circuit_t *circ, return 0; }
-/** The period for which a hidden service directory cannot be queried for - * the same descriptor ID again. */ -#define REND_HID_SERV_DIR_REQUERY_PERIOD (15 * 60) -/** Test networks generate a new consensus every 5 or 10 seconds. - * So allow them to requery HSDirs much faster. */ -#define REND_HID_SERV_DIR_REQUERY_PERIOD_TESTING (5) - -/** Return the period for which a hidden service directory cannot be queried - * for the same descriptor ID again, taking TestingTorNetwork into account. */ -static time_t -hsdir_requery_period(const or_options_t *options) -{ - tor_assert(options); - - if (options->TestingTorNetwork) { - return REND_HID_SERV_DIR_REQUERY_PERIOD_TESTING; - } else { - return REND_HID_SERV_DIR_REQUERY_PERIOD; - } -} - -/** Contains the last request times to hidden service directories for - * certain queries; each key is a string consisting of the - * concatenation of a base32-encoded HS directory identity digest and - * base32-encoded HS descriptor ID; each value is a pointer to a time_t - * holding the time of the last request for that descriptor ID to that - * HS directory. */ -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_; -} - -#define LAST_HID_SERV_REQUEST_KEY_LEN (REND_DESC_ID_V2_LEN_BASE32 + \ - REND_DESC_ID_V2_LEN_BASE32) - -/** Look up the last request time to hidden service directory <b>hs_dir</b> - * for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero, - * assign the current time <b>now</b> and return that. Otherwise, return the - * most recent request time, or 0 if no such request has been sent before. - */ -static time_t -lookup_last_hid_serv_request(routerstatus_t *hs_dir, - const char *desc_id_base32, - time_t now, int set) -{ - char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; - char hsdir_desc_comb_id[LAST_HID_SERV_REQUEST_KEY_LEN + 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", - hsdir_id_base32, - desc_id_base32); - /* XXX++?? tor_assert(strlen(hsdir_desc_comb_id) == - LAST_HID_SERV_REQUEST_KEY_LEN); */ - if (set) { - time_t *oldptr; - last_request_ptr = tor_malloc_zero(sizeof(time_t)); - *last_request_ptr = now; - oldptr = strmap_set(last_hid_serv_requests, hsdir_desc_comb_id, - last_request_ptr); - tor_free(oldptr); - } else - last_request_ptr = strmap_get_lc(last_hid_serv_requests, - hsdir_desc_comb_id); - return (last_request_ptr) ? *last_request_ptr : 0; -} - -/** Clean the history of request times to hidden service directories, so that - * it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD - * seconds any more. */ -static void -directory_clean_last_hid_serv_requests(time_t now) -{ - strmap_iter_t *iter; - time_t cutoff = now - hsdir_requery_period(get_options()); - 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; - void *val; - time_t *ent; - strmap_iter_get(iter, &key, &val); - ent = (time_t *) val; - if (*ent < cutoff) { - iter = strmap_iter_next_rmv(last_hid_serv_requests, iter); - tor_free(ent); - } else { - iter = strmap_iter_next(last_hid_serv_requests, iter); - } - } -} - -/** Remove all requests related to the descriptor ID <b>desc_id</b> from the - * history of times of requests to hidden service directories. - * <b>desc_id</b> is an unencoded descriptor ID of size DIGEST_LEN. - * - * This is called from rend_client_note_connection_attempt_ended(), which - * must be idempotent, so any future changes to this function must leave it - * idempotent too. */ -static void -purge_hid_serv_from_last_hid_serv_requests(const char *desc_id) -{ - strmap_iter_t *iter; - strmap_t *last_hid_serv_requests = get_last_hid_serv_requests(); - char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; - - /* Key is stored with the base32 encoded desc_id. */ - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id, - DIGEST_LEN); - for (iter = strmap_iter_init(last_hid_serv_requests); - !strmap_iter_done(iter); ) { - const char *key; - void *val; - strmap_iter_get(iter, &key, &val); - /* XXX++?? tor_assert(strlen(key) == LAST_HID_SERV_REQUEST_KEY_LEN); */ - if (tor_memeq(key + LAST_HID_SERV_REQUEST_KEY_LEN - - REND_DESC_ID_V2_LEN_BASE32, - desc_id_base32, - REND_DESC_ID_V2_LEN_BASE32)) { - iter = strmap_iter_next_rmv(last_hid_serv_requests, iter); - tor_free(val); - } else { - iter = strmap_iter_next(last_hid_serv_requests, iter); - } - } -} - -/** 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) { - log_info(LD_REND, "Purging client last-HS-desc-request-time table"); - strmap_free(old_last_hid_serv_requests, tor_free_); - } -} - -/** This returns a good valid hs dir that should be used for the given - * descriptor id. - * - * Return NULL on error else the hsdir node pointer. */ -static routerstatus_t * -pick_hsdir(const char *desc_id, const char *desc_id_base32) -{ - smartlist_t *responsible_dirs = smartlist_new(); - smartlist_t *usable_responsible_dirs = smartlist_new(); - const or_options_t *options = get_options(); - routerstatus_t *hs_dir; - time_t now = time(NULL); - int excluded_some; - - tor_assert(desc_id); - tor_assert(desc_id_base32); - - /* Determine responsible dirs. Even if we can't get all we want, work with - * the ones we have. If it's empty, we'll notice below. */ - hid_serv_get_responsible_directories(responsible_dirs, desc_id); - - /* Clean request history first. */ - directory_clean_last_hid_serv_requests(now); - - /* Only select those hidden service directories to which we did not send a - * request recently and for which we have a router descriptor here. */ - SMARTLIST_FOREACH_BEGIN(responsible_dirs, routerstatus_t *, dir) { - time_t last = lookup_last_hid_serv_request(dir, desc_id_base32, - 0, 0); - const node_t *node = node_get_by_id(dir->identity_digest); - if (last + hsdir_requery_period(options) >= now || - !node || !node_has_descriptor(node)) { - SMARTLIST_DEL_CURRENT(responsible_dirs, dir); - continue; - } - if (!routerset_contains_node(options->ExcludeNodes, node)) { - smartlist_add(usable_responsible_dirs, dir); - } - } SMARTLIST_FOREACH_END(dir); - - excluded_some = - smartlist_len(usable_responsible_dirs) < smartlist_len(responsible_dirs); - - hs_dir = smartlist_choose(usable_responsible_dirs); - if (!hs_dir && !options->StrictNodes) { - hs_dir = smartlist_choose(responsible_dirs); - } - - smartlist_free(responsible_dirs); - smartlist_free(usable_responsible_dirs); - if (!hs_dir) { - log_info(LD_REND, "Could not pick one of the responsible hidden " - "service directories, because we requested them all " - "recently without success."); - if (options->StrictNodes && excluded_some) { - log_warn(LD_REND, "Could not pick a hidden service directory for the " - "requested hidden service: they are all either down or " - "excluded, and StrictNodes is set."); - } - } else { - /* Remember that we are requesting a descriptor from this hidden service - * directory now. */ - lookup_last_hid_serv_request(hs_dir, desc_id_base32, now, 1); - } - - return hs_dir; -} - /** Determine the responsible hidden service directories for <b>desc_id</b> * and fetch the descriptor with that ID from one of them. Only * send a request to a hidden service directory that we have not yet tried diff --git a/src/or/rendclient.h b/src/or/rendclient.h index ff0f4084f..375bc973b 100644 --- a/src/or/rendclient.h +++ b/src/or/rendclient.h @@ -24,7 +24,6 @@ int rend_client_introduction_acked(origin_circuit_t *circ, void rend_client_refetch_v2_renddesc(rend_data_t *rend_query); int rend_client_fetch_v2_desc(rend_data_t *query, smartlist_t *hsdirs); void rend_client_cancel_descriptor_fetches(void); -void rend_client_purge_last_hid_serv_requests(void);
int rend_client_report_intro_point_failure(extend_info_t *failed_intro, rend_data_t *rend_data,
tor-commits@lists.torproject.org