commit 2444629c86e3368ebd6c9ee1b54aa5a5959fa398 Author: David Goulet dgoulet@torproject.org Date: Fri Feb 5 10:39:55 2021 -0500
hs-v2: Remove client support
Related to #40266
Signed-off-by: David Goulet dgoulet@torproject.org --- src/app/config/config.c | 3 +- src/app/config/or_options_st.h | 3 - src/app/main/shutdown.c | 2 - src/core/mainloop/connection.c | 1 - src/core/or/circuitlist.c | 2 +- src/core/or/circuitstats.c | 1 - src/core/or/circuituse.c | 7 +- src/core/or/connection_edge.c | 82 +- src/core/or/connection_edge.h | 1 - src/core/or/crypt_path.c | 4 - src/feature/control/control_cmd.c | 5 +- src/feature/control/control_getinfo.c | 30 +- src/feature/dirclient/dirclient.c | 13 - src/feature/dircommon/directory.c | 1 - src/feature/hs/hs_circuit.c | 5 +- src/feature/hs/hs_client.c | 32 +- src/feature/hs/hs_common.c | 5 +- src/feature/hs/hs_config.c | 6 - src/feature/rend/include.am | 2 - src/feature/rend/rendclient.c | 1322 --------------------------------- src/feature/rend/rendclient.h | 54 -- src/feature/rend/rendcommon.c | 2 +- src/feature/rend/rendservice.c | 1 - src/test/test_config.c | 1 - src/test/test_entryconn.c | 41 - src/test/test_hs_common.c | 15 - src/test/test_options.c | 8 - 27 files changed, 26 insertions(+), 1623 deletions(-)
diff --git a/src/app/config/config.c b/src/app/config/config.c index 1e4d18116c..dec4890e70 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -103,7 +103,7 @@ #include "feature/relay/routermode.h" #include "feature/relay/relay_config.h" #include "feature/relay/transport_config.h" -#include "feature/rend/rendclient.h" +#include "feature/rend/rendcommon.h" #include "feature/rend/rendservice.h" #include "lib/geoip/geoip.h" #include "feature/stats/geoip_stats.h" @@ -504,7 +504,6 @@ static const config_var_t option_vars_[] = { VAR("HiddenServiceOnionBalanceInstance", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"), - V(HidServAuth, LINELIST, NULL), V(ClientOnionAuthDir, FILENAME, NULL), OBSOLETE("CloseHSClientCircuitsImmediatelyOnTimeout"), OBSOLETE("CloseHSServiceRendCircuitsImmediatelyOnTimeout"), diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h index 714034b28d..f9c6dae2b6 100644 --- a/src/app/config/or_options_st.h +++ b/src/app/config/or_options_st.h @@ -428,9 +428,6 @@ struct or_options_t { int NumCPUs; /**< How many CPUs should we try to use? */ struct config_line_t *RendConfigLines; /**< List of configuration lines * for rendezvous services. */ - struct config_line_t *HidServAuth; /**< List of configuration lines for - * client-side authorizations for hidden - * services */ char *ClientOnionAuthDir; /**< Directory to keep client * onion service authorization secret keys */ char *ContactInfo; /**< Contact info to be published in the directory. */ diff --git a/src/app/main/shutdown.c b/src/app/main/shutdown.c index 4a556333db..fe80a92991 100644 --- a/src/app/main/shutdown.c +++ b/src/app/main/shutdown.c @@ -46,7 +46,6 @@ #include "feature/relay/ext_orport.h" #include "feature/relay/relay_config.h" #include "feature/rend/rendcache.h" -#include "feature/rend/rendclient.h" #include "feature/stats/bwhist.h" #include "feature/stats/geoip_stats.h" #include "feature/stats/rephist.h" @@ -120,7 +119,6 @@ tor_free_all(int postfork) addressmap_free_all(); dirserv_free_all(); rend_cache_free_all(); - rend_service_authorization_free_all(); rep_hist_free_all(); bwhist_free_all(); circuit_free_all(); diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c index f90872ec22..376994f1c1 100644 --- a/src/core/mainloop/connection.c +++ b/src/core/mainloop/connection.c @@ -106,7 +106,6 @@ #include "feature/relay/dns.h" #include "feature/relay/ext_orport.h" #include "feature/relay/routermode.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendcommon.h" #include "feature/stats/connstats.h" #include "feature/stats/rephist.h" diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c index bd36683880..f6d9fcf534 100644 --- a/src/core/or/circuitlist.c +++ b/src/core/or/circuitlist.c @@ -88,7 +88,7 @@ #include "core/or/policies.h" #include "core/or/relay.h" #include "core/crypto/relay_crypto.h" -#include "feature/rend/rendclient.h" +#include "feature/rend/rendcache.h" #include "feature/rend/rendcommon.h" #include "feature/stats/predict_ports.h" #include "feature/stats/bwhist.h" diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c index b7f5216d72..7f3b5007b3 100644 --- a/src/core/or/circuitstats.c +++ b/src/core/or/circuitstats.c @@ -34,7 +34,6 @@ #include "lib/crypt_ops/crypto_rand.h" #include "core/mainloop/mainloop.h" #include "feature/nodelist/networkstatus.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendservice.h" #include "feature/relay/router.h" #include "app/config/statefile.h" diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c index 11ba059b0e..26c4711a5b 100644 --- a/src/core/or/circuituse.c +++ b/src/core/or/circuituse.c @@ -58,7 +58,6 @@ #include "feature/nodelist/routerlist.h" #include "feature/relay/routermode.h" #include "feature/relay/selftest.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendservice.h" #include "feature/stats/predict_ports.h" @@ -2448,11 +2447,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, extend_info = hs_client_get_random_intro_from_edge(edge_conn); if (!extend_info) { log_info(LD_REND, "No intro points: re-fetching service descriptor."); - if (edge_conn->rend_data) { - rend_client_refetch_v2_renddesc(edge_conn->rend_data); - } else { - hs_client_refetch_hsdesc(&edge_conn->hs_ident->identity_pk); - } + hs_client_refetch_hsdesc(&edge_conn->hs_ident->identity_pk); connection_ap_mark_as_waiting_for_renddesc(conn); return 0; } diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c index aa48d16b7c..37cc24672e 100644 --- a/src/core/or/connection_edge.c +++ b/src/core/or/connection_edge.c @@ -96,7 +96,6 @@ #include "feature/relay/dns.h" #include "feature/relay/router.h" #include "feature/relay/routermode.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendservice.h" #include "feature/stats/predict_ports.h" @@ -251,24 +250,9 @@ connection_mark_unattached_ap_,(entry_connection_t *conn, int endreason, int line, const char *file)) { connection_t *base_conn = ENTRY_TO_CONN(conn); - edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn); tor_assert(base_conn->type == CONN_TYPE_AP); ENTRY_TO_EDGE_CONN(conn)->edge_has_sent_end = 1; /* no circ yet */
- /* If this is a rendezvous stream and it is failing without ever - * being attached to a circuit, assume that an attempt to connect to - * the destination hidden service has just ended. - * - * XXXX This condition doesn't limit to only streams failing - * without ever being attached. That sloppiness should be harmless, - * but we should fix it someday anyway. */ - if ((edge_conn->on_circuit != NULL || edge_conn->edge_has_sent_end) && - connection_edge_is_rendezvous_stream(edge_conn)) { - if (edge_conn->rend_data) { - rend_client_note_connection_attempt_ended(edge_conn->rend_data); - } - } - if (base_conn->marked_for_close) { /* This call will warn as appropriate. */ connection_mark_for_close_(base_conn, line, file); @@ -1636,12 +1620,12 @@ consider_plaintext_ports(entry_connection_t *conn, uint16_t port) * The possible recognized forms are (where true is returned): * * If address is of the form "y.onion" with a well-formed handle y: - * Put a NUL after y, lower-case it, and return ONION_V2_HOSTNAME or - * ONION_V3_HOSTNAME depending on the HS version. + * Put a NUL after y, lower-case it, and return ONION_V3_HOSTNAME + * depending on the HS version. * * If address is of the form "x.y.onion" with a well-formed handle x: * Drop "x.", put a NUL after y, lower-case it, and return - * ONION_V2_HOSTNAME or ONION_V3_HOSTNAME depending on the HS version. + * ONION_V3_HOSTNAME depending on the HS version. * * If address is of the form "y.onion" with a badly-formed handle y: * Return BAD_HOSTNAME and log a message. @@ -1691,14 +1675,6 @@ parse_extended_hostname(char *address, hostname_type_t *type_out) if (q != address) { memmove(address, q, strlen(q) + 1 /* also get \0 */); } - /* v2 onion address check. */ - if (strlen(query) == REND_SERVICE_ID_LEN_BASE32) { - *type_out = ONION_V2_HOSTNAME; - if (rend_valid_v2_service_id(query)) { - goto success; - } - goto failed; - }
/* v3 onion address check. */ if (strlen(query) == HS_SERVICE_ADDR_LEN_BASE32) { @@ -1718,8 +1694,7 @@ parse_extended_hostname(char *address, hostname_type_t *type_out) failed: /* otherwise, return to previous state and return 0 */ *s = '.'; - const bool is_onion = (*type_out == ONION_V2_HOSTNAME) || - (*type_out == ONION_V3_HOSTNAME); + const bool is_onion = (*type_out == ONION_V3_HOSTNAME); log_warn(LD_APP, "Invalid %shostname %s; rejecting", is_onion ? "onion " : "", safe_str_client(address)); @@ -2004,41 +1979,7 @@ connection_ap_handle_onion(entry_connection_t *conn, int rend_cache_lookup_result = -ENOENT; int descriptor_is_usable = 0;
- if (addresstype == ONION_V2_HOSTNAME) { /* it's a v2 hidden service */ - rend_cache_entry_t *entry = NULL; - /* Look up if we have client authorization configured for this hidden - * service. If we do, associate it with the rend_data. */ - rend_service_authorization_t *client_auth = - rend_client_lookup_service_authorization(socks->address); - - const uint8_t *cookie = NULL; - rend_auth_type_t auth_type = REND_NO_AUTH; - if (client_auth) { - log_info(LD_REND, "Using previously configured client authorization " - "for hidden service request."); - auth_type = client_auth->auth_type; - cookie = client_auth->descriptor_cookie; - } - - /* Fill in the rend_data field so we can start doing a connection to - * a hidden service. */ - rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data = - rend_data_client_create(socks->address, NULL, (char *) cookie, - auth_type); - if (rend_data == NULL) { - return -1; - } - onion_address = rend_data_get_address(rend_data); - log_info(LD_REND,"Got a hidden service request for ID '%s'", - safe_str_client(onion_address)); - - rend_cache_lookup_result = rend_cache_lookup_entry(onion_address,-1, - &entry); - if (!rend_cache_lookup_result && entry) { - descriptor_is_usable = rend_client_any_intro_points_usable(entry); - } - } else { /* it's a v3 hidden service */ - tor_assert(addresstype == ONION_V3_HOSTNAME); + if (addresstype == ONION_V3_HOSTNAME) { const hs_descriptor_t *cached_desc = NULL; int retval; /* Create HS conn identifier with HS pubkey */ @@ -2108,13 +2049,7 @@ connection_ap_handle_onion(entry_connection_t *conn, edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn); connection_ap_mark_as_non_pending_circuit(conn); base_conn->state = AP_CONN_STATE_RENDDESC_WAIT; - 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); + if (addresstype == ONION_V3_HOSTNAME) { tor_assert(edge_conn->hs_ident); /* Attempt to fetch the hsv3 descriptor. Check the retval to see how it * went and act accordingly. */ @@ -2313,7 +2248,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, }
/* Now, we handle everything that isn't a .onion address. */ - if (addresstype != ONION_V2_HOSTNAME && addresstype != ONION_V3_HOSTNAME) { + if (addresstype != ONION_V3_HOSTNAME) { /* Not a hidden-service request. It's either a hostname or an IP, * possibly with a .exit that we stripped off. We're going to check * if we're allowed to connect/resolve there, and then launch the @@ -2579,8 +2514,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, return 0; } else { /* If we get here, it's a request for a .onion address! */ - tor_assert(addresstype == ONION_V2_HOSTNAME || - addresstype == ONION_V3_HOSTNAME); + tor_assert(addresstype == ONION_V3_HOSTNAME); tor_assert(!automap); return connection_ap_handle_onion(conn, socks, circ, addresstype); } diff --git a/src/core/or/connection_edge.h b/src/core/or/connection_edge.h index c9433adade..701812b9bb 100644 --- a/src/core/or/connection_edge.h +++ b/src/core/or/connection_edge.h @@ -80,7 +80,6 @@ typedef enum hostname_type_t { BAD_HOSTNAME, EXIT_HOSTNAME, NORMAL_HOSTNAME, - ONION_V2_HOSTNAME, ONION_V3_HOSTNAME, } hostname_type_t;
diff --git a/src/core/or/crypt_path.c b/src/core/or/crypt_path.c index e1bbd81251..f035cf461a 100644 --- a/src/core/or/crypt_path.c +++ b/src/core/or/crypt_path.c @@ -15,10 +15,6 @@ * some more effort: * * - circuit_list_path_impl() - * - Functions dealing with cpaths in HSv2 create_rend_cpath() and - * create_rend_cpath_legacy() - * - The cpath related parts of rend_service_receive_introduction() and - * rend_client_send_introduction(). **/
#define CRYPT_PATH_PRIVATE diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c index 623c6d2eae..737a5927e9 100644 --- a/src/feature/control/control_cmd.c +++ b/src/feature/control/control_cmd.c @@ -37,7 +37,6 @@ #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerinfo.h" #include "feature/nodelist/routerlist.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendparse.h" #include "feature/rend/rendservice.h" @@ -1520,9 +1519,7 @@ handle_control_hsfetch(control_connection_t *conn, /* Trigger the fetch using the built rend query and possibly a list of HS * directory to use. This function ignores the client cache thus this will * always send a fetch command. */ - if (version == HS_VERSION_TWO) { - rend_client_fetch_v2_desc(rend_query, hsdirs); - } else if (version == HS_VERSION_THREE) { + if (version == HS_VERSION_THREE) { hs_control_hsfetch_command(&v3_pk, hsdirs); }
diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c index 5feadd23d1..75d5418d19 100644 --- a/src/feature/control/control_getinfo.c +++ b/src/feature/control/control_getinfo.c @@ -542,25 +542,14 @@ getinfo_helper_dir(control_connection_t *control_conn, hostname_type_t addr_type;
question += strlen("hs/client/desc/id/"); - if (rend_valid_v2_service_id(question)) { - addr_type = ONION_V2_HOSTNAME; - } else if (hs_address_is_valid(question)) { + if (hs_address_is_valid(question)) { addr_type = ONION_V3_HOSTNAME; } else { *errmsg = "Invalid address"; return -1; }
- if (addr_type == ONION_V2_HOSTNAME) { - rend_cache_entry_t *e = NULL; - if (!rend_cache_lookup_entry(question, -1, &e)) { - /* Descriptor found in cache */ - *answer = tor_strdup(e->desc); - } else { - *errmsg = "Not found in cache"; - return -1; - } - } else { + if (addr_type == ONION_V3_HOSTNAME) { ed25519_public_key_t service_pk; const char *desc;
@@ -584,25 +573,14 @@ getinfo_helper_dir(control_connection_t *control_conn, hostname_type_t addr_type;
question += strlen("hs/service/desc/id/"); - if (rend_valid_v2_service_id(question)) { - addr_type = ONION_V2_HOSTNAME; - } else if (hs_address_is_valid(question)) { + if (hs_address_is_valid(question)) { addr_type = ONION_V3_HOSTNAME; } else { *errmsg = "Invalid address"; return -1; } - rend_cache_entry_t *e = NULL;
- if (addr_type == ONION_V2_HOSTNAME) { - if (!rend_cache_lookup_v2_desc_as_service(question, &e)) { - /* Descriptor found in cache */ - *answer = tor_strdup(e->desc); - } else { - *errmsg = "Not found in cache"; - return -1; - } - } else { + if (addr_type == ONION_V3_HOSTNAME) { ed25519_public_key_t service_pk; char *desc;
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c index a5dd856729..dd7af9dbfc 100644 --- a/src/feature/dirclient/dirclient.c +++ b/src/feature/dirclient/dirclient.c @@ -48,7 +48,6 @@ #include "feature/relay/routermode.h" #include "feature/relay/selftest.h" #include "feature/rend/rendcache.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendservice.h" #include "feature/stats/predict_ports.h" @@ -2861,7 +2860,6 @@ handle_response_fetch_renddesc_v2(dir_connection_t *conn, conn->identity_digest, body); conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2; - rend_client_desc_trynow(service_id); memwipe(service_id, 0, sizeof(service_id)); } break; @@ -3024,17 +3022,6 @@ connection_dir_client_refetch_hsdesc_if_needed(dir_connection_t *dir_conn) { connection_t *conn = TO_CONN(dir_conn);
- /* If we were trying to fetch a v2 rend desc and did not succeed, retry as - * needed. (If a fetch is successful, the connection state is changed to - * DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 or DIR_PURPOSE_HAS_FETCHED_HSDESC to - * mark that refetching is unnecessary.) */ - if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 && - dir_conn->rend_data && - rend_valid_v2_service_id( - rend_data_get_address(dir_conn->rend_data))) { - rend_client_refetch_v2_renddesc(dir_conn->rend_data); - } - /* Check for v3 rend desc fetch */ if (conn->purpose == DIR_PURPOSE_FETCH_HSDESC && dir_conn->hs_ident && diff --git a/src/feature/dircommon/directory.c b/src/feature/dircommon/directory.c index b276ac3441..0029eb37a1 100644 --- a/src/feature/dircommon/directory.c +++ b/src/feature/dircommon/directory.c @@ -68,7 +68,6 @@ * router_upload_dir_desc_to_dirservers() in router.c * upload_service_descriptor() in rendservice.c * - directory_get_from_dirserver(), called from - * rend_client_refetch_renddesc() in rendclient.c * run_scheduled_events() in main.c * do_hup() in main.c * - connection_dir_process_inbuf(), called from diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c index f0059a1a7c..b246ab423c 100644 --- a/src/feature/hs/hs_circuit.c +++ b/src/feature/hs/hs_circuit.c @@ -29,7 +29,6 @@ #include "feature/nodelist/describe.h" #include "feature/nodelist/nodelist.h" #include "feature/rend/rendservice.h" -#include "feature/rend/rendclient.h" #include "feature/stats/rephist.h" #include "lib/crypt_ops/crypto_dh.h" #include "lib/crypt_ops/crypto_rand.h" @@ -647,9 +646,7 @@ cleanup_on_free_client_circ(circuit_t *circ) { tor_assert(circ);
- if (circuit_is_hs_v2(circ)) { - rend_client_circuit_cleanup_on_free(circ); - } else if (circuit_is_hs_v3(circ)) { + if (circuit_is_hs_v3(circ)) { hs_client_circuit_cleanup_on_free(circ); } /* It is possible the circuit has an HS purpose but no identifier (rend_data diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index 3b03bda1f5..28bbe72459 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -34,7 +34,6 @@ #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerset.h" -#include "feature/rend/rendclient.h" #include "lib/crypt_ops/crypto_format.h" #include "lib/crypt_ops/crypto_rand.h" #include "lib/crypt_ops/crypto_util.h" @@ -1959,9 +1958,6 @@ hs_client_note_connection_attempt_succeeded(const edge_connection_t *conn) if (conn->hs_ident) { /* It's v3: pass it to the prop224 handler */ note_connection_attempt_succeeded(conn->hs_ident); return; - } else if (conn->rend_data) { /* It's v2: pass it to the legacy handler */ - rend_client_note_connection_attempt_ended(conn->rend_data); - return; } }
@@ -2087,9 +2083,7 @@ int hs_client_send_introduce1(origin_circuit_t *intro_circ, origin_circuit_t *rend_circ) { - return (intro_circ->hs_ident) ? send_introduce1(intro_circ, rend_circ) : - rend_client_send_introduction(intro_circ, - rend_circ); + return send_introduce1(intro_circ, rend_circ); }
/** Called when the client circuit circ has been established. It can be either @@ -2106,15 +2100,11 @@ hs_client_circuit_has_opened(origin_circuit_t *circ) case CIRCUIT_PURPOSE_C_INTRODUCING: if (circ->hs_ident) { client_intro_circ_has_opened(circ); - } else { - rend_client_introcirc_has_opened(circ); } break; case CIRCUIT_PURPOSE_C_ESTABLISH_REND: if (circ->hs_ident) { client_rendezvous_circ_has_opened(circ); - } else { - rend_client_rendcirc_has_opened(circ); } break; default: @@ -2428,9 +2418,7 @@ hs_client_get_random_intro_from_edge(const edge_connection_t *edge_conn) { tor_assert(edge_conn);
- return (edge_conn->hs_ident) ? - client_get_random_intro(&edge_conn->hs_ident->identity_pk) : - rend_client_get_random_intro(edge_conn->rend_data); + return client_get_random_intro(&edge_conn->hs_ident->identity_pk); }
/** Called when get an INTRODUCE_ACK cell on the introduction circuit circ. @@ -2452,9 +2440,7 @@ hs_client_receive_introduce_ack(origin_circuit_t *circ, goto end; }
- ret = (circ->hs_ident) ? handle_introduce_ack(circ, payload, payload_len) : - rend_client_introduction_acked(circ, payload, - payload_len); + ret = handle_introduce_ack(circ, payload, payload_len); /* For path bias: This circuit was used successfully. NACK or ACK counts. */ pathbias_mark_use_success(circ);
@@ -2488,9 +2474,8 @@ hs_client_receive_rendezvous2(origin_circuit_t *circ, log_info(LD_REND, "Got RENDEZVOUS2 cell from hidden service on circuit %u.", TO_CIRCUIT(circ)->n_circ_id);
- ret = (circ->hs_ident) ? handle_rendezvous2(circ, payload, payload_len) : - rend_client_receive_rendezvous(circ, payload, - payload_len); + ret = handle_rendezvous2(circ, payload, payload_len); + end: return ret; } @@ -2511,9 +2496,7 @@ hs_client_reextend_intro_circuit(origin_circuit_t *circ)
tor_assert(circ);
- ei = (circ->hs_ident) ? - client_get_random_intro(&circ->hs_ident->identity_pk) : - rend_client_get_random_intro(circ->rend_data); + ei = client_get_random_intro(&circ->hs_ident->identity_pk); if (ei == NULL) { log_warn(LD_REND, "No usable introduction points left. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); @@ -2591,9 +2574,6 @@ hs_client_free_all(void) void hs_client_purge_state(void) { - /* v2 subsystem. */ - rend_client_purge_state(); - /* Cancel all descriptor fetches. Do this first so once done we are sure * that our descriptor cache won't modified. */ cancel_descriptor_fetches(); diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c index fa27ac5223..91cb6d529b 100644 --- a/src/feature/hs/hs_common.c +++ b/src/feature/hs/hs_common.c @@ -1559,9 +1559,8 @@ hs_clean_last_hid_serv_requests(time_t now) * <b>req_key_str</b> from the history of times of requests to hidden service * directories. * - * This is called from rend_client_note_connection_attempt_ended(), which - * must be idempotent, so any future changes to this function must leave it - * idempotent too. */ + * This is called from purge_hid_serv_request(), which must be idempotent, so + * any future changes to this function must leave it idempotent too. */ void hs_purge_hid_serv_from_last_hid_serv_requests(const char *req_key_str) { diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c index 7ffc7ecb96..403ea151c4 100644 --- a/src/feature/hs/hs_config.c +++ b/src/feature/hs/hs_config.c @@ -28,7 +28,6 @@ #include "feature/hs/hs_client.h" #include "feature/hs/hs_ob.h" #include "feature/hs/hs_service.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendservice.h" #include "lib/encoding/confline.h" #include "lib/conf/confdecl.h" @@ -717,11 +716,6 @@ hs_config_client_auth_all(const or_options_t *options, int validate_only) { int ret = -1;
- /* Configure v2 authorization. */ - if (rend_parse_service_authorization(options, validate_only) < 0) { - goto done; - } - /* Configure v3 authorization. */ if (hs_config_client_authorization(options, validate_only) < 0) { goto done; diff --git a/src/feature/rend/include.am b/src/feature/rend/include.am index fb12439a90..8ad85bd7b1 100644 --- a/src/feature/rend/include.am +++ b/src/feature/rend/include.am @@ -2,7 +2,6 @@ # ADD_C_FILE: INSERT SOURCES HERE. LIBTOR_APP_A_SOURCES += \ src/feature/rend/rendcache.c \ - src/feature/rend/rendclient.c \ src/feature/rend/rendcommon.c \ src/feature/rend/rendmid.c \ src/feature/rend/rendparse.c \ @@ -15,7 +14,6 @@ noinst_HEADERS += \ src/feature/rend/rend_intro_point_st.h \ src/feature/rend/rend_service_descriptor_st.h \ src/feature/rend/rendcache.h \ - src/feature/rend/rendclient.h \ src/feature/rend/rendcommon.h \ src/feature/rend/rendmid.h \ src/feature/rend/rendparse.h \ diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c deleted file mode 100644 index 3dda7cd46d..0000000000 --- a/src/feature/rend/rendclient.c +++ /dev/null @@ -1,1322 +0,0 @@ -/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2020, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file rendclient.c - * \brief Client code to access location-hidden services. - **/ - -#include "core/or/or.h" -#include "app/config/config.h" -#include "core/mainloop/connection.h" -#include "core/mainloop/mainloop.h" -#include "core/or/circuitbuild.h" -#include "core/or/circuitlist.h" -#include "core/or/circuituse.h" -#include "core/or/connection_edge.h" -#include "core/or/extendinfo.h" -#include "core/or/relay.h" -#include "feature/client/circpathbias.h" -#include "feature/control/control_events.h" -#include "feature/dirclient/dirclient.h" -#include "feature/dircommon/directory.h" -#include "feature/hs/hs_circuit.h" -#include "feature/hs/hs_client.h" -#include "feature/hs/hs_common.h" -#include "feature/nodelist/describe.h" -#include "feature/nodelist/networkstatus.h" -#include "feature/nodelist/nodelist.h" -#include "feature/nodelist/routerlist.h" -#include "feature/nodelist/routerset.h" -#include "feature/rend/rendclient.h" -#include "feature/rend/rendcommon.h" -#include "feature/stats/rephist.h" -#include "lib/crypt_ops/crypto_dh.h" -#include "lib/crypt_ops/crypto_rand.h" -#include "lib/crypt_ops/crypto_util.h" -#include "lib/encoding/confline.h" - -#include "core/or/cpath_build_state_st.h" -#include "core/or/crypt_path_st.h" -#include "feature/dircommon/dir_connection_st.h" -#include "core/or/entry_connection_st.h" -#include "core/or/extend_info_st.h" -#include "core/or/origin_circuit_st.h" -#include "feature/rend/rend_intro_point_st.h" -#include "feature/rend/rend_service_descriptor_st.h" -#include "feature/nodelist/routerstatus_st.h" - -static extend_info_t *rend_client_get_random_intro_impl( - const rend_cache_entry_t *rend_query, - const int strict, const int warnings); - -/** Purge all potentially remotely-detectable state held in the hidden - * service client code. Called on SIGNAL NEWNYM. */ -void -rend_client_purge_state(void) -{ - rend_cache_purge(); - rend_cache_failure_purge(); - rend_client_cancel_descriptor_fetches(); - hs_purge_last_hid_serv_requests(); -} - -/** Called when we've established a circuit to an introduction point: - * send the introduction request. */ -void -rend_client_introcirc_has_opened(origin_circuit_t *circ) -{ - tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); - tor_assert(circ->cpath); - - log_info(LD_REND,"introcirc is open"); - connection_ap_attach_pending(1); -} - -/** Send the establish-rendezvous cell along a rendezvous circuit. if - * it fails, mark the circ for close and return -1. else return 0. - */ -static int -rend_client_send_establish_rendezvous(origin_circuit_t *circ) -{ - tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); - tor_assert(circ->rend_data); - log_info(LD_REND, "Sending an ESTABLISH_RENDEZVOUS cell"); - - crypto_rand(circ->rend_data->rend_cookie, REND_COOKIE_LEN); - - /* Set timestamp_dirty, because circuit_expire_building expects it, - * and the rend cookie also means we've used the circ. */ - circ->base_.timestamp_dirty = time(NULL); - - /* We've attempted to use this circuit. Probe it if we fail */ - pathbias_count_use_attempt(circ); - - if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), - RELAY_COMMAND_ESTABLISH_RENDEZVOUS, - circ->rend_data->rend_cookie, - REND_COOKIE_LEN, - circ->cpath->prev)<0) { - /* circ is already marked for close */ - log_warn(LD_GENERAL, "Couldn't send ESTABLISH_RENDEZVOUS cell"); - return -1; - } - - return 0; -} - -/** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell - * down introcirc if possible. - */ -int -rend_client_send_introduction(origin_circuit_t *introcirc, - origin_circuit_t *rendcirc) -{ - const or_options_t *options = get_options(); - size_t payload_len; - int r, v3_shift = 0; - char payload[RELAY_PAYLOAD_SIZE]; - char tmp[RELAY_PAYLOAD_SIZE]; - rend_cache_entry_t *entry = NULL; - crypt_path_t *cpath; - ptrdiff_t dh_offset; - crypto_pk_t *intro_key = NULL; - int status = 0; - const char *onion_address; - - tor_assert(introcirc->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING); - tor_assert(rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY); - tor_assert(introcirc->rend_data); - tor_assert(rendcirc->rend_data); - tor_assert(!rend_cmp_service_ids(rend_data_get_address(introcirc->rend_data), - rend_data_get_address(rendcirc->rend_data))); - assert_circ_anonymity_ok(introcirc, options); - assert_circ_anonymity_ok(rendcirc, options); - onion_address = rend_data_get_address(introcirc->rend_data); - - r = rend_cache_lookup_entry(onion_address, -1, &entry); - /* An invalid onion address is not possible else we have a big issue. */ - tor_assert(r != -EINVAL); - if (r < 0 || !rend_client_any_intro_points_usable(entry)) { - /* If the descriptor is not found or the intro points are not usable - * anymore, trigger a fetch. */ - log_info(LD_REND, - "query %s didn't have valid rend desc in cache. " - "Refetching descriptor.", - safe_str_client(onion_address)); - rend_client_refetch_v2_renddesc(introcirc->rend_data); - { - connection_t *conn; - - while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP, - AP_CONN_STATE_CIRCUIT_WAIT, onion_address))) { - connection_ap_mark_as_waiting_for_renddesc(TO_ENTRY_CONN(conn)); - } - } - - status = -1; - goto cleanup; - } - - /* first 20 bytes of payload are the hash of the service's pk */ - intro_key = NULL; - SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, - intro, { - if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest, - intro->extend_info->identity_digest, DIGEST_LEN)) { - intro_key = intro->intro_key; - break; - } - }); - if (!intro_key) { - log_info(LD_REND, "Could not find intro key for %s at %s; we " - "have a v2 rend desc with %d intro points. " - "Trying a different intro point...", - safe_str_client(onion_address), - safe_str_client(extend_info_describe( - introcirc->build_state->chosen_exit)), - smartlist_len(entry->parsed->intro_nodes)); - - if (hs_client_reextend_intro_circuit(introcirc)) { - status = -2; - goto perm_err; - } else { - status = -1; - goto cleanup; - } - } - if (crypto_pk_get_digest(intro_key, payload)<0) { - log_warn(LD_BUG, "Internal error: couldn't hash public key."); - status = -2; - goto perm_err; - } - - /* Initialize the pending_final_cpath and start the DH handshake. */ - cpath = rendcirc->build_state->pending_final_cpath; - if (!cpath) { - cpath = rendcirc->build_state->pending_final_cpath = - tor_malloc_zero(sizeof(crypt_path_t)); - cpath->magic = CRYPT_PATH_MAGIC; - if (!(cpath->rend_dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) { - log_warn(LD_BUG, "Internal error: couldn't allocate DH."); - status = -2; - goto perm_err; - } - if (crypto_dh_generate_public(cpath->rend_dh_handshake_state)<0) { - log_warn(LD_BUG, "Internal error: couldn't generate g^x."); - status = -2; - goto perm_err; - } - } - - /* If version is 3, write (optional) auth data and timestamp. */ - if (entry->parsed->protocols & (1<<3)) { - tmp[0] = 3; /* version 3 of the cell format */ - /* auth type, if any */ - tmp[1] = (uint8_t) TO_REND_DATA_V2(introcirc->rend_data)->auth_type; - v3_shift = 1; - if (tmp[1] != REND_NO_AUTH) { - set_uint16(tmp+2, htons(REND_DESC_COOKIE_LEN)); - memcpy(tmp+4, TO_REND_DATA_V2(introcirc->rend_data)->descriptor_cookie, - REND_DESC_COOKIE_LEN); - v3_shift += 2+REND_DESC_COOKIE_LEN; - } - /* Once this held a timestamp. */ - set_uint32(tmp+v3_shift+1, 0); - v3_shift += 4; - } /* if version 2 only write version number */ - else if (entry->parsed->protocols & (1<<2)) { - tmp[0] = 2; /* version 2 of the cell format */ - } - - /* write the remaining items into tmp */ - if (entry->parsed->protocols & (1<<3) || entry->parsed->protocols & (1<<2)) { - /* version 2 format */ - extend_info_t *extend_info = rendcirc->build_state->chosen_exit; - int klen; - const tor_addr_port_t *orport = - extend_info_get_orport(extend_info, AF_INET); - IF_BUG_ONCE(! orport) { - /* we should never put an IPv6 address here. */ - goto perm_err; - } - /* nul pads */ - set_uint32(tmp+v3_shift+1, tor_addr_to_ipv4n(&orport->addr)); - set_uint16(tmp+v3_shift+5, htons(orport->port)); - memcpy(tmp+v3_shift+7, extend_info->identity_digest, DIGEST_LEN); - klen = crypto_pk_asn1_encode(extend_info->onion_key, - tmp+v3_shift+7+DIGEST_LEN+2, - sizeof(tmp)-(v3_shift+7+DIGEST_LEN+2)); - if (klen < 0) { - log_warn(LD_BUG,"Internal error: can't encode public key."); - status = -2; - goto perm_err; - } - set_uint16(tmp+v3_shift+7+DIGEST_LEN, htons(klen)); - memcpy(tmp+v3_shift+7+DIGEST_LEN+2+klen, rendcirc->rend_data->rend_cookie, - REND_COOKIE_LEN); - dh_offset = v3_shift+7+DIGEST_LEN+2+klen+REND_COOKIE_LEN; - } else { - /* Version 0. */ - - /* Some compilers are smart enough to work out that nickname can be more - * than 19 characters, when it's a hexdigest. They warn that strncpy() - * will truncate hexdigests without NUL-terminating them. But we only put - * hexdigests in HSDir and general circuit exits. */ - if (BUG(strlen(rendcirc->build_state->chosen_exit->nickname) - > MAX_NICKNAME_LEN)) { - goto perm_err; - } - strlcpy(tmp, rendcirc->build_state->chosen_exit->nickname, - sizeof(tmp)); - memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_data->rend_cookie, - REND_COOKIE_LEN); - dh_offset = MAX_NICKNAME_LEN+1+REND_COOKIE_LEN; - } - - if (crypto_dh_get_public(cpath->rend_dh_handshake_state, tmp+dh_offset, - DH1024_KEY_LEN)<0) { - log_warn(LD_BUG, "Internal error: couldn't extract g^x."); - status = -2; - goto perm_err; - } - - /*XXX maybe give crypto_pk_obsolete_public_hybrid_encrypt a max_len arg, - * to avoid buffer overflows? */ - r = crypto_pk_obsolete_public_hybrid_encrypt(intro_key, payload+DIGEST_LEN, - sizeof(payload)-DIGEST_LEN, - tmp, - (int)(dh_offset+DH1024_KEY_LEN), - PK_PKCS1_OAEP_PADDING, 0); - if (r<0) { - log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed."); - status = -2; - goto perm_err; - } - - payload_len = DIGEST_LEN + r; - tor_assert(payload_len <= RELAY_PAYLOAD_SIZE); /* we overran something */ - - /* Copy the rendezvous cookie from rendcirc to introcirc, so that - * when introcirc gets an ack, we can change the state of the right - * rendezvous circuit. */ - memcpy(introcirc->rend_data->rend_cookie, rendcirc->rend_data->rend_cookie, - REND_COOKIE_LEN); - - log_info(LD_REND, "Sending an INTRODUCE1 cell"); - if (relay_send_command_from_edge(0, TO_CIRCUIT(introcirc), - RELAY_COMMAND_INTRODUCE1, - payload, payload_len, - introcirc->cpath->prev)<0) { - /* introcirc is already marked for close. leave rendcirc alone. */ - log_warn(LD_BUG, "Couldn't send INTRODUCE1 cell"); - status = -2; - goto cleanup; - } - - /* Now, we wait for an ACK or NAK on this circuit. */ - circuit_change_purpose(TO_CIRCUIT(introcirc), - CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT); - /* Set timestamp_dirty, because circuit_expire_building expects it - * to specify when a circuit entered the _C_INTRODUCE_ACK_WAIT - * state. */ - introcirc->base_.timestamp_dirty = time(NULL); - - pathbias_count_use_attempt(introcirc); - - goto cleanup; - - perm_err: - if (!introcirc->base_.marked_for_close) - circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL); - circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL); - cleanup: - memwipe(payload, 0, sizeof(payload)); - memwipe(tmp, 0, sizeof(tmp)); - - return status; -} - -/** Called when a rendezvous circuit is open; sends a establish - * rendezvous circuit as appropriate. */ -void -rend_client_rendcirc_has_opened(origin_circuit_t *circ) -{ - tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); - - log_info(LD_REND,"rendcirc is open"); - - /* generate a rendezvous cookie, store it in circ */ - if (rend_client_send_establish_rendezvous(circ) < 0) { - return; - } -} - -/** - * Called to close other intro circuits we launched in parallel. - */ -static void -rend_client_close_other_intros(const uint8_t *rend_pk_digest) -{ - /* abort parallel intro circs, if any */ - SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) { - if ((c->purpose == CIRCUIT_PURPOSE_C_INTRODUCING || - c->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) && - !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { - origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c); - if (oc->rend_data && - rend_circuit_pk_digest_eq(oc, rend_pk_digest)) { - log_info(LD_REND|LD_CIRC, "Closing introduction circuit %d that we " - "built in parallel (Purpose %d).", oc->global_identifier, - c->purpose); - circuit_mark_for_close(c, END_CIRC_REASON_IP_NOW_REDUNDANT); - } - } - } - SMARTLIST_FOREACH_END(c); -} - -/** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell. - */ -int -rend_client_introduction_acked(origin_circuit_t *circ, - const uint8_t *request, size_t request_len) -{ - const or_options_t *options = get_options(); - origin_circuit_t *rendcirc; - (void) request; // XXXX Use this. - - tor_assert(circ->build_state); - tor_assert(circ->build_state->chosen_exit); - assert_circ_anonymity_ok(circ, options); - tor_assert(circ->rend_data); - - if (request_len == 0) { - /* It's an ACK; the introduction point relayed our introduction request. */ - /* Locate the rend circ which is waiting to hear about this ack, - * and tell it. - */ - log_info(LD_REND,"Received ack. Telling rend circ..."); - rendcirc = circuit_get_ready_rend_circ_by_rend_data(circ->rend_data); - if (rendcirc) { /* remember the ack */ - assert_circ_anonymity_ok(rendcirc, options); - circuit_change_purpose(TO_CIRCUIT(rendcirc), - CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED); - /* Set timestamp_dirty, because circuit_expire_building expects - * it to specify when a circuit entered the - * _C_REND_READY_INTRO_ACKED state. */ - rendcirc->base_.timestamp_dirty = time(NULL); - } else { - log_info(LD_REND,"...Found no rend circ. Dropping on the floor."); - } - /* Save the rend data digest to a temporary object so that we don't access - * it after we mark the circuit for close. */ - const uint8_t *rend_digest_tmp = NULL; - size_t digest_len; - uint8_t *cached_rend_digest = NULL; - rend_digest_tmp = rend_data_get_pk_digest(circ->rend_data, &digest_len); - cached_rend_digest = tor_malloc_zero(digest_len); - memcpy(cached_rend_digest, rend_digest_tmp, digest_len); - - /* close the circuit: we won't need it anymore. */ - circuit_change_purpose(TO_CIRCUIT(circ), - CIRCUIT_PURPOSE_C_INTRODUCE_ACKED); - circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); - - /* close any other intros launched in parallel */ - rend_client_close_other_intros(cached_rend_digest); - tor_free(cached_rend_digest); /* free the temporary digest */ - } else { - /* It's a NAK; the introduction point didn't relay our request. */ - circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_INTRODUCING); - /* Remove this intro point from the set of viable introduction - * points. If any remain, extend to a new one and try again. - * If none remain, refetch the service descriptor. - */ - log_info(LD_REND, "Got nack for %s from %s...", - safe_str_client(rend_data_get_address(circ->rend_data)), - safe_str_client(extend_info_describe(circ->build_state->chosen_exit))); - if (rend_client_report_intro_point_failure(circ->build_state->chosen_exit, - circ->rend_data, - INTRO_POINT_FAILURE_GENERIC)>0) { - /* There are introduction points left. Re-extend the circuit to - * another intro point and try again. */ - int result = hs_client_reextend_intro_circuit(circ); - /* XXXX If that call failed, should we close the rend circuit, - * too? */ - return result; - } else { - /* Close circuit because no more intro points are usable thus not - * useful anymore. Change it's purpose before so we don't report an - * intro point failure again triggering an extra descriptor fetch. */ - circuit_change_purpose(TO_CIRCUIT(circ), - CIRCUIT_PURPOSE_C_INTRODUCE_ACKED); - circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); - } - } - return 0; -} - -/** Determine the responsible hidden service directories for <b>desc_id</b> - * and fetch the descriptor with that ID from one of them. Only - * send a request to a hidden service directory that we have not yet tried - * during this attempt to connect to this hidden service; on success, return 1, - * in the case that no hidden service directory is left to ask for the - * descriptor, return 0, and in case of a failure -1. */ -static int -directory_get_from_hs_dir(const char *desc_id, - const rend_data_t *rend_query, - routerstatus_t *rs_hsdir) -{ - routerstatus_t *hs_dir = rs_hsdir; - char *hsdir_fp; - char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; - char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64]; - const rend_data_v2_t *rend_data; - const int how_to_fetch = DIRIND_ANONYMOUS; - - tor_assert(desc_id); - tor_assert(rend_query); - rend_data = TO_REND_DATA_V2(rend_query); - - base32_encode(desc_id_base32, sizeof(desc_id_base32), - desc_id, DIGEST_LEN); - - /* Automatically pick an hs dir if none given. */ - if (!rs_hsdir) { - bool rate_limited = false; - - /* Determine responsible dirs. Even if we can't get all we want, work with - * the ones we have. If it's empty, we'll notice in hs_pick_hsdir(). */ - smartlist_t *responsible_dirs = smartlist_new(); - hid_serv_get_responsible_directories(responsible_dirs, desc_id); - - hs_dir = hs_pick_hsdir(responsible_dirs, desc_id_base32, &rate_limited); - if (!hs_dir) { - /* No suitable hs dir can be found, stop right now. */ - const char *query_response = (rate_limited) ? "QUERY_RATE_LIMITED" : - "QUERY_NO_HSDIR"; - control_event_hsv2_descriptor_failed(rend_query, NULL, query_response); - control_event_hs_descriptor_content(rend_data_get_address(rend_query), - desc_id_base32, NULL, NULL); - return 0; - } - } - - /* Add a copy of the HSDir identity digest to the query so we can track it - * on the control port. */ - hsdir_fp = tor_memdup(hs_dir->identity_digest, - sizeof(hs_dir->identity_digest)); - smartlist_add(rend_query->hsdirs_fp, hsdir_fp); - - /* Encode descriptor cookie for logging purposes. Also, if the cookie is - * malformed, no fetch is triggered thus this needs to be done before the - * fetch request. */ - if (rend_data->auth_type != REND_NO_AUTH) { - if (base64_encode(descriptor_cookie_base64, - sizeof(descriptor_cookie_base64), - rend_data->descriptor_cookie, - REND_DESC_COOKIE_LEN, - 0)<0) { - log_warn(LD_BUG, "Could not base64-encode descriptor cookie."); - control_event_hsv2_descriptor_failed(rend_query, hsdir_fp, "BAD_DESC"); - control_event_hs_descriptor_content(rend_data_get_address(rend_query), - desc_id_base32, hsdir_fp, NULL); - return 0; - } - /* Remove == signs. */ - descriptor_cookie_base64[strlen(descriptor_cookie_base64)-2] = '\0'; - } else { - strlcpy(descriptor_cookie_base64, "(none)", - sizeof(descriptor_cookie_base64)); - } - - /* Send fetch request. (Pass query and possibly descriptor cookie so that - * they can be written to the directory connection and be referred to when - * the response arrives. */ - directory_request_t *req = - directory_request_new(DIR_PURPOSE_FETCH_RENDDESC_V2); - directory_request_set_routerstatus(req, hs_dir); - directory_request_set_indirection(req, how_to_fetch); - directory_request_set_resource(req, desc_id_base32); - directory_request_set_rend_query(req, rend_query); - directory_initiate_request(req); - directory_request_free(req); - - log_info(LD_REND, "Sending fetch request for v2 descriptor for " - "service '%s' with descriptor ID '%s', auth type %d, " - "and descriptor cookie '%s' to hidden service " - "directory %s", - rend_data->onion_address, desc_id_base32, - rend_data->auth_type, - (rend_data->auth_type == REND_NO_AUTH ? "[none]" : - escaped_safe_str_client(descriptor_cookie_base64)), - routerstatus_describe(hs_dir)); - control_event_hs_descriptor_requested(rend_data->onion_address, - rend_data->auth_type, - hs_dir->identity_digest, - desc_id_base32, NULL); - return 1; -} - -/** Remove tracked HSDir requests from our history for this hidden service - * descriptor <b>desc_id</b> (of size DIGEST_LEN) */ -static void -purge_v2_hidserv_req(const char *desc_id) -{ - char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; - - /* The hsdir request tracker stores v2 keys using the base32 encoded - desc_id. Do it: */ - base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id, - DIGEST_LEN); - hs_purge_hid_serv_from_last_hid_serv_requests(desc_id_base32); -} - -/** Fetch a v2 descriptor using the given descriptor id. If any hsdir(s) are - * given, they will be used instead. - * - * On success, 1 is returned. If no hidden service is left to ask, return 0. - * On error, -1 is returned. */ -static int -fetch_v2_desc_by_descid(const char *desc_id, - const rend_data_t *rend_query, smartlist_t *hsdirs) -{ - int ret; - - tor_assert(rend_query); - - if (!hsdirs) { - ret = directory_get_from_hs_dir(desc_id, rend_query, NULL); - goto end; /* either success or failure, but we're done */ - } - - /* Using the given hsdir list, trigger a fetch on each of them. */ - SMARTLIST_FOREACH_BEGIN(hsdirs, routerstatus_t *, hs_dir) { - /* This should always be a success. */ - ret = directory_get_from_hs_dir(desc_id, rend_query, hs_dir); - tor_assert(ret); - } SMARTLIST_FOREACH_END(hs_dir); - - /* Everything went well. */ - ret = 0; - - end: - return ret; -} - -/** Fetch a v2 descriptor using the onion address in the given query object. - * This will compute the descriptor id for each replicas and fetch it on the - * given hsdir(s) if any or the responsible ones that are chosen - * automatically. - * - * On success, 1 is returned. If no hidden service is left to ask, return 0. - * On error, -1 is returned. */ -static int -fetch_v2_desc_by_addr(rend_data_t *rend_query, smartlist_t *hsdirs) -{ - char descriptor_id[DIGEST_LEN]; - int replicas_left_to_try[REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS]; - int i, tries_left, ret; - rend_data_v2_t *rend_data = TO_REND_DATA_V2(rend_query); - - /* Randomly iterate over the replicas until a descriptor can be fetched - * from one of the consecutive nodes, or no options are left. */ - for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) { - replicas_left_to_try[i] = i; - } - - tries_left = REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; - while (tries_left > 0) { - int rand_val = crypto_rand_int(tries_left); - int chosen_replica = replicas_left_to_try[rand_val]; - replicas_left_to_try[rand_val] = replicas_left_to_try[--tries_left]; - - ret = rend_compute_v2_desc_id(descriptor_id, - rend_data->onion_address, - rend_data->auth_type == REND_STEALTH_AUTH ? - rend_data->descriptor_cookie : NULL, - time(NULL), chosen_replica); - if (ret < 0) { - /* Normally, on failure the descriptor_id is untouched but let's be - * safe in general in case the function changes at some point. */ - goto end; - } - - if (tor_memcmp(descriptor_id, rend_data->descriptor_id[chosen_replica], - sizeof(descriptor_id)) != 0) { - /* Not equal from what we currently have so purge the last hid serv - * request cache and update the descriptor ID with the new value. */ - purge_v2_hidserv_req(rend_data->descriptor_id[chosen_replica]); - memcpy(rend_data->descriptor_id[chosen_replica], descriptor_id, - sizeof(rend_data->descriptor_id[chosen_replica])); - } - - /* Trigger the fetch with the computed descriptor ID. */ - ret = fetch_v2_desc_by_descid(descriptor_id, rend_query, hsdirs); - if (ret != 0) { - /* Either on success or failure, as long as we tried a fetch we are - * done here. */ - goto end; - } - } - - /* If we come here, there are no hidden service directories left. */ - log_info(LD_REND, "Could not pick one of the responsible hidden " - "service directories to fetch descriptors, because " - "we already tried them all unsuccessfully."); - ret = 0; - - end: - memwipe(descriptor_id, 0, sizeof(descriptor_id)); - return ret; -} - -/** Fetch a v2 descriptor using the given query. If any hsdir are specified, - * use them for the fetch. - * - * On success, 1 is returned. If no hidden service is left to ask, return 0. - * On error, -1 is returned. */ -int -rend_client_fetch_v2_desc(rend_data_t *query, smartlist_t *hsdirs) -{ - int ret; - rend_data_v2_t *rend_data; - const char *onion_address; - - tor_assert(query); - - /* Get the version 2 data structure of the query. */ - rend_data = TO_REND_DATA_V2(query); - onion_address = rend_data_get_address(query); - - /* Depending on what's available in the rend data query object, we will - * trigger a fetch by HS address or using a descriptor ID. */ - - if (onion_address[0] != '\0') { - ret = fetch_v2_desc_by_addr(query, hsdirs); - } else if (!tor_digest_is_zero(rend_data->desc_id_fetch)) { - ret = fetch_v2_desc_by_descid(rend_data->desc_id_fetch, query, - hsdirs); - } else { - /* Query data is invalid. */ - ret = -1; - goto error; - } - - error: - return ret; -} - -/** Unless we already have a descriptor for <b>rend_query</b> with at least - * one (possibly) working introduction point in it, start a connection to a - * hidden service directory to fetch a v2 rendezvous service descriptor. */ -void -rend_client_refetch_v2_renddesc(rend_data_t *rend_query) -{ - rend_cache_entry_t *e = NULL; - const char *onion_address = rend_data_get_address(rend_query); - - tor_assert(rend_query); - /* Before fetching, check if we already have a usable descriptor here. */ - if (rend_cache_lookup_entry(onion_address, -1, &e) == 0 && - rend_client_any_intro_points_usable(e)) { - log_info(LD_REND, "We would fetch a v2 rendezvous descriptor, but we " - "already have a usable descriptor here. Not fetching."); - return; - } - /* Are we configured to fetch descriptors? */ - if (!get_options()->FetchHidServDescriptors) { - log_warn(LD_REND, "We received an onion address for a v2 rendezvous " - "service descriptor, but are not fetching service descriptors."); - return; - } - log_debug(LD_REND, "Fetching v2 rendezvous descriptor for service %s", - safe_str_client(onion_address)); - - rend_client_fetch_v2_desc(rend_query, NULL); - /* We don't need to look the error code because either on failure or - * success, the necessary steps to continue the HS connection will be - * triggered once the descriptor arrives or if all fetch failed. */ - return; -} - -/** Cancel all rendezvous descriptor fetches currently in progress. - */ -void -rend_client_cancel_descriptor_fetches(void) -{ - smartlist_t *connection_array = get_connection_array(); - - SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) { - if (conn->type == CONN_TYPE_DIR && - conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) { - /* It's a rendezvous descriptor fetch in progress -- cancel it - * by marking the connection for close. - * - * Even if this connection has already reached EOF, this is - * enough to make sure that if the descriptor hasn't been - * processed yet, it won't be. See the end of - * connection_handle_read; connection_reached_eof (indirectly) - * processes whatever response the connection received. */ - - const rend_data_t *rd = (TO_DIR_CONN(conn))->rend_data; - if (!rd) { - log_warn(LD_BUG | LD_REND, - "Marking for close dir conn fetching rendezvous " - "descriptor for unknown service!"); - } else { - log_debug(LD_REND, "Marking for close dir conn fetching " - "rendezvous descriptor for service %s", - safe_str(rend_data_get_address(rd))); - } - connection_mark_for_close(conn); - } - } SMARTLIST_FOREACH_END(conn); -} - -/** Mark <b>failed_intro</b> as a failed introduction point for the - * hidden service specified by <b>rend_query</b>. If the HS now has no - * usable intro points, or we do not have an HS descriptor for it, - * then launch a new renddesc fetch. - * - * If <b>failure_type</b> is INTRO_POINT_FAILURE_GENERIC, remove the - * intro point from (our parsed copy of) the HS descriptor. - * - * If <b>failure_type</b> is INTRO_POINT_FAILURE_TIMEOUT, mark the - * intro point as 'timed out'; it will not be retried until the - * current hidden service connection attempt has ended or it has - * appeared in a newly fetched rendezvous descriptor. - * - * If <b>failure_type</b> is INTRO_POINT_FAILURE_UNREACHABLE, - * increment the intro point's reachability-failure count; if it has - * now failed MAX_INTRO_POINT_REACHABILITY_FAILURES or more times, - * remove the intro point from (our parsed copy of) the HS descriptor. - * - * Return -1 if error, 0 if no usable intro points remain or service - * unrecognized, 1 if recognized and some intro points remain. - */ -int -rend_client_report_intro_point_failure(extend_info_t *failed_intro, - rend_data_t *rend_data, - unsigned int failure_type) -{ - int i, r; - rend_cache_entry_t *ent; - connection_t *conn; - const char *onion_address = rend_data_get_address(rend_data); - - r = rend_cache_lookup_entry(onion_address, -1, &ent); - if (r < 0) { - /* Either invalid onion address or cache entry not found. */ - switch (-r) { - case EINVAL: - log_warn(LD_BUG, "Malformed service ID %s.", - escaped_safe_str_client(onion_address)); - return -1; - case ENOENT: - log_info(LD_REND, "Unknown service %s. Re-fetching descriptor.", - escaped_safe_str_client(onion_address)); - rend_client_refetch_v2_renddesc(rend_data); - return 0; - default: - log_warn(LD_BUG, "Unknown cache lookup returned code: %d", r); - return -1; - } - } - /* The intro points are not checked here if they are usable or not because - * this is called when an intro point circuit is closed thus there must be - * at least one intro point that is usable and is about to be flagged. */ - - for (i = 0; i < smartlist_len(ent->parsed->intro_nodes); i++) { - rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i); - if (tor_memeq(failed_intro->identity_digest, - intro->extend_info->identity_digest, DIGEST_LEN)) { - switch (failure_type) { - default: - log_warn(LD_BUG, "Unknown failure type %u. Removing intro point.", - failure_type); - tor_fragile_assert(); - FALLTHROUGH_UNLESS_ALL_BUGS_ARE_FATAL; - case INTRO_POINT_FAILURE_GENERIC: - rend_cache_intro_failure_note(failure_type, - (uint8_t *)failed_intro->identity_digest, - onion_address); - rend_intro_point_free(intro); - smartlist_del(ent->parsed->intro_nodes, i); - break; - case INTRO_POINT_FAILURE_TIMEOUT: - intro->timed_out = 1; - break; - case INTRO_POINT_FAILURE_UNREACHABLE: - ++(intro->unreachable_count); - { - int zap_intro_point = - intro->unreachable_count >= MAX_INTRO_POINT_REACHABILITY_FAILURES; - log_info(LD_REND, "Failed to reach this intro point %u times.%s", - intro->unreachable_count, - zap_intro_point ? " Removing from descriptor.": ""); - if (zap_intro_point) { - rend_cache_intro_failure_note( - failure_type, - (uint8_t *) failed_intro->identity_digest, onion_address); - rend_intro_point_free(intro); - smartlist_del(ent->parsed->intro_nodes, i); - } - } - break; - } - break; - } - } - - if (! rend_client_any_intro_points_usable(ent)) { - log_info(LD_REND, - "No more intro points remain for %s. Re-fetching descriptor.", - escaped_safe_str_client(onion_address)); - rend_client_refetch_v2_renddesc(rend_data); - - /* move all pending streams back to renddesc_wait */ - /* NOTE: We can now do this faster, if we use pending_entry_connections */ - while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP, - AP_CONN_STATE_CIRCUIT_WAIT, - onion_address))) { - connection_ap_mark_as_waiting_for_renddesc(TO_ENTRY_CONN(conn)); - } - - return 0; - } - log_info(LD_REND,"%d options left for %s.", - smartlist_len(ent->parsed->intro_nodes), - escaped_safe_str_client(onion_address)); - return 1; -} - -/** The service sent us a rendezvous cell; join the circuits. */ -int -rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, - size_t request_len) -{ - if (request_len != DH1024_KEY_LEN+DIGEST_LEN) { - log_warn(LD_PROTOCOL,"Incorrect length (%d) on RENDEZVOUS2 cell.", - (int)request_len); - goto err; - } - - if (hs_circuit_setup_e2e_rend_circ_legacy_client(circ, request) < 0) { - log_warn(LD_GENERAL, "Failed to setup circ"); - goto err; - } - return 0; - - err: - circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); - return -1; -} - -/** Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that are - * waiting on <b>query</b>. If there's a working cache entry here with at - * least one intro point, move them to the next state. */ -void -rend_client_desc_trynow(const char *query) -{ - entry_connection_t *conn; - rend_cache_entry_t *entry; - const rend_data_t *rend_data; - time_t now = time(NULL); - - smartlist_t *conns = get_connection_array(); - SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) { - if (base_conn->type != CONN_TYPE_AP || - base_conn->state != AP_CONN_STATE_RENDDESC_WAIT || - base_conn->marked_for_close) - continue; - conn = TO_ENTRY_CONN(base_conn); - rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data; - if (!rend_data) - continue; - const char *onion_address = rend_data_get_address(rend_data); - if (rend_cmp_service_ids(query, onion_address)) - continue; - assert_connection_ok(base_conn, now); - if (rend_cache_lookup_entry(onion_address, -1, - &entry) == 0 && - rend_client_any_intro_points_usable(entry)) { - /* either this fetch worked, or it failed but there was a - * valid entry from before which we should reuse */ - log_info(LD_REND,"Rend desc is usable. Launching circuits."); - base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; - - /* restart their timeout values, so they get a fair shake at - * connecting to the hidden service. */ - base_conn->timestamp_created = now; - base_conn->timestamp_last_read_allowed = now; - base_conn->timestamp_last_write_allowed = now; - - connection_ap_mark_as_pending_circuit(conn); - } else { /* 404, or fetch didn't get that far */ - log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is " - "unavailable (try again later).", - safe_str_client(query)); - connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED); - rend_client_note_connection_attempt_ended(rend_data); - } - } SMARTLIST_FOREACH_END(base_conn); -} - -/** Clear temporary state used only during an attempt to connect to the - * hidden service with <b>rend_data</b>. Called when a connection attempt - * has ended; it is possible for this to be called multiple times while - * handling an ended connection attempt, and any future changes to this - * function must ensure it remains idempotent. */ -void -rend_client_note_connection_attempt_ended(const rend_data_t *rend_data) -{ - unsigned int have_onion = 0; - rend_cache_entry_t *cache_entry = NULL; - const char *onion_address = rend_data_get_address(rend_data); - rend_data_v2_t *rend_data_v2 = TO_REND_DATA_V2(rend_data); - - if (onion_address[0] != '\0') { - /* Ignore return value; we find an entry, or we don't. */ - (void) rend_cache_lookup_entry(onion_address, -1, &cache_entry); - have_onion = 1; - } - - /* Clear the timed_out flag on all remaining intro points for this HS. */ - if (cache_entry != NULL) { - SMARTLIST_FOREACH(cache_entry->parsed->intro_nodes, - rend_intro_point_t *, ip, - ip->timed_out = 0; ); - } - - /* Remove the HS's entries in last_hid_serv_requests. */ - if (have_onion) { - unsigned int replica; - for (replica = 0; replica < ARRAY_LENGTH(rend_data_v2->descriptor_id); - replica++) { - const char *desc_id = rend_data_v2->descriptor_id[replica]; - purge_v2_hidserv_req(desc_id); - } - log_info(LD_REND, "Connection attempt for %s has ended; " - "cleaning up temporary state.", - safe_str_client(onion_address)); - } else { - /* We only have an ID for a fetch. Probably used by HSFETCH. */ - purge_v2_hidserv_req(rend_data_v2->desc_id_fetch); - } -} - -/** Return a newly allocated extend_info_t* for a randomly chosen introduction - * point for the named hidden service. Return NULL if all introduction points - * have been tried and failed. - */ -extend_info_t * -rend_client_get_random_intro(const rend_data_t *rend_query) -{ - int ret; - extend_info_t *result; - rend_cache_entry_t *entry; - const char *onion_address = rend_data_get_address(rend_query); - - ret = rend_cache_lookup_entry(onion_address, -1, &entry); - if (ret < 0 || !rend_client_any_intro_points_usable(entry)) { - log_warn(LD_REND, - "Query '%s' didn't have valid rend desc in cache. Failing.", - safe_str_client(onion_address)); - /* XXX: Should we refetch the descriptor here if the IPs are not usable - * anymore ?. */ - return NULL; - } - - /* See if we can get a node that complies with ExcludeNodes */ - if ((result = rend_client_get_random_intro_impl(entry, 1, 1))) - return result; - /* If not, and StrictNodes is not set, see if we can return any old node - */ - if (!get_options()->StrictNodes) - return rend_client_get_random_intro_impl(entry, 0, 1); - return NULL; -} - -/** As rend_client_get_random_intro, except assume that StrictNodes is set - * iff <b>strict</b> is true. If <b>warnings</b> is false, don't complain - * to the user when we're out of nodes, even if StrictNodes is true. - */ -static extend_info_t * -rend_client_get_random_intro_impl(const rend_cache_entry_t *entry, - const int strict, - const int warnings) -{ - int i; - - rend_intro_point_t *intro; - const or_options_t *options = get_options(); - smartlist_t *usable_nodes; - int n_excluded = 0; - char service_id[REND_SERVICE_ID_LEN_BASE32 + 1]; - - /* We'll keep a separate list of the usable nodes. If this becomes empty, - * no nodes are usable. */ - usable_nodes = smartlist_new(); - smartlist_add_all(usable_nodes, entry->parsed->intro_nodes); - - /* Get service ID so we can use it to query the failure cache. If we fail to - * parse it, this cache entry is no good. */ - if (BUG(rend_get_service_id(entry->parsed->pk, service_id) < 0)) { - smartlist_free(usable_nodes); - return NULL; - } - - /* Remove the intro points that have timed out during this HS - * connection attempt from our list of usable nodes. */ - SMARTLIST_FOREACH_BEGIN(usable_nodes, const rend_intro_point_t *, ip) { - bool failed_intro = - rend_cache_intro_failure_exists(service_id, - (const uint8_t *) ip->extend_info->identity_digest); - if (ip->timed_out || failed_intro) { - SMARTLIST_DEL_CURRENT(usable_nodes, ip); - }; - } SMARTLIST_FOREACH_END(ip); - - again: - if (smartlist_len(usable_nodes) == 0) { - if (n_excluded && get_options()->StrictNodes && warnings) { - /* We only want to warn if StrictNodes is really set. Otherwise - * we're just about to retry anyways. - */ - log_warn(LD_REND, "All introduction points for hidden service are " - "at excluded relays, and StrictNodes is set. Skipping."); - } - smartlist_free(usable_nodes); - return NULL; - } - - i = crypto_rand_int(smartlist_len(usable_nodes)); - intro = smartlist_get(usable_nodes, i); - if (BUG(!intro->extend_info)) { - /* This should never happen, but it isn't fatal, just try another */ - smartlist_del(usable_nodes, i); - goto again; - } - /* All version 2 HS descriptors come with a TAP onion key. - * Clients used to try to get the TAP onion key from the consensus, but this - * meant that hidden services could discover which consensus clients have. */ - if (!extend_info_supports_tap(intro->extend_info)) { - log_info(LD_REND, "The HS descriptor is missing a TAP onion key for the " - "intro-point relay '%s'; trying another.", - safe_str_client(extend_info_describe(intro->extend_info))); - smartlist_del(usable_nodes, i); - goto again; - } - /* Check if we should refuse to talk to this router. */ - if (strict && - routerset_contains_extendinfo(options->ExcludeNodes, - intro->extend_info)) { - n_excluded++; - smartlist_del(usable_nodes, i); - goto again; - } - - smartlist_free(usable_nodes); - return extend_info_dup(intro->extend_info); -} - -/** Return true iff any introduction points still listed in <b>entry</b> are - * usable. */ -int -rend_client_any_intro_points_usable(const rend_cache_entry_t *entry) -{ - extend_info_t *extend_info = - rend_client_get_random_intro_impl(entry, get_options()->StrictNodes, 0); - - int rv = (extend_info != NULL); - - extend_info_free(extend_info); - return rv; -} - -/** Client-side authorizations for hidden services; map of onion address to - * rend_service_authorization_t*. */ -static strmap_t *auth_hid_servs = NULL; - -/** Look up the client-side authorization for the hidden service with - * <b>onion_address</b>. Return NULL if no authorization is available for - * that address. */ -rend_service_authorization_t* -rend_client_lookup_service_authorization(const char *onion_address) -{ - tor_assert(onion_address); - if (!auth_hid_servs) return NULL; - return strmap_get(auth_hid_servs, onion_address); -} - -#define rend_service_authorization_free(val) \ - FREE_AND_NULL(rend_service_authorization_t, \ - rend_service_authorization_free_, (val)) - -/** Helper: Free storage held by rend_service_authorization_t. */ -static void -rend_service_authorization_free_(rend_service_authorization_t *auth) -{ - tor_free(auth); -} - -/** Helper for strmap_free. */ -static void -rend_service_authorization_free_void(void *service_auth) -{ - rend_service_authorization_free_(service_auth); -} - -/** Release all the storage held in auth_hid_servs. - */ -void -rend_service_authorization_free_all(void) -{ - if (!auth_hid_servs) { - return; - } - strmap_free(auth_hid_servs, rend_service_authorization_free_void); - auth_hid_servs = NULL; -} - -/** Parse <b>config_line</b> as a client-side authorization for a hidden - * service and add it to the local map of hidden service authorizations. - * Return 0 for success and -1 for failure. */ -int -rend_parse_service_authorization(const or_options_t *options, - int validate_only) -{ - config_line_t *line; - int res = -1; - strmap_t *parsed = strmap_new(); - smartlist_t *sl = smartlist_new(); - rend_service_authorization_t *auth = NULL; - char *err_msg = NULL; - - for (line = options->HidServAuth; line; line = line->next) { - char *onion_address, *descriptor_cookie; - auth = NULL; - SMARTLIST_FOREACH(sl, char *, c, tor_free(c);); - smartlist_clear(sl); - smartlist_split_string(sl, line->value, " ", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3); - if (smartlist_len(sl) < 2) { - log_warn(LD_CONFIG, "Configuration line does not consist of " - ""onion-address authorization-cookie [service-name]": " - "'%s'", line->value); - goto err; - } - auth = tor_malloc_zero(sizeof(rend_service_authorization_t)); - /* Parse onion address. */ - onion_address = smartlist_get(sl, 0); - if (strlen(onion_address) != REND_SERVICE_ADDRESS_LEN || - strcmpend(onion_address, ".onion")) { - log_warn(LD_CONFIG, "Onion address has wrong format: '%s'", - onion_address); - goto err; - } - strlcpy(auth->onion_address, onion_address, REND_SERVICE_ID_LEN_BASE32+1); - if (!rend_valid_v2_service_id(auth->onion_address)) { - log_warn(LD_CONFIG, "Onion address has wrong format: '%s'", - onion_address); - goto err; - } - /* Parse descriptor cookie. */ - descriptor_cookie = smartlist_get(sl, 1); - if (rend_auth_decode_cookie(descriptor_cookie, auth->descriptor_cookie, - &auth->auth_type, &err_msg) < 0) { - tor_assert(err_msg); - log_warn(LD_CONFIG, "%s", err_msg); - tor_free(err_msg); - goto err; - } - if (strmap_get(parsed, auth->onion_address)) { - log_warn(LD_CONFIG, "Duplicate authorization for the same hidden " - "service."); - goto err; - } - strmap_set(parsed, auth->onion_address, auth); - auth = NULL; - } - res = 0; - goto done; - err: - res = -1; - done: - rend_service_authorization_free(auth); - SMARTLIST_FOREACH(sl, char *, c, tor_free(c);); - smartlist_free(sl); - if (!validate_only && res == 0) { - rend_service_authorization_free_all(); - auth_hid_servs = parsed; - } else { - strmap_free(parsed, rend_service_authorization_free_void); - } - return res; -} - -/** The given circuit is being freed. Take appropriate action if it is of - * interest to the client subsystem. */ -void -rend_client_circuit_cleanup_on_free(const circuit_t *circ) -{ - int reason, orig_reason; - bool has_timed_out, ip_is_redundant; - const origin_circuit_t *ocirc = NULL; - - tor_assert(circ); - tor_assert(CIRCUIT_IS_ORIGIN(circ)); - - reason = circ->marked_for_close_reason; - orig_reason = circ->marked_for_close_orig_reason; - ocirc = CONST_TO_ORIGIN_CIRCUIT(circ); - tor_assert(ocirc->rend_data); - - has_timed_out = (reason == END_CIRC_REASON_TIMEOUT); - ip_is_redundant = (orig_reason == END_CIRC_REASON_IP_NOW_REDUNDANT); - - switch (circ->purpose) { - case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT: - { - if (ip_is_redundant) { - break; - } - tor_assert(circ->state == CIRCUIT_STATE_OPEN); - tor_assert(ocirc->build_state->chosen_exit); - /* Treat this like getting a nack from it */ - log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s", - safe_str_client(rend_data_get_address(ocirc->rend_data)), - safe_str_client(build_state_get_exit_nickname(ocirc->build_state)), - has_timed_out ? "Recording timeout." : "Removing from descriptor."); - rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit, - ocirc->rend_data, - has_timed_out ? - INTRO_POINT_FAILURE_TIMEOUT : - INTRO_POINT_FAILURE_GENERIC); - break; - } - case CIRCUIT_PURPOSE_C_INTRODUCING: - { - /* Ignore if we were introducing and it timed out, we didn't pick an exit - * point yet (IP) or the reason indicate that it was a redundant IP. */ - if (has_timed_out || !ocirc->build_state->chosen_exit || ip_is_redundant) { - break; - } - log_info(LD_REND, "Failed intro circ %s to %s " - "(building circuit to intro point). " - "Marking intro point as possibly unreachable.", - safe_str_client(rend_data_get_address(ocirc->rend_data)), - safe_str_client(build_state_get_exit_nickname( - ocirc->build_state))); - rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit, - ocirc->rend_data, - INTRO_POINT_FAILURE_UNREACHABLE); - break; - } - default: - break; - } -} diff --git a/src/feature/rend/rendclient.h b/src/feature/rend/rendclient.h deleted file mode 100644 index b7aa212487..0000000000 --- a/src/feature/rend/rendclient.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2001 Matej Pfajfar. - * Copyright (c) 2001-2004, Roger Dingledine. - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2020, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file rendclient.h - * \brief Header file for rendclient.c. - **/ - -#ifndef TOR_RENDCLIENT_H -#define TOR_RENDCLIENT_H - -#include "feature/hs/hs_circuit.h" -#include "feature/rend/rendcache.h" - -void rend_client_purge_state(void); - -void rend_client_introcirc_has_opened(origin_circuit_t *circ); -void rend_client_rendcirc_has_opened(origin_circuit_t *circ); -int rend_client_introduction_acked(origin_circuit_t *circ, - const uint8_t *request, - size_t request_len); -void rend_client_refetch_v2_renddesc(rend_data_t *rend_query); -int rend_client_fetch_v2_desc(rend_data_t *query, smartlist_t *hsdirs); -void rend_client_cancel_descriptor_fetches(void); - -int rend_client_report_intro_point_failure(extend_info_t *failed_intro, - rend_data_t *rend_data, - unsigned int failure_type); - -int rend_client_receive_rendezvous(origin_circuit_t *circ, - const uint8_t *request, - size_t request_len); -void rend_client_desc_trynow(const char *query); - -void rend_client_note_connection_attempt_ended(const rend_data_t *rend_data); - -extend_info_t *rend_client_get_random_intro(const rend_data_t *rend_query); -int rend_client_any_intro_points_usable(const rend_cache_entry_t *entry); - -int rend_client_send_introduction(origin_circuit_t *introcirc, - origin_circuit_t *rendcirc); -int rend_parse_service_authorization(const or_options_t *options, - int validate_only); -rend_service_authorization_t *rend_client_lookup_service_authorization( - const char *onion_address); -void rend_service_authorization_free_all(void); - -void rend_client_circuit_cleanup_on_free(const circuit_t *circ); - -#endif /* !defined(TOR_RENDCLIENT_H) */ - diff --git a/src/feature/rend/rendcommon.c b/src/feature/rend/rendcommon.c index f00dfee68a..275ee52968 100644 --- a/src/feature/rend/rendcommon.c +++ b/src/feature/rend/rendcommon.c @@ -23,7 +23,7 @@ #include "feature/hs/hs_common.h" #include "feature/hs/hs_intropoint.h" #include "feature/nodelist/networkstatus.h" -#include "feature/rend/rendclient.h" +#include "feature/rend/rendcache.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendmid.h" #include "feature/rend/rendparse.h" diff --git a/src/feature/rend/rendservice.c b/src/feature/rend/rendservice.c index add25579b3..2be68eadbe 100644 --- a/src/feature/rend/rendservice.c +++ b/src/feature/rend/rendservice.c @@ -34,7 +34,6 @@ #include "feature/nodelist/node_select.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerset.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendparse.h" #include "feature/rend/rendservice.h" diff --git a/src/test/test_config.c b/src/test/test_config.c index 73c8ca0549..5bca3e04fc 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -41,7 +41,6 @@ #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/nodelist.h" #include "core/or/policies.h" -#include "feature/rend/rendclient.h" #include "feature/rend/rendservice.h" #include "feature/relay/relay_find_addr.h" #include "feature/relay/router.h" diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c index 6a8603cbf8..11840b2c4f 100644 --- a/src/test/test_entryconn.c +++ b/src/test/test_entryconn.c @@ -728,46 +728,6 @@ test_entryconn_rewrite_mapaddress_automap_onion4(void *arg) test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 0, 1); }
-/** Test that rewrite functions can handle v2 addresses */ -static void -test_entryconn_rewrite_onion_v2(void *arg) -{ - int retval; - entry_connection_t *conn = arg; - - (void) arg; - - rend_cache_init(); - - /* Make a SOCKS request */ - conn->socks_request->command = SOCKS_COMMAND_CONNECT; - strlcpy(conn->socks_request->address, - "pqeed46efnwmfuid.onion", - sizeof(conn->socks_request->address)); - - /* Make an onion connection using the SOCKS request */ - conn->entry_cfg.onion_traffic = 1; - ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_SOCKS_WAIT; - tt_assert(!ENTRY_TO_EDGE_CONN(conn)->rend_data); - - /* Handle SOCKS and rewrite! */ - retval = connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); - 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); - /* check that the address got rewritten */ - tt_str_op(conn->socks_request->address, OP_EQ, - "pqeed46efnwmfuid"); - /* check that HS information got attached to the connection */ - tt_assert(ENTRY_TO_EDGE_CONN(conn)->rend_data); - tt_assert(!ENTRY_TO_EDGE_CONN(conn)->hs_ident); - - done: - rend_cache_free_all(); - /* 'conn' is cleaned by handler */ -} - /** Test that rewrite functions can handle v3 onion addresses */ static void test_entryconn_rewrite_onion_v3(void *arg) @@ -830,7 +790,6 @@ struct testcase_t entryconn_tests[] = { REWRITE(rewrite_mapaddress_automap_onion2), REWRITE(rewrite_mapaddress_automap_onion3), REWRITE(rewrite_mapaddress_automap_onion4), - REWRITE(rewrite_onion_v2), REWRITE(rewrite_onion_v3),
END_OF_TESTCASES diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c index 5032a82b9c..916b7e4a04 100644 --- a/src/test/test_hs_common.c +++ b/src/test/test_hs_common.c @@ -787,11 +787,8 @@ test_parse_extended_hostname(void *arg) hostname_type_t type;
char address1[] = "fooaddress.onion"; - char address2[] = "aaaaaaaaaaaaaaaa.onion"; char address3[] = "fooaddress.exit"; char address4[] = "www.torproject.org"; - char address5[] = "foo.abcdefghijklmnop.onion"; - char address6[] = "foo.bar.abcdefghijklmnop.onion"; char address7[] = ".abcdefghijklmnop.onion"; char address8[] = "www.25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion"; @@ -803,24 +800,12 @@ test_parse_extended_hostname(void *arg) tt_assert(!parse_extended_hostname(address1, &type)); tt_int_op(type, OP_EQ, BAD_HOSTNAME);
- tt_assert(parse_extended_hostname(address2, &type)); - tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME); - tt_str_op(address2, OP_EQ, "aaaaaaaaaaaaaaaa"); - tt_assert(parse_extended_hostname(address3, &type)); tt_int_op(type, OP_EQ, EXIT_HOSTNAME);
tt_assert(parse_extended_hostname(address4, &type)); tt_int_op(type, OP_EQ, NORMAL_HOSTNAME);
- tt_assert(parse_extended_hostname(address5, &type)); - tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME); - tt_str_op(address5, OP_EQ, "abcdefghijklmnop"); - - tt_assert(parse_extended_hostname(address6, &type)); - tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME); - tt_str_op(address6, OP_EQ, "abcdefghijklmnop"); - tt_assert(!parse_extended_hostname(address7, &type)); tt_int_op(type, OP_EQ, BAD_HOSTNAME);
diff --git a/src/test/test_options.c b/src/test/test_options.c index 714ee4767f..653b647dfe 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -2389,14 +2389,6 @@ test_options_validate__rend(void *ignored) "Failed to configure rendezvous options. See logs for details."); tor_free(msg);
- free_options_test_data(tdata); - tdata = get_options_test_data("HidServAuth failed\n"); - ret = options_validate(NULL, tdata->opt, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "Failed to configure client authorization for hidden " - "services. See logs for details."); - tor_free(msg); - done: policies_free_all(); teardown_capture_of_logs();
tor-commits@lists.torproject.org