From 5cbeb6080596c4442a19cffb56c1a68316b3014a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 12 Sep 2012 10:15:58 -0400 Subject: [PATCH] Fix directory self-testing logic When I removed version_supports_begindir, I accidentally removed the mechanism we had been using to make a directory cache self-test its directory port. This caused bug 6815, which caused 6814 (both in 0.2.4.2-alpha). To fix this bug, I'm replacing the "anonymized_connection" argument to directory_initiate_command_* with an enumeration to say how indirectly to connect to a directory server. (I don't want to reinstate the "version_supports_begindir" argument as "begindir_ok" or anything -- these functions already take too many arguments.) For safety, I made sure that passing 0 and 1 for 'indirection' gives the same result as you would have gotten before -- just in case I missed any 0s or 1s. --- changes/bug6815 | 6 ++++++ src/or/circuitbuild.c | 2 +- src/or/directory.c | 48 ++++++++++++++++++++++++++++-------------- src/or/directory.h | 20 +++++++++++++++--- src/or/networkstatus.c | 2 +- src/or/rendclient.c | 3 ++- src/or/rendservice.c | 3 ++- src/or/router.c | 2 +- src/or/routerlist.c | 2 +- 9 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 changes/bug6815 diff --git a/changes/bug6815 b/changes/bug6815 new file mode 100644 index 0000000000..d6a1233a4f --- /dev/null +++ b/changes/bug6815 @@ -0,0 +1,6 @@ + o Major bugfixes: + - Allow routers to correctly detect their own DirPorts as running. + When we removed support for versions_supports_begindir, we also + accidentally removed the mechanism we used to self-test our + DirPort. Diagnosed with help from kargig. Fixes bugs 6814 and + 6815; bugfix on 0.2.4.2-alpha. diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index fe327cab45..4384e291f7 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -5479,7 +5479,7 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) bridge->identity, DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_BRIDGE, - 0, "authority.z", NULL, 0, 0); + DIRIND_ONEHOP, "authority.z", NULL, 0, 0); tor_free(address); } diff --git a/src/or/directory.c b/src/or/directory.c index d22a8b877d..effccc5856 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -91,7 +91,7 @@ static void directory_initiate_command_rend(const char *address, const char *digest, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -432,7 +432,8 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, ri->cache_info.identity_digest, dir_purpose, router_purpose, - 0, resource, NULL, 0, if_modified_since); + DIRIND_ONEHOP, + resource, NULL, 0, if_modified_since); } else log_notice(LD_DIR, "Ignoring directory request, since no bridge " "nodes are available yet."); @@ -493,13 +494,15 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, } } - if (rs) + if (rs) { + const dir_indirection_t indirection = + get_via_tor ? DIRIND_ANONYMOUS : DIRIND_ONEHOP; directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, - get_via_tor, + indirection, resource, NULL, 0, if_modified_since); - else { + } else { log_notice(LD_DIR, "While fetching directory info, " "no running dirservers known. Will try again later. " @@ -531,17 +534,25 @@ directory_get_from_all_authorities(uint8_t dir_purpose, continue; rs = &ds->fake_status; directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, - 0, resource, NULL, 0, 0); + DIRIND_ONEHOP, resource, NULL, + 0, 0); } SMARTLIST_FOREACH_END(ds); } +/** Return true iff ind requires a multihop circuit. */ +static int +dirind_is_anon(dir_indirection_t ind) +{ + return ind == DIRIND_ANON_DIRPORT || ind == DIRIND_ANONYMOUS; +} + /** Same as directory_initiate_command_routerstatus(), but accepts * rendezvous data to fetch a hidden service descriptor. */ void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -554,6 +565,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, struct in_addr in; const char *address; tor_addr_t addr; + const int anonymized_connection = dirind_is_anon(indirection); node = node_get_by_id(status->identity_digest); if (!node && anonymized_connection) { @@ -585,7 +597,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, status->or_port, status->dir_port, status->identity_digest, dir_purpose, router_purpose, - anonymized_connection, resource, + indirection, resource, payload, payload_len, if_modified_since, rend_query); } @@ -608,7 +620,7 @@ void directory_initiate_command_routerstatus(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -616,7 +628,7 @@ directory_initiate_command_routerstatus(const routerstatus_t *status, { directory_initiate_command_routerstatus_rend(status, dir_purpose, router_purpose, - anonymized_connection, resource, + indirection, resource, payload, payload_len, if_modified_since, NULL); } @@ -818,11 +830,13 @@ static int directory_command_should_use_begindir(const or_options_t *options, const tor_addr_t *addr, int or_port, uint8_t router_purpose, - int anonymized_connection) + dir_indirection_t indirection) { if (!or_port) return 0; /* We don't know an ORPort -- no chance. */ - if (!anonymized_connection) + if (indirection == DIRIND_DIRECT_CONN || indirection == DIRIND_ANON_DIRPORT) + return 0; + if (indirection == DIRIND_ONEHOP) if (!fascist_firewall_allows_address_or(addr, or_port) || directory_fetches_from_authorities(options)) return 0; /* We're firewalled or are acting like a relay -- also no. */ @@ -842,13 +856,13 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr, uint16_t or_port, uint16_t dir_port, const char *digest, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, const char *resource, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, time_t if_modified_since) { directory_initiate_command_rend(address, _addr, or_port, dir_port, digest, dir_purpose, - router_purpose, anonymized_connection, + router_purpose, indirection, resource, payload, payload_len, if_modified_since, NULL); } @@ -874,7 +888,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, uint16_t or_port, uint16_t dir_port, const char *digest, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, time_t if_modified_since, @@ -884,7 +898,8 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, const or_options_t *options = get_options(); int socket_error = 0; int use_begindir = directory_command_should_use_begindir(options, _addr, - or_port, router_purpose, anonymized_connection); + or_port, router_purpose, indirection); + const int anonymized_connection = dirind_is_anon(indirection); tor_addr_t addr; tor_assert(address); @@ -930,6 +945,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, conn->_base.state = DIR_CONN_STATE_CONNECTING; /* decide whether we can learn our IP address from this conn */ + /* XXXX This is a bad name for this field now. */ conn->dirconn_direct = !anonymized_connection; /* copy rendezvous data, if any */ diff --git a/src/or/directory.h b/src/or/directory.h index 14444c0ce4..7029abc582 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -22,10 +22,24 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, void directory_get_from_all_authorities(uint8_t dir_purpose, uint8_t router_purpose, const char *resource); + +/** Enumeration of ways to connect to a directory server */ +typedef enum { + /** Default: connect over a one-hop Tor circuit but fall back to direct + * connection */ + DIRIND_ONEHOP=0, + /** Connect over a multi-hop anonymizing Tor circuit */ + DIRIND_ANONYMOUS=1, + /** Conncet to the DirPort directly */ + DIRIND_DIRECT_CONN, + /** Connect over a multi-hop anonymizing Tor circuit to our dirport */ + DIRIND_ANON_DIRPORT, +} dir_indirection_t; + void directory_initiate_command_routerstatus(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -33,7 +47,7 @@ void directory_initiate_command_routerstatus(const routerstatus_t *status, void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, @@ -53,7 +67,7 @@ void directory_initiate_command(const char *address, const tor_addr_t *addr, uint16_t or_port, uint16_t dir_port, const char *digest, uint8_t dir_purpose, uint8_t router_purpose, - int anonymized_connection, + dir_indirection_t indirection, const char *resource, const char *payload, size_t payload_len, time_t if_modified_since); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 0df5c4e631..ff31f82ff6 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1168,7 +1168,7 @@ update_v2_networkstatus_cache_downloads(time_t now) directory_initiate_command_routerstatus( &ds->fake_status, DIR_PURPOSE_FETCH_V2_NETWORKSTATUS, ROUTER_PURPOSE_GENERAL, - 0, /* Not private */ + DIRIND_ONEHOP, resource, NULL, 0 /* No payload. */, 0 /* No I-M-S. */); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 5b3b92e406..0b6d82bdf4 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -617,7 +617,8 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) directory_initiate_command_routerstatus_rend(hs_dir, DIR_PURPOSE_FETCH_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, - !tor2web_mode, desc_id_base32, + tor2web_mode?DIRIND_ONEHOP:DIRIND_ANONYMOUS, + desc_id_base32, NULL, 0, 0, rend_query); log_info(LD_REND, "Sending fetch request for v2 descriptor for " diff --git a/src/or/rendservice.c b/src/or/rendservice.c index bd8b13a762..394831f857 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -2782,7 +2782,8 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, directory_initiate_command_routerstatus(hs_dir, DIR_PURPOSE_UPLOAD_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, - 1, NULL, desc->desc_str, + DIRIND_ANONYMOUS, NULL, + desc->desc_str, strlen(desc->desc_str), 0); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc->desc_id, DIGEST_LEN); diff --git a/src/or/router.c b/src/or/router.c index 4e1eb2ddb2..a26dccc78f 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -957,7 +957,7 @@ consider_testing_reachability(int test_or, int test_dir) me->cache_info.identity_digest, DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_GENERAL, - 1, "authority.z", NULL, 0, 0); + DIRIND_ANON_DIRPORT, "authority.z", NULL, 0, 0); } } diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 41abc4c87a..214c086448 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -4326,7 +4326,7 @@ initiate_descriptor_downloads(const routerstatus_t *source, /* We know which authority we want. */ directory_initiate_command_routerstatus(source, purpose, ROUTER_PURPOSE_GENERAL, - 0, /* not private */ + DIRIND_ONEHOP, resource, NULL, 0, 0); } else { directory_get_from_dirserver(purpose, ROUTER_PURPOSE_GENERAL, resource,