hs-v3: Set extended error when missing/bad client auth

Part of #30382

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2019-05-28 13:49:03 -04:00 committed by George Kadianakis
parent fb1d212021
commit 542402cd60
3 changed files with 62 additions and 10 deletions

View File

@ -2734,21 +2734,40 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
/* We got something: Try storing it in the cache. */
decode_status = hs_cache_store_as_client(body,
&conn->hs_ident->identity_pk);
if (decode_status != HS_DESC_DECODE_OK) {
log_info(LD_REND, "Failed to store hidden service descriptor");
switch (decode_status) {
case HS_DESC_DECODE_OK:
case HS_DESC_DECODE_NEED_CLIENT_AUTH:
case HS_DESC_DECODE_BAD_CLIENT_AUTH:
log_info(LD_REND, "Stored hidden service descriptor successfully.");
TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
if (decode_status == HS_DESC_DECODE_OK) {
hs_client_desc_has_arrived(conn->hs_ident);
} else {
/* This handles both client auth decode status. */
hs_client_desc_missing_bad_client_auth(conn->hs_ident, decode_status);
log_info(LD_REND, "Stored hidden service descriptor requires "
"%s client authorization.",
decode_status == HS_DESC_DECODE_NEED_CLIENT_AUTH ? "missing"
: "new");
}
/* Fire control port RECEIVED event. */
hs_control_desc_event_received(conn->hs_ident, conn->identity_digest);
hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
body);
break;
case HS_DESC_DECODE_ENCRYPTED_ERROR:
case HS_DESC_DECODE_SUPERENC_ERROR:
case HS_DESC_DECODE_PLAINTEXT_ERROR:
case HS_DESC_DECODE_GENERIC_ERROR:
default:
log_info(LD_REND, "Failed to store hidden service descriptor. "
"Descriptor decoding status: %d", decode_status);
/* Fire control port FAILED event. */
hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
"BAD_DESC");
hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
NULL);
} else {
log_info(LD_REND, "Stored hidden service descriptor successfully.");
TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
hs_client_desc_has_arrived(conn->hs_ident);
/* Fire control port RECEIVED event. */
hs_control_desc_event_received(conn->hs_ident, conn->identity_digest);
hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
body);
break;
}
break;
case 404:

View File

@ -1782,6 +1782,37 @@ hs_client_desc_not_found(const hs_ident_dir_conn_t *ident)
smartlist_free(entry_conns);
}
/* This is called when a descriptor fetch was successful but the descriptor
* couldn't be decrypted due to missing or bad client authorization. */
void
hs_client_desc_missing_bad_client_auth(const hs_ident_dir_conn_t *ident,
hs_desc_decode_status_t status)
{
smartlist_t *entry_conns;
tor_assert(ident);
entry_conns = find_entry_conns(&ident->identity_pk);
SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
socks5_reply_status_t code;
if (status == HS_DESC_DECODE_BAD_CLIENT_AUTH) {
code = SOCKS5_HS_BAD_CLIENT_AUTH;
} else if (status == HS_DESC_DECODE_NEED_CLIENT_AUTH) {
code = SOCKS5_HS_MISSING_CLIENT_AUTH;
} else {
/* We should not be called with another type of status. Recover by
* sending a generic error. */
tor_assert_nonfatal_unreached();
code = HS_DESC_DECODE_GENERIC_ERROR;
}
entry_conn->socks_request->socks_extended_error_code = code;
} SMARTLIST_FOREACH_END(entry_conn);
/* We don't have ownership of the objects in this list. */
smartlist_free(entry_conns);
}
/** Return a newly allocated extend_info_t for a randomly chosen introduction
* point for the given edge connection identifier ident. Return NULL if we
* can't pick any usable introduction points. */

View File

@ -74,6 +74,8 @@ int hs_client_receive_rendezvous2(origin_circuit_t *circ,
void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident);
void hs_client_desc_not_found(const hs_ident_dir_conn_t *ident);
void hs_client_desc_missing_bad_client_auth(const hs_ident_dir_conn_t *ident,
hs_desc_decode_status_t status);
extend_info_t *hs_client_get_random_intro_from_edge(
const edge_connection_t *edge_conn);