From e0486c937178981585d45b65b359f488ed96c06d Mon Sep 17 00:00:00 2001 From: teor Date: Thu, 2 Mar 2017 15:33:09 +1100 Subject: [PATCH 1/3] Make hidden services always check for failed intro point connections Previously, they would stop checking when they exceeded their intro point creation limit. Fixes bug 21596; bugfix on commit d67bf8b2f23 in Tor 0.2.7.2-alpha. Reported by alecmuffett. --- changes/bug21596 | 5 +++++ src/or/rendservice.c | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 changes/bug21596 diff --git a/changes/bug21596 b/changes/bug21596 new file mode 100644 index 000000000..ec0a46bb8 --- /dev/null +++ b/changes/bug21596 @@ -0,0 +1,5 @@ + o Minor bugfixes (hidden services): + - Make hidden services check for failed intro point connections, even when + they have exceeded their intro point creation limit. Fixes bug 21596; + bugfix on commit d67bf8b2f23 in Tor 0.2.7.2-alpha. Reported by + alecmuffett. diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 4d04da02a..c04f5bb6e 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -3930,6 +3930,10 @@ rend_consider_services_intro_points(void) smartlist_clear(exclude_nodes); smartlist_clear(retry_nodes); + /* Cleanup the invalid intro points and save the node objects, if any, + * in the exclude_nodes and retry_nodes lists. */ + remove_invalid_intro_points(service, exclude_nodes, retry_nodes, now); + /* This retry period is important here so we don't stress circuit * creation. */ if (now > service->intro_period_started + INTRO_CIRC_RETRY_PERIOD) { @@ -3939,14 +3943,10 @@ rend_consider_services_intro_points(void) } else if (service->n_intro_circuits_launched >= MAX_INTRO_CIRCS_PER_PERIOD) { /* We have failed too many times in this period; wait for the next - * one before we try again. */ + * one before we try to initiate any more connections. */ continue; } - /* Cleanup the invalid intro points and save the node objects, if apply, - * in the exclude_nodes and retry_nodes list. */ - remove_invalid_intro_points(service, exclude_nodes, retry_nodes, now); - /* Let's try to rebuild circuit on the nodes we want to retry on. */ SMARTLIST_FOREACH_BEGIN(retry_nodes, rend_intro_point_t *, intro) { r = rend_service_launch_establish_intro(service, intro); From 41324b5ae1334a40baa87785ad18d1a4d9df5322 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 2 Mar 2017 16:47:47 +0200 Subject: [PATCH 2/3] Revert "Restore correct behavior of 0.3.0.4-rc with bridges+ipv6-min" This reverts commit 5298ab59170be74aed20e04e5378ec66eef6476e. --- src/or/entrynodes.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index c3c576c81..729e4b039 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -3365,14 +3365,7 @@ guard_selection_have_enough_dir_info_to_build_circuits(guard_selection_t *gs) * guards in our list, since these are the guards that we typically use for * circuits. */ num_primary_to_check = get_n_primary_guards_to_use(GUARD_USAGE_TRAFFIC); - /* - We had added this to try to guarantee that we'd not normally try a guard - without a descriptor, even if we didn't use the first guard. But it led - to problems with the chutney bridges+ipv6-min test. A better solution is - needed. - - num_primary_to_check++; - */ + num_primary_to_check++; SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) { entry_guard_consider_retry(guard); From 6cab0f8ad712def4f5a9bdfb9d11b0e773f7f76a Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 2 Mar 2017 16:28:11 +0200 Subject: [PATCH 3/3] Fix failing bridges+ipv6-min integration test. The bridges+ipv6-min integration test has a client with bridges: Bridge 127.0.0.1:5003 Bridge [::1]:5003 which got stuck in guard_selection_have_enough_dir_info_to_build_circuits() because it couldn't find the descriptor of both bridges. Specifically, the guard_has_descriptor() function could not find the node_t of the [::1] bridge, because the [::1] bridge had no identity digest assigned to it. After further examination, it seems that during fetching the descriptor for our bridges, we used the CERTS cell to fill the identity digest of 127.0.0.1:5003 properly. However, when we received a CERTS cell from [::1]:5003 we actually ignored its identity digest because the learned_router_identity() function was using get_configured_bridge_by_addr_port_digest() which was returning the 127.0.0.1 bridge instead of the [::1] bridge (because it prioritizes digest matching over addrport matching). The fix replaces get_configured_bridge_by_addr_port_digest() with the recent get_configured_bridge_by_exact_addr_port_digest() function. It also relaxes the constraints of the get_configured_bridge_by_exact_addr_port_digest() function by making it return bridges whose identity digest is not yet known. By using the _exact_() function, learned_router_identity() actually fills in the identity digest of the [::1] bridge, which then allows guard_has_descriptor() to find the right node_t and verify that the descriptor is there. FWIW, in the bridges+ipv6-min test both 127.0.0.1 and [::1] bridges correspond to the same node_t, which I guess makes sense given that it's actually the same underlying bridge. --- src/or/bridges.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/or/bridges.c b/src/or/bridges.c index f766931b4..88154c6c8 100644 --- a/src/or/bridges.c +++ b/src/or/bridges.c @@ -218,7 +218,7 @@ get_configured_bridge_by_exact_addr_port_digest(const tor_addr_t *addr, if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN)) return bridge; - else if (!digest) + else if (!digest || tor_digest_is_zero(bridge->identity)) return bridge; } @@ -297,7 +297,7 @@ learned_router_identity(const tor_addr_t *addr, uint16_t port, (void)ed_id; int learned = 0; bridge_info_t *bridge = - get_configured_bridge_by_addr_port_digest(addr, port, digest); + get_configured_bridge_by_exact_addr_port_digest(addr, port, digest); if (bridge && tor_digest_is_zero(bridge->identity)) { memcpy(bridge->identity, digest, DIGEST_LEN); learned = 1;