diff options
author | David Goulet <dgoulet@torproject.org> | 2017-09-12 12:24:26 -0400 |
---|---|---|
committer | George Kadianakis <desnacked@riseup.net> | 2017-09-12 21:34:26 +0300 |
commit | 6b4eace248272f4defae0f6cc9933588b1b498b3 (patch) | |
tree | 9e1ac44754af860125953f7fe8cac267e59fd335 | |
parent | d71a00e91f3921f6bdf160811313e7b32f890b6c (diff) | |
download | tor-6b4eace248272f4defae0f6cc9933588b1b498b3.tar.gz tor-6b4eace248272f4defae0f6cc9933588b1b498b3.zip |
hs-v3: Stall SOCKS connection when no live consensus available
Fixes #23481
Signed-off-by: David Goulet <dgoulet@torproject.org>
-rw-r--r-- | src/or/connection_edge.c | 26 | ||||
-rw-r--r-- | src/or/hs_client.c | 31 | ||||
-rw-r--r-- | src/or/hs_client.h | 16 | ||||
-rw-r--r-- | src/test/test_entryconn.c | 2 |
4 files changed, 63 insertions, 12 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index dfa89bc2ce..d1b8abda82 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -80,6 +80,7 @@ #include "hs_client.h" #include "hs_circuit.h" #include "main.h" +#include "networkstatus.h" #include "nodelist.h" #include "policies.h" #include "proto_http.h" @@ -1561,18 +1562,37 @@ connection_ap_handle_onion(entry_connection_t *conn, if (addresstype == ONION_V2_HOSTNAME) { tor_assert(edge_conn->rend_data); rend_client_refetch_v2_renddesc(edge_conn->rend_data); + /* Whatever the result of the refetch, we don't go further. */ + return 0; } else { tor_assert(addresstype == ONION_V3_HOSTNAME); tor_assert(edge_conn->hs_ident); - hs_client_refetch_hsdesc(&edge_conn->hs_ident->identity_pk); + /* Attempt to fetch the hsv3 descriptor. Check the retval to see how it + * went and act accordingly. */ + int ret = hs_client_refetch_hsdesc(&edge_conn->hs_ident->identity_pk); + switch (ret) { + case HS_CLIENT_FETCH_MISSING_INFO: + /* By going to the end, the connection is put in waiting for a circuit + * state which means that it will be retried and consider as a pending + * connection. */ + goto end; + case HS_CLIENT_FETCH_LAUNCHED: + case HS_CLIENT_FETCH_HAVE_DESC: + return 0; + case HS_CLIENT_FETCH_ERROR: + case HS_CLIENT_FETCH_NO_HSDIRS: + case HS_CLIENT_FETCH_NOT_ALLOWED: + /* Can't proceed further and better close the SOCKS request. */ + return -1; + } } - return 0; } /* We have the descriptor! So launch a connection to the HS. */ - base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; log_info(LD_REND, "Descriptor is here. Great."); + end: + base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; /* We'll try to attach it at the next event loop, or whenever * we call connection_ap_attach_pending() */ connection_ap_mark_as_pending_circuit(conn); diff --git a/src/or/hs_client.c b/src/or/hs_client.c index 620ef3a100..be5ece068c 100644 --- a/src/or/hs_client.c +++ b/src/or/hs_client.c @@ -152,7 +152,7 @@ directory_launch_v3_desc_fetch(const ed25519_public_key_t *onion_identity_pk, /* ...and base64 it. */ retval = ed25519_public_to_base64(base64_blinded_pubkey, &blinded_pubkey); if (BUG(retval < 0)) { - return -1; + return HS_CLIENT_FETCH_ERROR; } /* Copy onion pk to a dir_ident so that we attach it to the dir conn */ @@ -180,7 +180,7 @@ directory_launch_v3_desc_fetch(const ed25519_public_key_t *onion_identity_pk, memwipe(base64_blinded_pubkey, 0, sizeof(base64_blinded_pubkey)); memwipe(&hs_conn_dir_ident, 0, sizeof(hs_conn_dir_ident)); - return 1; + return HS_CLIENT_FETCH_LAUNCHED; } /** Return the HSDir we should use to fetch the descriptor of the hidden @@ -236,7 +236,7 @@ fetch_v3_desc(const ed25519_public_key_t *onion_identity_pk) hsdir_rs = pick_hsdir_v3(onion_identity_pk); if (!hsdir_rs) { log_info(LD_REND, "Couldn't pick a v3 hsdir."); - return 0; + return HS_CLIENT_FETCH_NO_HSDIRS; } return directory_launch_v3_desc_fetch(onion_identity_pk, hsdir_rs); @@ -998,8 +998,7 @@ hs_client_any_intro_points_usable(const ed25519_public_key_t *service_pk, /** Launch a connection to a hidden service directory to fetch a hidden * service descriptor using <b>identity_pk</b> to get the necessary keys. * - * On success, 1 is returned. If no hidden service is left to ask, return 0. - * On error, -1 is returned. (retval is only used by unittests right now) */ + * A hs_client_fetch_status_t code is returned. */ int hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk) { @@ -1009,7 +1008,23 @@ hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk) if (!get_options()->FetchHidServDescriptors) { log_warn(LD_REND, "We received an onion address for a hidden service " "descriptor but we are configured to not fetch."); - return 0; + return HS_CLIENT_FETCH_NOT_ALLOWED; + } + + /* Without a live consensus we can't do any client actions. It is needed to + * compute the hashring for a service. */ + if (!networkstatus_get_live_consensus(approx_time())) { + log_info(LD_REND, "Can't fetch descriptor for service %s because we " + "are missing a live consensus. Stalling connection.", + safe_str_client(ed25519_fmt(identity_pk))); + return HS_CLIENT_FETCH_MISSING_INFO; + } + + if (!router_have_minimum_dir_info()) { + log_info(LD_REND, "Can't fetch descriptor for service %s because we " + "dont have enough descriptors. Stalling connection.", + safe_str_client(ed25519_fmt(identity_pk))); + return HS_CLIENT_FETCH_MISSING_INFO; } /* Check if fetching a desc for this HS is useful to us right now */ @@ -1019,8 +1034,8 @@ hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk) if (cached_desc && hs_client_any_intro_points_usable(identity_pk, cached_desc)) { log_info(LD_GENERAL, "We would fetch a v3 hidden service descriptor " - "but we already have a usable descriptor."); - return 0; + "but we already have a usable descriptor."); + return HS_CLIENT_FETCH_HAVE_DESC; } } diff --git a/src/or/hs_client.h b/src/or/hs_client.h index 5227704506..3ea2b8cdf9 100644 --- a/src/or/hs_client.h +++ b/src/or/hs_client.h @@ -13,6 +13,22 @@ #include "hs_descriptor.h" #include "hs_ident.h" +/* Status code of a descriptor fetch request. */ +typedef enum { + /* Something internally went wrong. */ + HS_CLIENT_FETCH_ERROR = -1, + /* The fetch request has been launched successfully. */ + HS_CLIENT_FETCH_LAUNCHED = 0, + /* We already have a usable descriptor. No fetch. */ + HS_CLIENT_FETCH_HAVE_DESC = 1, + /* No more HSDir available to query. */ + HS_CLIENT_FETCH_NO_HSDIRS = 2, + /* The fetch request is not allowed. */ + HS_CLIENT_FETCH_NOT_ALLOWED = 3, + /* We are missing information to be able to launch a request. */ + HS_CLIENT_FETCH_MISSING_INFO = 4, +} hs_client_fetch_status_t; + void hs_client_note_connection_attempt_succeeded( const edge_connection_t *conn); diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c index 9fe3db26f7..2d28f1d428 100644 --- a/src/test/test_entryconn.c +++ b/src/test/test_entryconn.c @@ -815,7 +815,7 @@ test_entryconn_rewrite_onion_v3(void *arg) tt_int_op(retval, OP_EQ, 0); /* Check connection state after rewrite */ - tt_int_op(ENTRY_TO_CONN(conn)->state, OP_EQ, AP_CONN_STATE_RENDDESC_WAIT); + tt_int_op(ENTRY_TO_CONN(conn)->state, OP_EQ, AP_CONN_STATE_CIRCUIT_WAIT); /* check that the address got rewritten */ tt_str_op(conn->socks_request->address, OP_EQ, "p3xnclpu4mu22dwaurjtsybyqk4xfjmcfz6z62yl24uwmhjatiwnlnad"); |