mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
hs-v3: Close pending SOCKS connection on descriptor fetch error
Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
cf75c1af66
commit
c232b6b59c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user