commit c232b6b59cc136f7053922b3efc14afd5c34b6ec Author: David Goulet dgoulet@torproject.org Date: Tue Sep 26 10:45:24 2017 -0400
hs-v3: Close pending SOCKS connection on descriptor fetch error
Signed-off-by: David Goulet dgoulet@torproject.org --- src/or/hs_client.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-)
diff --git a/src/or/hs_client.c b/src/or/hs_client.c index 8ed19529b..6f81ea09e 100644 --- a/src/or/hs_client.c +++ b/src/or/hs_client.c @@ -32,6 +32,58 @@ #include "hs_ntor.h" #include "circuitbuild.h" #include "networkstatus.h" +#include "reasons.h" + +/* Return a human-readable string for the client fetch status code. */ +static const char * +fetch_status_to_string(hs_client_fetch_status_t status) +{ + switch (status) { + case HS_CLIENT_FETCH_ERROR: + return "Internal error"; + case HS_CLIENT_FETCH_LAUNCHED: + return "Descriptor fetch launched"; + case HS_CLIENT_FETCH_HAVE_DESC: + return "Already have descriptor"; + case HS_CLIENT_FETCH_NO_HSDIRS: + return "No more HSDir available to query"; + case HS_CLIENT_FETCH_NOT_ALLOWED: + return "Fetching descriptors is not allowed"; + case HS_CLIENT_FETCH_MISSING_INFO: + return "Missing directory information"; + case HS_CLIENT_FETCH_PENDING: + return "Pending descriptor fetch"; + default: + return "(Unknown client fetch status code)"; + } +} + +/* Return true iff tor should close the SOCKS request(s) for the descriptor + * fetch that ended up with this given status code. */ +static int +fetch_status_should_close_socks(hs_client_fetch_status_t status) +{ + switch (status) { + case HS_CLIENT_FETCH_NO_HSDIRS: + /* No more HSDir to query, we can't complete the SOCKS request(s). */ + case HS_CLIENT_FETCH_ERROR: + /* The fetch triggered an internal error. */ + case HS_CLIENT_FETCH_NOT_ALLOWED: + /* Client is not allowed to fetch (FetchHidServDescriptors 0). */ + goto close; + case HS_CLIENT_FETCH_MISSING_INFO: + case HS_CLIENT_FETCH_HAVE_DESC: + case HS_CLIENT_FETCH_PENDING: + case HS_CLIENT_FETCH_LAUNCHED: + /* The rest doesn't require tor to close the SOCKS request(s). */ + goto no_close; + } + + no_close: + return 0; + close: + return 1; +}
/* Cancel all descriptor fetches currently in progress. */ static void @@ -136,6 +188,51 @@ directory_request_is_pending(const ed25519_public_key_t *identity_pk) return ret; }
+/* We failed to fetch a descriptor for the service with <b>identity_pk</b> + * because of <b>status</b>. Find all pending SOCKS connections for this + * service that are waiting on the descriptor and close them with + * <b>reason</b>. */ +static void +close_all_socks_conns_waiting_for_desc(const ed25519_public_key_t *identity_pk, + hs_client_fetch_status_t status, + int reason) +{ + unsigned int count = 0; + time_t now = approx_time(); + smartlist_t *conns = + connection_list_by_type_state(CONN_TYPE_AP, AP_CONN_STATE_RENDDESC_WAIT); + + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) { + entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn); + const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn); + + /* Only consider the entry connections that matches the service for which + * we tried to get the descriptor */ + if (!edge_conn->hs_ident || + !ed25519_pubkey_eq(identity_pk, + &edge_conn->hs_ident->identity_pk)) { + continue; + } + assert_connection_ok(base_conn, now); + /* Unattach the entry connection which will close for the reason. */ + connection_mark_unattached_ap(entry_conn, reason); + count++; + } SMARTLIST_FOREACH_END(base_conn); + + if (count > 0) { + char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1]; + hs_build_address(identity_pk, HS_VERSION_THREE, onion_address); + log_notice(LD_REND, "Closed %u streams for service %s.onion " + "for reason %s. Fetch status: %s.", + count, safe_str_client(onion_address), + stream_end_reason_to_string(reason), + fetch_status_to_string(status)); + } + + /* No ownership of the object(s) in this list. */ + smartlist_free(conns); +} + /* A v3 HS circuit successfully connected to the hidden service. Update the * stream state at <b>hs_conn_ident</b> appropriately. */ static void @@ -1037,6 +1134,8 @@ hs_client_any_intro_points_usable(const ed25519_public_key_t *service_pk, int hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk) { + int ret; + tor_assert(identity_pk);
/* Are we configured to fetch descriptors? */ @@ -1080,7 +1179,17 @@ hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk) return HS_CLIENT_FETCH_PENDING; }
- return fetch_v3_desc(identity_pk); + /* Try to fetch the desc and if we encounter an unrecoverable error, mark the + * desc as unavailable for now. */ + ret = fetch_v3_desc(identity_pk); + if (fetch_status_should_close_socks(ret)) { + close_all_socks_conns_waiting_for_desc(identity_pk, ret, + END_STREAM_REASON_RESOLVEFAILED); + /* Remove HSDir fetch attempts so that we can retry later if the user + * wants us to regardless of if we closed any connections. */ + purge_hid_serv_request(identity_pk); + } + return ret; }
/* This is called when we are trying to attach an AP connection to these
tor-commits@lists.torproject.org