diff options
author | George Kadianakis <desnacked@riseup.net> | 2020-04-08 18:15:37 +0300 |
---|---|---|
committer | George Kadianakis <desnacked@riseup.net> | 2020-04-08 18:15:37 +0300 |
commit | 7a82c972efacb5004431ae81326b3a8e55d5fac7 (patch) | |
tree | 8ac7a83885ac9bfc1fab2d3661a5c6f61873705c /src/feature/hs | |
parent | c1bf819a31d729abee8cf1440cefb7b4776248cc (diff) | |
parent | 92ae8cea30d5c4b3cd5283abf571ffdb5ed06bcb (diff) | |
download | tor-7a82c972efacb5004431ae81326b3a8e55d5fac7.tar.gz tor-7a82c972efacb5004431ae81326b3a8e55d5fac7.zip |
Merge branch 'tor-github/pr/1857'
Diffstat (limited to 'src/feature/hs')
-rw-r--r-- | src/feature/hs/hs_circuit.c | 18 | ||||
-rw-r--r-- | src/feature/hs/hs_client.c | 110 | ||||
-rw-r--r-- | src/feature/hs/hs_client.h | 1 |
3 files changed, 129 insertions, 0 deletions
diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c index dc13c7045e..53f574c14a 100644 --- a/src/feature/hs/hs_circuit.c +++ b/src/feature/hs/hs_circuit.c @@ -622,6 +622,20 @@ setup_introduce1_data(const hs_desc_intro_point_t *ip, } /** Helper: cleanup function for client circuit. This is for every HS version. + * It is called from hs_circ_cleanup_on_close() entry point. */ +static void +cleanup_on_close_client_circ(circuit_t *circ) +{ + tor_assert(circ); + + if (circuit_is_hs_v3(circ)) { + hs_client_circuit_cleanup_on_close(circ); + } + /* It is possible the circuit has an HS purpose but no identifier (rend_data + * or hs_ident). Thus possible that this passess through. */ +} + +/** Helper: cleanup function for client circuit. This is for every HS version. * It is called from hs_circ_cleanup_on_free() entry point. */ static void cleanup_on_free_client_circ(circuit_t *circ) @@ -1293,6 +1307,10 @@ hs_circ_cleanup_on_close(circuit_t *circ) { tor_assert(circ); + if (circuit_purpose_is_hs_client(circ->purpose)) { + cleanup_on_close_client_circ(circ); + } + /* On close, we simply remove it from the circuit map. It can not be used * anymore. We keep this code path fast and lean. */ diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index cc1b01d2ef..40647ac256 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -961,6 +961,81 @@ client_get_random_intro(const ed25519_public_key_t *service_pk) return ei; } +/** Return true iff all intro points for the given service have timed out. */ +static bool +intro_points_all_timed_out(const ed25519_public_key_t *service_pk) +{ + bool ret = false; + + tor_assert(service_pk); + + const hs_descriptor_t *desc = hs_cache_lookup_as_client(service_pk); + + SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points, + const hs_desc_intro_point_t *, ip) { + const hs_cache_intro_state_t *state = + hs_cache_client_intro_state_find(service_pk, + &ip->auth_key_cert->signed_key); + if (!state || !state->timed_out) { + /* No state or if this intro point has not timed out, we are done since + * clearly not all of them have timed out. */ + goto end; + } + } SMARTLIST_FOREACH_END(ip); + + /* Exiting the loop here means that all intro points we've looked at have + * timed out. Note that we can _not_ have a descriptor without intro points + * in the client cache. */ + ret = true; + + end: + return ret; +} + +/** Called when a rendezvous circuit has timed out. Every streams attached to + * the circuit will get set with the SOCKS5_HS_REND_FAILED (0xF3) extended + * error code so if the connection to the rendezvous point ends up not + * working, this code could be sent back as a reason. */ +static void +socks_report_rend_circuit_timed_out(const origin_circuit_t *rend_circ) +{ + tor_assert(rend_circ); + + /* For each entry connections attached to this rendezvous circuit, report + * the error. */ + for (edge_connection_t *edge = rend_circ->p_streams; edge; + edge = edge->next_stream) { + entry_connection_t *entry = EDGE_TO_ENTRY_CONN(edge); + if (entry->socks_request) { + entry->socks_request->socks_extended_error_code = + SOCKS5_HS_REND_FAILED; + } + } +} + +/** Called when introduction has failed meaning there is no more usable + * introduction points to be used (either NACKed or failed) for the given + * entry connection. + * + * This function only reports back the SOCKS5_HS_INTRO_FAILED (0xF2) code or + * SOCKS5_HS_INTRO_TIMEDOUT (0xF7) if all intros have timed out. The caller + * has to make sure to close the entry connections. */ +static void +socks_report_introduction_failed(entry_connection_t *conn, + const ed25519_public_key_t *identity_pk) +{ + socks5_reply_status_t code = SOCKS5_HS_INTRO_FAILED; + + tor_assert(conn); + tor_assert(conn->socks_request); + tor_assert(identity_pk); + + if (intro_points_all_timed_out(identity_pk)) { + code = SOCKS5_HS_INTRO_TIMEDOUT; + } + conn->socks_request->socks_extended_error_code = code; +} + /** For this introduction circuit, we'll look at if we have any usable * introduction point left for this service. If so, we'll use the circuit to * re-extend to a new intro point. Else, we'll close the circuit and its @@ -1313,6 +1388,10 @@ client_desc_has_arrived(const smartlist_t *entry_conns) if (!hs_client_any_intro_points_usable(identity_pk, desc)) { log_info(LD_REND, "Hidden service descriptor is unusable. " "Closing streams."); + /* Report the extended socks error code that we were unable to introduce + * to the service. */ + socks_report_introduction_failed(entry_conn, identity_pk); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_RESOLVEFAILED); /* We are unable to use the descriptor so remove the directory request @@ -1762,6 +1841,37 @@ get_hs_client_auths_map(void) /* ========== */ /** Called when a circuit was just cleaned up. This is done right before the + * circuit is marked for close. */ +void +hs_client_circuit_cleanup_on_close(const circuit_t *circ) +{ + bool has_timed_out; + + tor_assert(circ); + tor_assert(CIRCUIT_IS_ORIGIN(circ)); + + has_timed_out = + (circ->marked_for_close_orig_reason == END_CIRC_REASON_TIMEOUT); + + switch (circ->purpose) { + case CIRCUIT_PURPOSE_C_ESTABLISH_REND: + case CIRCUIT_PURPOSE_C_REND_READY: + case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: + case CIRCUIT_PURPOSE_C_REND_JOINED: + /* Report extended SOCKS error code when a rendezvous circuit timeouts. + * This MUST be done on_close() because it is possible the entry + * connection would get closed before the circuit is freed and thus + * failing to report the error code. */ + if (has_timed_out) { + socks_report_rend_circuit_timed_out(CONST_TO_ORIGIN_CIRCUIT(circ)); + } + break; + default: + break; + } +} + +/** Called when a circuit was just cleaned up. This is done right before the * circuit is freed. */ void hs_client_circuit_cleanup_on_free(const circuit_t *circ) diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h index 3660bfa96c..685b10f955 100644 --- a/src/feature/hs/hs_client.h +++ b/src/feature/hs/hs_client.h @@ -110,6 +110,7 @@ int hs_client_send_introduce1(origin_circuit_t *intro_circ, origin_circuit_t *rend_circ); void hs_client_circuit_has_opened(origin_circuit_t *circ); +void hs_client_circuit_cleanup_on_close(const circuit_t *circ); void hs_client_circuit_cleanup_on_free(const circuit_t *circ); int hs_client_receive_rendezvous_acked(origin_circuit_t *circ, |