diff --git a/ChangeLog b/ChangeLog index 7d43130b85..c678be4d61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,9 @@ Changes in version 0.2.0.1-alpha - 2007-??-?? especially on platforms where malloc() is inefficient. - Stop reading on edge connections when their corresponding circuit buffers are full; start again as the circuits empty out. + - Make PreferTunneledDirConns and TunnelDirConns work even when + we have no cached directory info. This means Tor clients can now + do all of their connections protected by TLS. o Security fixes: - Directory authorities now call routers stable if they have an diff --git a/src/or/circuituse.c b/src/or/circuituse.c index fd0e609d2d..8b3e1a8f14 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -91,10 +91,18 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, log_debug(LD_CIRC,"Skipping one-hop circuit."); return 0; } + tor_assert(conn->chosen_exit_name); + if (build_state->chosen_exit) { + char digest[DIGEST_LEN]; + if (hexdigest_to_digest(conn->chosen_exit_name, digest) < 0 || + memcmp(digest, build_state->chosen_exit->identity_digest, + DIGEST_LEN)) + return 0; /* this is a circuit to somewhere else */ + } } else { if (conn->socks_request->command == SOCKS_COMMAND_CONNECT_DIR) { /* don't use three-hop circuits -- that could hurt our anonymity. */ - log_debug(LD_CIRC,"Skipping multi-hop circuit for CONNECT_DIR."); +// log_debug(LD_CIRC,"Skipping multi-hop circuit for CONNECT_DIR."); return 0; } } diff --git a/src/or/directory.c b/src/or/directory.c index d21882732e..e768f1d00a 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -248,7 +248,8 @@ directory_initiate_command_routerstatus(routerstatus_t *status, tor_inet_ntoa(&in, address_buf, sizeof(address_buf)); address = address_buf; } - directory_initiate_command(address, status->addr, status->dir_port, + directory_initiate_command(address, status->addr, + status->or_port, status->dir_port, status->version_supports_begindir, status->identity_digest, purpose, private_connection, resource, @@ -365,7 +366,8 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn) * digest. */ void directory_initiate_command(const char *address, uint32_t addr, - uint16_t dir_port, int supports_begindir, + uint16_t or_port, uint16_t dir_port, + int supports_begindir, const char *digest, uint8_t purpose, int private_connection, const char *resource, const char *payload, size_t payload_len) @@ -373,7 +375,8 @@ directory_initiate_command(const char *address, uint32_t addr, dir_connection_t *conn; or_options_t *options = get_options(); int want_to_tunnel = options->TunnelDirConns && supports_begindir && - router_get_by_digest(digest); + !private_connection && or_port && + fascist_firewall_allows_address_or(addr, or_port); tor_assert(address); tor_assert(addr); @@ -414,7 +417,7 @@ directory_initiate_command(const char *address, uint32_t addr, /* set up conn so it's got all the data we need to remember */ conn->_base.addr = addr; - conn->_base.port = dir_port; + conn->_base.port = want_to_tunnel ? or_port : dir_port; conn->_base.address = tor_strdup(address); memcpy(conn->identity_digest, digest, DIGEST_LEN); diff --git a/src/or/or.h b/src/or/or.h index a61f33a34d..ed89e5cc88 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2487,7 +2487,8 @@ int connection_dir_finished_flushing(dir_connection_t *conn); int connection_dir_finished_connecting(dir_connection_t *conn); void connection_dir_request_failed(dir_connection_t *conn); void directory_initiate_command(const char *address, uint32_t addr, - uint16_t dir_port, int supports_begindir, + uint16_t or_port, uint16_t dir_port, + int supports_begindir, const char *digest, uint8_t purpose, int private_connection, const char *resource, const char *payload, size_t payload_len); @@ -3021,6 +3022,7 @@ routerinfo_t *router_choose_random_node(const char *preferred, int weight_for_exit); routerinfo_t *router_get_by_nickname(const char *nickname, int warn_if_unnamed); +int hexdigest_to_digest(const char *hexdigest, char *digest); routerinfo_t *router_get_by_hexdigest(const char *hexdigest); routerinfo_t *router_get_by_digest(const char *digest); signed_descriptor_t *router_get_by_descriptor_digest(const char *digest); diff --git a/src/or/router.c b/src/or/router.c index ad7ad96a24..0dfe62d62d 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -507,7 +507,8 @@ consider_testing_reachability(int test_or, int test_dir) CONN_TYPE_DIR, me->addr, me->dir_port, DIR_PURPOSE_FETCH_SERVERDESC)) { /* ask myself, via tor, for my server descriptor. */ - directory_initiate_command(me->address, me->addr, me->dir_port, + directory_initiate_command(me->address, me->addr, + me->or_port, me->dir_port, 0, me->cache_info.identity_digest, DIR_PURPOSE_FETCH_SERVERDESC, 1, "authority", NULL, 0); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index b1efe89eaf..0dfa4dbcaf 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -574,16 +574,15 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall, is_trusted = router_digest_is_trusted_dir(status->identity_digest); if (for_v2_directory && !(status->is_v2_dir || is_trusted)) continue; - if (fascistfirewall && - prefer_tunnel && + if (prefer_tunnel && status->version_supports_begindir && - router_get_by_digest(status->identity_digest) && - fascist_firewall_allows_address_or(status->addr, status->or_port)) + (!fascistfirewall || + fascist_firewall_allows_address_or(status->addr, status->or_port))) smartlist_add(is_trusted ? trusted_tunnel : is_overloaded ? overloaded_tunnel : tunnel, status); - else if (!fascistfirewall || (fascistfirewall && + else if (!fascistfirewall || fascist_firewall_allows_address_dir(status->addr, - status->dir_port))) + status->dir_port)) smartlist_add(is_trusted ? trusted_direct : is_overloaded ? overloaded_direct : direct, status); }); @@ -652,17 +651,14 @@ router_pick_trusteddirserver_impl(authority_type_t type, continue; if (requireother && me && router_digest_is_me(d->digest)) continue; - - if (fascistfirewall && - prefer_tunnel && + if (prefer_tunnel && d->or_port && - router_get_by_digest(d->digest) && - fascist_firewall_allows_address_or(d->addr, d->or_port)) + (!fascistfirewall || + fascist_firewall_allows_address_or(d->addr, d->or_port))) smartlist_add(is_overloaded ? overloaded_tunnel : tunnel, &d->fake_status.status); - else if (!fascistfirewall || (fascistfirewall && - fascist_firewall_allows_address_dir(d->addr, - d->dir_port))) + else if (!fascistfirewall || + fascist_firewall_allows_address_dir(d->addr, d->dir_port)) smartlist_add(is_overloaded ? overloaded_direct : direct, &d->fake_status.status); }); @@ -1379,6 +1375,21 @@ router_digest_is_trusted_dir(const char *digest) return 0; } +/** If hexdigest is correctly formed, base16_decode it into + * digest, which must have DIGEST_LEN space in it. + * Return 0 on success, -1 on failure. + */ +int +hexdigest_to_digest(const char *hexdigest, char *digest) +{ + if (hexdigest[0]=='$') + ++hexdigest; + if (strlen(hexdigest) < HEX_DIGEST_LEN || + base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN) < 0) + return -1; + return 0; +} + /** Return the router in our routerlist whose hexadecimal key digest * is hexdigest. Return NULL if no such router is known. */ routerinfo_t * @@ -1394,8 +1405,7 @@ router_get_by_hexdigest(const char *hexdigest) if (hexdigest[0]=='$') ++hexdigest; len = strlen(hexdigest); - if (len < HEX_DIGEST_LEN || - base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN) < 0) + if (hexdigest_to_digest(hexdigest, digest) < 0) return NULL; ri = router_get_by_digest(digest); @@ -3189,6 +3199,9 @@ add_trusted_dir_server(const char *nickname, const char *address, ent->fake_status.status.dir_port = ent->dir_port; ent->fake_status.status.or_port = ent->or_port; + if (ent->or_port) + ent->fake_status.status.version_supports_begindir = 1; + smartlist_add(trusted_dir_servers, ent); router_dir_info_changed(); }