[tor-commits] [tor/master] hs-v2: Remove client support

dgoulet at torproject.org dgoulet at torproject.org
Fri Feb 19 21:22:23 UTC 2021


commit 2444629c86e3368ebd6c9ee1b54aa5a5959fa398
Author: David Goulet <dgoulet at 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 at 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();





More information about the tor-commits mailing list