LCOV - code coverage report
Current view: top level - feature/hs - hs_client.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 605 1057 57.2 %
Date: 2021-11-24 03:28:48 Functions: 49 75 65.3 %

          Line data    Source code
       1             : /* Copyright (c) 2016-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file hs_client.c
       6             :  * \brief Implement next generation hidden service client functionality
       7             :  **/
       8             : 
       9             : #define HS_CLIENT_PRIVATE
      10             : 
      11             : #include "core/or/or.h"
      12             : #include "app/config/config.h"
      13             : #include "core/crypto/hs_ntor.h"
      14             : #include "core/mainloop/connection.h"
      15             : #include "core/or/circuitbuild.h"
      16             : #include "core/or/circuitlist.h"
      17             : #include "core/or/circuituse.h"
      18             : #include "core/or/connection_edge.h"
      19             : #include "core/or/extendinfo.h"
      20             : #include "core/or/reasons.h"
      21             : #include "feature/client/circpathbias.h"
      22             : #include "feature/dirclient/dirclient.h"
      23             : #include "feature/dircommon/directory.h"
      24             : #include "feature/hs/hs_cache.h"
      25             : #include "feature/hs/hs_cell.h"
      26             : #include "feature/hs/hs_circuit.h"
      27             : #include "feature/hs/hs_circuitmap.h"
      28             : #include "feature/hs/hs_client.h"
      29             : #include "feature/hs/hs_control.h"
      30             : #include "feature/hs/hs_descriptor.h"
      31             : #include "feature/hs/hs_ident.h"
      32             : #include "feature/nodelist/describe.h"
      33             : #include "feature/nodelist/microdesc.h"
      34             : #include "feature/nodelist/networkstatus.h"
      35             : #include "feature/nodelist/nodelist.h"
      36             : #include "feature/nodelist/routerset.h"
      37             : #include "lib/crypt_ops/crypto_format.h"
      38             : #include "lib/crypt_ops/crypto_rand.h"
      39             : #include "lib/crypt_ops/crypto_util.h"
      40             : 
      41             : #include "core/or/cpath_build_state_st.h"
      42             : #include "feature/dircommon/dir_connection_st.h"
      43             : #include "core/or/entry_connection_st.h"
      44             : #include "core/or/extend_info_st.h"
      45             : #include "core/or/origin_circuit_st.h"
      46             : #include "core/or/socks_request_st.h"
      47             : 
      48             : /** Client-side authorizations for hidden services; map of service identity
      49             :  * public key to hs_client_service_authorization_t *. */
      50             : static digest256map_t *client_auths = NULL;
      51             : 
      52             : #include "trunnel/hs/cell_introduce1.h"
      53             : 
      54             : /** Return a human-readable string for the client fetch status code. */
      55             : static const char *
      56           1 : fetch_status_to_string(hs_client_fetch_status_t status)
      57             : {
      58           1 :   switch (status) {
      59             :   case HS_CLIENT_FETCH_ERROR:
      60             :     return "Internal error";
      61           0 :   case HS_CLIENT_FETCH_LAUNCHED:
      62           0 :     return "Descriptor fetch launched";
      63           0 :   case HS_CLIENT_FETCH_HAVE_DESC:
      64           0 :     return "Already have descriptor";
      65           0 :   case HS_CLIENT_FETCH_NO_HSDIRS:
      66           0 :     return "No more HSDir available to query";
      67           0 :   case HS_CLIENT_FETCH_NOT_ALLOWED:
      68           0 :     return "Fetching descriptors is not allowed";
      69           0 :   case HS_CLIENT_FETCH_MISSING_INFO:
      70           0 :     return "Missing directory information";
      71           0 :   case HS_CLIENT_FETCH_PENDING:
      72           0 :     return "Pending descriptor fetch";
      73           0 :   default:
      74           0 :     return "(Unknown client fetch status code)";
      75             :   }
      76             : }
      77             : 
      78             : /** Return true iff tor should close the SOCKS request(s) for the descriptor
      79             :  * fetch that ended up with this given status code. */
      80             : static int
      81           1 : fetch_status_should_close_socks(hs_client_fetch_status_t status)
      82             : {
      83           1 :   switch (status) {
      84           1 :   case HS_CLIENT_FETCH_NO_HSDIRS:
      85             :     /* No more HSDir to query, we can't complete the SOCKS request(s). */
      86             :   case HS_CLIENT_FETCH_ERROR:
      87             :     /* The fetch triggered an internal error. */
      88             :   case HS_CLIENT_FETCH_NOT_ALLOWED:
      89             :     /* Client is not allowed to fetch (FetchHidServDescriptors 0). */
      90           1 :     goto close;
      91           0 :   case HS_CLIENT_FETCH_MISSING_INFO:
      92             :   case HS_CLIENT_FETCH_HAVE_DESC:
      93             :   case HS_CLIENT_FETCH_PENDING:
      94             :   case HS_CLIENT_FETCH_LAUNCHED:
      95             :     /* The rest doesn't require tor to close the SOCKS request(s). */
      96           0 :     goto no_close;
      97             :   }
      98             : 
      99           1 :  no_close:
     100             :   return 0;
     101           1 :  close:
     102           1 :   return 1;
     103             : }
     104             : 
     105             : /* Return a newly allocated list of all the entry connections that matches the
     106             :  * given service identity pk. If service_identity_pk is NULL, all entry
     107             :  * connections with an hs_ident are returned.
     108             :  *
     109             :  * Caller must free the returned list but does NOT have ownership of the
     110             :  * object inside thus they have to remain untouched. */
     111             : static smartlist_t *
     112       45182 : find_entry_conns(const ed25519_public_key_t *service_identity_pk)
     113             : {
     114       45182 :   time_t now = time(NULL);
     115       45182 :   smartlist_t *conns = NULL, *entry_conns = NULL;
     116             : 
     117       45182 :   entry_conns = smartlist_new();
     118             : 
     119       45182 :   conns = connection_list_by_type_state(CONN_TYPE_AP,
     120             :                                         AP_CONN_STATE_RENDDESC_WAIT);
     121       45189 :   SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
     122           7 :     entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn);
     123           7 :     const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
     124             : 
     125             :     /* Only consider the entry connections that matches the service for which
     126             :      * we just fetched its descriptor. */
     127           7 :     if (!edge_conn->hs_ident ||
     128           7 :         (service_identity_pk &&
     129           7 :          !ed25519_pubkey_eq(service_identity_pk,
     130           7 :                             &edge_conn->hs_ident->identity_pk))) {
     131           0 :       continue;
     132             :     }
     133           7 :     assert_connection_ok(base_conn, now);
     134             : 
     135             :     /* Validated! Add the entry connection to the list. */
     136           7 :     smartlist_add(entry_conns, entry_conn);
     137           7 :   } SMARTLIST_FOREACH_END(base_conn);
     138             : 
     139             :   /* We don't have ownership of the objects in this list. */
     140       45182 :   smartlist_free(conns);
     141       45182 :   return entry_conns;
     142             : }
     143             : 
     144             : /* Cancel all descriptor fetches currently in progress. */
     145             : static void
     146           0 : cancel_descriptor_fetches(void)
     147             : {
     148           0 :   smartlist_t *conns =
     149           0 :     connection_list_by_type_purpose(CONN_TYPE_DIR, DIR_PURPOSE_FETCH_HSDESC);
     150           0 :   SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
     151           0 :     const hs_ident_dir_conn_t *ident = TO_DIR_CONN(conn)->hs_ident;
     152           0 :     if (BUG(ident == NULL)) {
     153             :       /* A directory connection fetching a service descriptor can't have an
     154             :        * empty hidden service identifier. */
     155           0 :       continue;
     156             :     }
     157           0 :     log_debug(LD_REND, "Marking for close a directory connection fetching "
     158             :                        "a hidden service descriptor for service %s.",
     159             :               safe_str_client(ed25519_fmt(&ident->identity_pk)));
     160           0 :     connection_mark_for_close(conn);
     161           0 :   } SMARTLIST_FOREACH_END(conn);
     162             : 
     163             :   /* No ownership of the objects in this list. */
     164           0 :   smartlist_free(conns);
     165           0 :   log_info(LD_REND, "Hidden service client descriptor fetches cancelled.");
     166           0 : }
     167             : 
     168             : /** Get all connections that are waiting on a circuit and flag them back to
     169             :  * waiting for a hidden service descriptor for the given service key
     170             :  * service_identity_pk. */
     171             : static void
     172           0 : flag_all_conn_wait_desc(const ed25519_public_key_t *service_identity_pk)
     173             : {
     174           0 :   tor_assert(service_identity_pk);
     175             : 
     176           0 :   smartlist_t *conns =
     177           0 :     connection_list_by_type_state(CONN_TYPE_AP, AP_CONN_STATE_CIRCUIT_WAIT);
     178             : 
     179           0 :   SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
     180           0 :     edge_connection_t *edge_conn;
     181           0 :     if (BUG(!CONN_IS_EDGE(conn))) {
     182           0 :       continue;
     183             :     }
     184           0 :     edge_conn = TO_EDGE_CONN(conn);
     185           0 :     if (edge_conn->hs_ident &&
     186           0 :         ed25519_pubkey_eq(&edge_conn->hs_ident->identity_pk,
     187             :                           service_identity_pk)) {
     188           0 :       connection_ap_mark_as_waiting_for_renddesc(TO_ENTRY_CONN(conn));
     189             :     }
     190           0 :   } SMARTLIST_FOREACH_END(conn);
     191             : 
     192           0 :   smartlist_free(conns);
     193           0 : }
     194             : 
     195             : /** Remove tracked HSDir requests from our history for this hidden service
     196             :  * identity public key. */
     197             : static void
     198           6 : purge_hid_serv_request(const ed25519_public_key_t *identity_pk)
     199             : {
     200           6 :   char base64_blinded_pk[ED25519_BASE64_LEN + 1];
     201           6 :   ed25519_public_key_t blinded_pk;
     202             : 
     203           6 :   tor_assert(identity_pk);
     204             : 
     205             :   /* Get blinded pubkey of hidden service. It is possible that we just moved
     206             :    * to a new time period meaning that we won't be able to purge the request
     207             :    * from the previous time period. That is fine because they will expire at
     208             :    * some point and we don't care about those anymore. */
     209           6 :   hs_build_blinded_pubkey(identity_pk, NULL, 0,
     210             :                           hs_get_time_period_num(0), &blinded_pk);
     211           6 :   ed25519_public_to_base64(base64_blinded_pk, &blinded_pk);
     212             :   /* Purge last hidden service request from cache for this blinded key. */
     213           6 :   hs_purge_hid_serv_from_last_hid_serv_requests(base64_blinded_pk);
     214           6 : }
     215             : 
     216             : /** Return true iff there is at least one pending directory descriptor request
     217             :  * for the service identity_pk. */
     218             : static int
     219           2 : directory_request_is_pending(const ed25519_public_key_t *identity_pk)
     220             : {
     221           2 :   int ret = 0;
     222           4 :   smartlist_t *conns =
     223           2 :     connection_list_by_type_purpose(CONN_TYPE_DIR, DIR_PURPOSE_FETCH_HSDESC);
     224             : 
     225           2 :   SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
     226           1 :     const hs_ident_dir_conn_t *ident = TO_DIR_CONN(conn)->hs_ident;
     227           1 :     if (BUG(ident == NULL)) {
     228             :       /* A directory connection fetching a service descriptor can't have an
     229             :        * empty hidden service identifier. */
     230           0 :       continue;
     231             :     }
     232           1 :     if (!ed25519_pubkey_eq(identity_pk, &ident->identity_pk)) {
     233           0 :       continue;
     234             :     }
     235             :     ret = 1;
     236             :     break;
     237           0 :   } SMARTLIST_FOREACH_END(conn);
     238             : 
     239             :   /* No ownership of the objects in this list. */
     240           2 :   smartlist_free(conns);
     241           2 :   return ret;
     242             : }
     243             : 
     244             : /** Helper function that changes the state of an entry connection to waiting
     245             :  * for a circuit. For this to work properly, the connection timestamps are set
     246             :  * to now and the connection is then marked as pending for a circuit. */
     247             : static void
     248           0 : mark_conn_as_waiting_for_circuit(connection_t *conn, time_t now)
     249             : {
     250           0 :   tor_assert(conn);
     251             : 
     252             :   /* Because the connection can now proceed to opening circuit and ultimately
     253             :    * connect to the service, reset those timestamp so the connection is
     254             :    * considered "fresh" and can continue without being closed too early. */
     255           0 :   conn->timestamp_created = now;
     256           0 :   conn->timestamp_last_read_allowed = now;
     257           0 :   conn->timestamp_last_write_allowed = now;
     258             :   /* Change connection's state into waiting for a circuit. */
     259           0 :   conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
     260             : 
     261           0 :   connection_ap_mark_as_pending_circuit(TO_ENTRY_CONN(conn));
     262           0 : }
     263             : 
     264             : /** We failed to fetch a descriptor for the service with <b>identity_pk</b>
     265             :  * because of <b>status</b>. Find all pending SOCKS connections for this
     266             :  * service that are waiting on the descriptor and close them with
     267             :  * <b>reason</b>. */
     268             : static void
     269           1 : close_all_socks_conns_waiting_for_desc(const ed25519_public_key_t *identity_pk,
     270             :                                        hs_client_fetch_status_t status,
     271             :                                        int reason)
     272             : {
     273           1 :   unsigned int count = 0;
     274           1 :   smartlist_t *entry_conns = find_entry_conns(identity_pk);
     275             : 
     276           2 :   SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
     277             :     /* Unattach the entry connection which will close for the reason. */
     278           1 :     connection_mark_unattached_ap(entry_conn, reason);
     279           1 :     count++;
     280           1 :   } SMARTLIST_FOREACH_END(entry_conn);
     281             : 
     282           1 :   if (count > 0) {
     283           1 :     char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
     284           1 :     hs_build_address(identity_pk, HS_VERSION_THREE, onion_address);
     285           1 :     log_notice(LD_REND, "Closed %u streams for service %s.onion "
     286             :                         "for reason %s. Fetch status: %s.",
     287             :                count, safe_str_client(onion_address),
     288             :                stream_end_reason_to_string(reason),
     289             :                fetch_status_to_string(status));
     290             :   }
     291             : 
     292             :   /* No ownership of the object(s) in this list. */
     293           1 :   smartlist_free(entry_conns);
     294           1 : }
     295             : 
     296             : /** Find all pending SOCKS connection waiting for a descriptor and retry them
     297             :  * all. This is called when the directory information changed. */
     298             : STATIC void
     299       45175 : retry_all_socks_conn_waiting_for_desc(void)
     300             : {
     301       45175 :   smartlist_t *entry_conns = find_entry_conns(NULL);
     302             : 
     303       45175 :   SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
     304           0 :     hs_client_fetch_status_t status;
     305           0 :     edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
     306           0 :     connection_t *base_conn = &edge_conn->base_;
     307             : 
     308             :     /* Ignore non HS or non v3 connection. */
     309           0 :     if (edge_conn->hs_ident == NULL) {
     310           0 :       continue;
     311             :     }
     312             : 
     313             :     /* In this loop, we will possibly try to fetch a descriptor for the
     314             :      * pending connections because we just got more directory information.
     315             :      * However, the refetch process can cleanup all SOCKS request to the same
     316             :      * service if an internal error happens. Thus, we can end up with closed
     317             :      * connections in our list. */
     318           0 :     if (base_conn->marked_for_close) {
     319           0 :       continue;
     320             :     }
     321             : 
     322             :     /* XXX: There is an optimization we could do which is that for a service
     323             :      * key, we could check if we can fetch and remember that decision. */
     324             : 
     325             :     /* Order a refetch in case it works this time. */
     326           0 :     status = hs_client_refetch_hsdesc(&edge_conn->hs_ident->identity_pk);
     327           0 :     if (status == HS_CLIENT_FETCH_HAVE_DESC) {
     328             :       /* This is a rare case where a SOCKS connection is in state waiting for
     329             :        * a descriptor but we do have it in the cache.
     330             :        *
     331             :        * This can happen is tor comes back from suspend where it previously
     332             :        * had the descriptor but the intro points were not usable. Once it
     333             :        * came back to life, the intro point failure cache was cleaned up and
     334             :        * thus the descriptor became usable again leaving us in this code path.
     335             :        *
     336             :        * We'll mark the connection as waiting for a circuit so the descriptor
     337             :        * can be retried. This is safe because a connection in state waiting
     338             :        * for a descriptor can not be in the entry connection pending list. */
     339           0 :       mark_conn_as_waiting_for_circuit(base_conn, approx_time());
     340           0 :       continue;
     341             :     }
     342             :     /* In the case of an error, either all SOCKS connections have been
     343             :      * closed or we are still missing directory information. Leave the
     344             :      * connection in renddesc wait state so when we get more info, we'll be
     345             :      * able to try it again. */
     346           0 :   } SMARTLIST_FOREACH_END(entry_conn);
     347             : 
     348             :   /* We don't have ownership of those objects. */
     349       45175 :   smartlist_free(entry_conns);
     350       45175 : }
     351             : 
     352             : /** A v3 HS circuit successfully connected to the hidden service. Update the
     353             :  * stream state at <b>hs_conn_ident</b> appropriately. */
     354             : static void
     355           5 : note_connection_attempt_succeeded(const hs_ident_edge_conn_t *hs_conn_ident)
     356             : {
     357           5 :   tor_assert(hs_conn_ident);
     358             : 
     359             :   /* Remove from the hid serv cache all requests for that service so we can
     360             :    * query the HSDir again later on for various reasons. */
     361           5 :   purge_hid_serv_request(&hs_conn_ident->identity_pk);
     362           5 : }
     363             : 
     364             : /** Given the pubkey of a hidden service in <b>onion_identity_pk</b>, fetch its
     365             :  * descriptor by launching a dir connection to <b>hsdir</b>. Return a
     366             :  * hs_client_fetch_status_t status code depending on how it went. */
     367             : static hs_client_fetch_status_t
     368           0 : directory_launch_v3_desc_fetch(const ed25519_public_key_t *onion_identity_pk,
     369             :                                const routerstatus_t *hsdir)
     370             : {
     371           0 :   uint64_t current_time_period = hs_get_time_period_num(0);
     372           0 :   ed25519_public_key_t blinded_pubkey;
     373           0 :   char base64_blinded_pubkey[ED25519_BASE64_LEN + 1];
     374           0 :   hs_ident_dir_conn_t hs_conn_dir_ident;
     375             : 
     376           0 :   tor_assert(hsdir);
     377           0 :   tor_assert(onion_identity_pk);
     378             : 
     379             :   /* Get blinded pubkey */
     380           0 :   hs_build_blinded_pubkey(onion_identity_pk, NULL, 0,
     381             :                           current_time_period, &blinded_pubkey);
     382             :   /* ...and base64 it. */
     383           0 :   ed25519_public_to_base64(base64_blinded_pubkey, &blinded_pubkey);
     384             : 
     385             :   /* Copy onion pk to a dir_ident so that we attach it to the dir conn */
     386           0 :   hs_ident_dir_conn_init(onion_identity_pk, &blinded_pubkey,
     387             :                          &hs_conn_dir_ident);
     388             : 
     389             :   /* Setup directory request */
     390           0 :   directory_request_t *req =
     391           0 :     directory_request_new(DIR_PURPOSE_FETCH_HSDESC);
     392           0 :   directory_request_set_routerstatus(req, hsdir);
     393           0 :   directory_request_set_indirection(req, DIRIND_ANONYMOUS);
     394           0 :   directory_request_set_resource(req, base64_blinded_pubkey);
     395           0 :   directory_request_fetch_set_hs_ident(req, &hs_conn_dir_ident);
     396           0 :   directory_initiate_request(req);
     397           0 :   directory_request_free(req);
     398             : 
     399           0 :   log_info(LD_REND, "Descriptor fetch request for service %s with blinded "
     400             :                     "key %s to directory %s",
     401             :            safe_str_client(ed25519_fmt(onion_identity_pk)),
     402             :            safe_str_client(base64_blinded_pubkey),
     403             :            safe_str_client(routerstatus_describe(hsdir)));
     404             : 
     405             :   /* Fire a REQUESTED event on the control port. */
     406           0 :   hs_control_desc_event_requested(onion_identity_pk, base64_blinded_pubkey,
     407             :                                   hsdir);
     408             : 
     409             :   /* Cleanup memory. */
     410           0 :   memwipe(&blinded_pubkey, 0, sizeof(blinded_pubkey));
     411           0 :   memwipe(base64_blinded_pubkey, 0, sizeof(base64_blinded_pubkey));
     412           0 :   memwipe(&hs_conn_dir_ident, 0, sizeof(hs_conn_dir_ident));
     413             : 
     414           0 :   return HS_CLIENT_FETCH_LAUNCHED;
     415             : }
     416             : 
     417             : /** Return the HSDir we should use to fetch the descriptor of the hidden
     418             :  *  service with identity key <b>onion_identity_pk</b>. */
     419             : STATIC routerstatus_t *
     420          42 : pick_hsdir_v3(const ed25519_public_key_t *onion_identity_pk)
     421             : {
     422          42 :   char base64_blinded_pubkey[ED25519_BASE64_LEN + 1];
     423          42 :   uint64_t current_time_period = hs_get_time_period_num(0);
     424          42 :   smartlist_t *responsible_hsdirs = NULL;
     425          42 :   ed25519_public_key_t blinded_pubkey;
     426          42 :   routerstatus_t *hsdir_rs = NULL;
     427             : 
     428          42 :   tor_assert(onion_identity_pk);
     429             : 
     430             :   /* Get blinded pubkey of hidden service */
     431          42 :   hs_build_blinded_pubkey(onion_identity_pk, NULL, 0,
     432             :                           current_time_period, &blinded_pubkey);
     433             :   /* ...and base64 it. */
     434          42 :   ed25519_public_to_base64(base64_blinded_pubkey, &blinded_pubkey);
     435             : 
     436             :   /* Get responsible hsdirs of service for this time period */
     437          42 :   responsible_hsdirs = smartlist_new();
     438             : 
     439          42 :   hs_get_responsible_hsdirs(&blinded_pubkey, current_time_period,
     440             :                             0, 1, responsible_hsdirs);
     441             : 
     442          42 :   log_debug(LD_REND, "Found %d responsible HSDirs and about to pick one.",
     443             :            smartlist_len(responsible_hsdirs));
     444             : 
     445             :   /* Pick an HSDir from the responsible ones. The ownership of
     446             :    * responsible_hsdirs is given to this function so no need to free it. */
     447          42 :   hsdir_rs = hs_pick_hsdir(responsible_hsdirs, base64_blinded_pubkey, NULL);
     448             : 
     449          42 :   return hsdir_rs;
     450             : }
     451             : 
     452             : /** Fetch a v3 descriptor using the given <b>onion_identity_pk</b>.
     453             :  *
     454             :  * On success, HS_CLIENT_FETCH_LAUNCHED is returned. Otherwise, an error from
     455             :  * hs_client_fetch_status_t is returned. */
     456           0 : MOCK_IMPL(STATIC hs_client_fetch_status_t,
     457             : fetch_v3_desc, (const ed25519_public_key_t *onion_identity_pk))
     458             : {
     459           0 :   routerstatus_t *hsdir_rs =NULL;
     460             : 
     461           0 :   tor_assert(onion_identity_pk);
     462             : 
     463           0 :   hsdir_rs = pick_hsdir_v3(onion_identity_pk);
     464           0 :   if (!hsdir_rs) {
     465           0 :     log_info(LD_REND, "Couldn't pick a v3 hsdir.");
     466           0 :     return HS_CLIENT_FETCH_NO_HSDIRS;
     467             :   }
     468             : 
     469           0 :   return directory_launch_v3_desc_fetch(onion_identity_pk, hsdir_rs);
     470             : }
     471             : 
     472             : /** With a given <b>onion_identity_pk</b>, fetch its descriptor. If
     473             :  * <b>hsdirs</b> is specified, use the directory servers specified in the list.
     474             :  * Else, use a random server. */
     475             : void
     476           0 : hs_client_launch_v3_desc_fetch(const ed25519_public_key_t *onion_identity_pk,
     477             :                                const smartlist_t *hsdirs)
     478             : {
     479           0 :   tor_assert(onion_identity_pk);
     480             : 
     481           0 :   if (hsdirs != NULL) {
     482           0 :     SMARTLIST_FOREACH_BEGIN(hsdirs, const routerstatus_t *, hsdir) {
     483           0 :       directory_launch_v3_desc_fetch(onion_identity_pk, hsdir);
     484           0 :     } SMARTLIST_FOREACH_END(hsdir);
     485             :   } else {
     486           0 :     fetch_v3_desc(onion_identity_pk);
     487             :   }
     488           0 : }
     489             : 
     490             : /** Make sure that the given v3 origin circuit circ is a valid correct
     491             :  * introduction circuit. This will BUG() on any problems and hard assert if
     492             :  * the anonymity of the circuit is not ok. Return 0 on success else -1 where
     493             :  * the circuit should be mark for closed immediately. */
     494             : static int
     495           0 : intro_circ_is_ok(const origin_circuit_t *circ)
     496             : {
     497           0 :   int ret = 0;
     498             : 
     499           0 :   tor_assert(circ);
     500             : 
     501           0 :   if (BUG(TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_INTRODUCING &&
     502             :           TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT &&
     503             :           TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACKED)) {
     504             :     ret = -1;
     505             :   }
     506           0 :   if (BUG(circ->hs_ident == NULL)) {
     507             :     ret = -1;
     508             :   }
     509           0 :   if (BUG(!hs_ident_intro_circ_is_valid(circ->hs_ident))) {
     510             :     ret = -1;
     511             :   }
     512             : 
     513             :   /* This can stop the tor daemon but we want that since if we don't have
     514             :    * anonymity on this circuit, something went really wrong. */
     515           0 :   assert_circ_anonymity_ok(circ, get_options());
     516           0 :   return ret;
     517             : }
     518             : 
     519             : /** Find a descriptor intro point object that matches the given ident in the
     520             :  * given descriptor desc. Return NULL if not found. */
     521             : static const hs_desc_intro_point_t *
     522           2 : find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident,
     523             :                                const hs_descriptor_t *desc)
     524             : {
     525           2 :   const hs_desc_intro_point_t *intro_point = NULL;
     526             : 
     527           2 :   tor_assert(ident);
     528           2 :   tor_assert(desc);
     529             : 
     530           2 :   SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points,
     531             :                           const hs_desc_intro_point_t *, ip) {
     532           2 :     if (ed25519_pubkey_eq(&ident->intro_auth_pk,
     533           2 :                           &ip->auth_key_cert->signed_key)) {
     534             :       intro_point = ip;
     535             :       break;
     536             :     }
     537           0 :   } SMARTLIST_FOREACH_END(ip);
     538             : 
     539           2 :   return intro_point;
     540             : }
     541             : 
     542             : /** Find a descriptor intro point object from the descriptor object desc that
     543             :  * matches the given legacy identity digest in legacy_id. Return NULL if not
     544             :  * found. */
     545             : static hs_desc_intro_point_t *
     546           0 : find_desc_intro_point_by_legacy_id(const char *legacy_id,
     547             :                                    const hs_descriptor_t *desc)
     548             : {
     549           0 :   hs_desc_intro_point_t *ret_ip = NULL;
     550             : 
     551           0 :   tor_assert(legacy_id);
     552           0 :   tor_assert(desc);
     553             : 
     554             :   /* We will go over every intro point and try to find which one is linked to
     555             :    * that circuit. Those lists are small so it's not that expensive. */
     556           0 :   SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points,
     557             :                           hs_desc_intro_point_t *, ip) {
     558           0 :     SMARTLIST_FOREACH_BEGIN(ip->link_specifiers,
     559             :                             const link_specifier_t *, lspec) {
     560             :       /* Not all tor node have an ed25519 identity key so we still rely on the
     561             :        * legacy identity digest. */
     562           0 :       if (link_specifier_get_ls_type(lspec) != LS_LEGACY_ID) {
     563           0 :         continue;
     564             :       }
     565           0 :       if (fast_memneq(legacy_id,
     566             :                       link_specifier_getconstarray_un_legacy_id(lspec),
     567             :                       DIGEST_LEN)) {
     568             :         break;
     569             :       }
     570             :       /* Found it. */
     571           0 :       ret_ip = ip;
     572           0 :       goto end;
     573           0 :     } SMARTLIST_FOREACH_END(lspec);
     574           0 :   } SMARTLIST_FOREACH_END(ip);
     575             : 
     576           0 :  end:
     577           0 :   return ret_ip;
     578             : }
     579             : 
     580             : /** Send an INTRODUCE1 cell along the intro circuit and populate the rend
     581             :  * circuit identifier with the needed key material for the e2e encryption.
     582             :  * Return 0 on success, -1 if there is a transient error such that an action
     583             :  * has been taken to recover and -2 if there is a permanent error indicating
     584             :  * that both circuits were closed. */
     585             : static int
     586           0 : send_introduce1(origin_circuit_t *intro_circ,
     587             :                 origin_circuit_t *rend_circ)
     588             : {
     589           0 :   int status;
     590           0 :   char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
     591           0 :   const ed25519_public_key_t *service_identity_pk = NULL;
     592           0 :   const hs_desc_intro_point_t *ip;
     593             : 
     594           0 :   tor_assert(rend_circ);
     595           0 :   if (intro_circ_is_ok(intro_circ) < 0) {
     596           0 :     goto perm_err;
     597             :   }
     598             : 
     599           0 :   service_identity_pk = &intro_circ->hs_ident->identity_pk;
     600             :   /* For logging purposes. There will be a time where the hs_ident will have a
     601             :    * version number but for now there is none because it's all v3. */
     602           0 :   hs_build_address(service_identity_pk, HS_VERSION_THREE, onion_address);
     603             : 
     604           0 :   log_info(LD_REND, "Sending INTRODUCE1 cell to service %s on circuit %u",
     605             :            safe_str_client(onion_address), TO_CIRCUIT(intro_circ)->n_circ_id);
     606             : 
     607             :   /* 1) Get descriptor from our cache. */
     608           0 :   const hs_descriptor_t *desc =
     609           0 :     hs_cache_lookup_as_client(service_identity_pk);
     610           0 :   if (desc == NULL || !hs_client_any_intro_points_usable(service_identity_pk,
     611             :                                                          desc)) {
     612           0 :     log_info(LD_REND, "Request to %s %s. Trying to fetch a new descriptor.",
     613             :              safe_str_client(onion_address),
     614             :              (desc) ? "didn't have usable intro points" :
     615             :              "didn't have a descriptor");
     616           0 :     hs_client_refetch_hsdesc(service_identity_pk);
     617             :     /* We just triggered a refetch, make sure every connections are back
     618             :      * waiting for that descriptor. */
     619           0 :     flag_all_conn_wait_desc(service_identity_pk);
     620             :     /* We just asked for a refetch so this is a transient error. */
     621           0 :     goto tran_err;
     622             :   }
     623             : 
     624             :   /* We need to find which intro point in the descriptor we are connected to
     625             :    * on intro_circ. */
     626           0 :   ip = find_desc_intro_point_by_ident(intro_circ->hs_ident, desc);
     627           0 :   if (ip == NULL) {
     628             :     /* The following is possible if the descriptor was changed while we had
     629             :      * this introduction circuit open and waiting for the rendezvous circuit to
     630             :      * be ready. Which results in this situation where we can't find the
     631             :      * corresponding intro point within the descriptor of the service. */
     632           0 :     log_info(LD_REND, "Unable to find introduction point for service %s "
     633             :                       "while trying to send an INTRODUCE1 cell.",
     634             :              safe_str_client(onion_address));
     635           0 :     goto perm_err;
     636             :   }
     637             : 
     638             :   /* Send the INTRODUCE1 cell. */
     639           0 :   if (hs_circ_send_introduce1(intro_circ, rend_circ, ip,
     640           0 :                               &desc->subcredential) < 0) {
     641           0 :     if (TO_CIRCUIT(intro_circ)->marked_for_close) {
     642             :       /* If the introduction circuit was closed, we were unable to send the
     643             :        * cell for some reasons. In any case, the intro circuit has to be
     644             :        * closed by the above function. We'll return a transient error so tor
     645             :        * can recover and pick a new intro point. To avoid picking that same
     646             :        * intro point, we'll note down the intro point failure so it doesn't
     647             :        * get reused. */
     648           0 :       hs_cache_client_intro_state_note(service_identity_pk,
     649           0 :                                        &intro_circ->hs_ident->intro_auth_pk,
     650             :                                        INTRO_POINT_FAILURE_GENERIC);
     651             :     }
     652             :     /* It is also possible that the rendezvous circuit was closed due to being
     653             :      * unable to use the rendezvous point node_t so in that case, we also want
     654             :      * to recover and let tor pick a new one. */
     655           0 :     goto tran_err;
     656             :   }
     657             : 
     658             :   /* Cell has been sent successfully. Copy the introduction point
     659             :    * authentication and encryption key in the rendezvous circuit identifier so
     660             :    * we can compute the ntor keys when we receive the RENDEZVOUS2 cell. */
     661           0 :   memcpy(&rend_circ->hs_ident->intro_enc_pk, &ip->enc_key,
     662             :          sizeof(rend_circ->hs_ident->intro_enc_pk));
     663           0 :   ed25519_pubkey_copy(&rend_circ->hs_ident->intro_auth_pk,
     664           0 :                       &intro_circ->hs_ident->intro_auth_pk);
     665             : 
     666             :   /* Now, we wait for an ACK or NAK on this circuit. */
     667           0 :   circuit_change_purpose(TO_CIRCUIT(intro_circ),
     668             :                          CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT);
     669             :   /* Set timestamp_dirty, because circuit_expire_building expects it to
     670             :    * specify when a circuit entered the _C_INTRODUCE_ACK_WAIT state. */
     671           0 :   TO_CIRCUIT(intro_circ)->timestamp_dirty = time(NULL);
     672           0 :   pathbias_count_use_attempt(intro_circ);
     673             : 
     674             :   /* Success. */
     675           0 :   status = 0;
     676           0 :   goto end;
     677             : 
     678           0 :  perm_err:
     679             :   /* Permanent error: it is possible that the intro circuit was closed prior
     680             :    * because we weren't able to send the cell. Make sure we don't double close
     681             :    * it which would result in a warning. */
     682           0 :   if (!TO_CIRCUIT(intro_circ)->marked_for_close) {
     683           0 :     circuit_mark_for_close(TO_CIRCUIT(intro_circ), END_CIRC_REASON_INTERNAL);
     684             :   }
     685           0 :   circuit_mark_for_close(TO_CIRCUIT(rend_circ), END_CIRC_REASON_INTERNAL);
     686           0 :   status = -2;
     687           0 :   goto end;
     688             : 
     689             :  tran_err:
     690             :   status = -1;
     691             : 
     692           0 :  end:
     693           0 :   memwipe(onion_address, 0, sizeof(onion_address));
     694           0 :   return status;
     695             : }
     696             : 
     697             : /** Using the introduction circuit circ, setup the authentication key of the
     698             :  * intro point this circuit has extended to.
     699             :  *
     700             :  * Return 0 if everything went well, otherwise return -1 in the case of errors.
     701             :  */
     702             : static int
     703           0 : setup_intro_circ_auth_key(origin_circuit_t *circ)
     704             : {
     705           0 :   const hs_descriptor_t *desc;
     706           0 :   const hs_desc_intro_point_t *ip;
     707             : 
     708           0 :   tor_assert(circ);
     709             : 
     710           0 :   desc = hs_cache_lookup_as_client(&circ->hs_ident->identity_pk);
     711           0 :   if (desc == NULL) {
     712             :     /* There is a very small race window between the opening of this circuit
     713             :      * and the client descriptor cache that gets purged (NEWNYM) or the
     714             :      * cleaned up because it expired. Mark the circuit for close so a new
     715             :      * descriptor fetch can occur. */
     716           0 :     goto err;
     717             :   }
     718             : 
     719             :   /* We will go over every intro point and try to find which one is linked to
     720             :    * that circuit. Those lists are small so it's not that expensive. */
     721           0 :   ip = find_desc_intro_point_by_legacy_id(
     722           0 :                        circ->build_state->chosen_exit->identity_digest, desc);
     723           0 :   if (!ip) {
     724             :     /* Reaching this point means we didn't find any intro point for this
     725             :      * circuit which is not supposed to happen. */
     726           0 :     log_info(LD_REND,"Could not match opened intro circuit with intro point.");
     727           0 :     goto err;
     728             :   }
     729             : 
     730             :   /* We got it, copy its authentication key to the identifier. */
     731           0 :   ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
     732           0 :                       &ip->auth_key_cert->signed_key);
     733           0 :   return 0;
     734             : 
     735           0 :  err:
     736           0 :   circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
     737           0 :   return -1;
     738             : }
     739             : 
     740             : /** Called when an introduction circuit has opened. */
     741             : static void
     742           0 : client_intro_circ_has_opened(origin_circuit_t *circ)
     743             : {
     744           0 :   tor_assert(circ);
     745           0 :   tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
     746           0 :   log_info(LD_REND, "Introduction circuit %u has opened. Attaching streams.",
     747             :            (unsigned int) TO_CIRCUIT(circ)->n_circ_id);
     748             : 
     749             :   /* This is an introduction circuit so we'll attach the correct
     750             :    * authentication key to the circuit identifier so it can be identified
     751             :    * properly later on. */
     752           0 :   if (setup_intro_circ_auth_key(circ) < 0) {
     753             :     return;
     754             :   }
     755             : 
     756           0 :   connection_ap_attach_pending(1);
     757             : }
     758             : 
     759             : /** Called when a rendezvous circuit has opened. */
     760             : static void
     761           0 : client_rendezvous_circ_has_opened(origin_circuit_t *circ)
     762             : {
     763           0 :   tor_assert(circ);
     764           0 :   tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
     765             : 
     766           0 :   const extend_info_t *rp_ei = circ->build_state->chosen_exit;
     767             : 
     768             :   /* Check that we didn't accidentally choose a node that does not understand
     769             :    * the v3 rendezvous protocol */
     770           0 :   if (rp_ei) {
     771           0 :     const node_t *rp_node = node_get_by_id(rp_ei->identity_digest);
     772           0 :     if (rp_node && !node_supports_v3_rendezvous_point(rp_node)) {
     773             :       /* Even tho we checked that this node supported v3 when we created the
     774             :          rendezvous circuit, there is a chance that we might think it does
     775             :          not support v3 anymore. This might happen if we got a new consensus
     776             :          in the meanwhile, where the relay is still listed but its listed
     777             :          descriptor digest has changed and hence we can't access its 'ri' or
     778             :          'md'. */
     779           0 :       log_info(LD_REND, "Rendezvous node %s did not support v3 after circuit "
     780             :                "has opened.", safe_str_client(extend_info_describe(rp_ei)));
     781           0 :       return;
     782             :     }
     783             :   }
     784             : 
     785           0 :   log_info(LD_REND, "Rendezvous circuit has opened to %s.",
     786             :            safe_str_client(extend_info_describe(rp_ei)));
     787             : 
     788             :   /* Ignore returned value, nothing we can really do. On failure, the circuit
     789             :    * will be marked for close. */
     790           0 :   hs_circ_send_establish_rendezvous(circ);
     791             : 
     792             :   /* Register rend circuit in circuitmap if it's still alive. */
     793           0 :   if (!TO_CIRCUIT(circ)->marked_for_close) {
     794           0 :     hs_circuitmap_register_rend_circ_client_side(circ,
     795           0 :                                      circ->hs_ident->rendezvous_cookie);
     796             :   }
     797             : }
     798             : 
     799             : /** This is an helper function that convert a descriptor intro point object ip
     800             :  * to a newly allocated extend_info_t object fully initialized. Return NULL if
     801             :  * we can't convert it for which chances are that we are missing or malformed
     802             :  * link specifiers. */
     803             : STATIC extend_info_t *
     804          75 : desc_intro_point_to_extend_info(const hs_desc_intro_point_t *ip)
     805             : {
     806          75 :   extend_info_t *ei;
     807             : 
     808          75 :   tor_assert(ip);
     809             : 
     810             :   /* Explicitly put the direct connection option to 0 because this is client
     811             :    * side and there is no such thing as a non anonymous client. */
     812          75 :   ei = hs_get_extend_info_from_lspecs(ip->link_specifiers, &ip->onion_key, 0);
     813             : 
     814          75 :   return ei;
     815             : }
     816             : 
     817             : /** Return true iff the intro point ip for the service service_pk is usable.
     818             :  * This function checks if the intro point is in the client intro state cache
     819             :  * and checks at the failures. It is considered usable if:
     820             :  *   - No error happened (INTRO_POINT_FAILURE_GENERIC)
     821             :  *   - It is not flagged as timed out (INTRO_POINT_FAILURE_TIMEOUT)
     822             :  *   - The unreachable count is lower than
     823             :  *     MAX_INTRO_POINT_REACHABILITY_FAILURES (INTRO_POINT_FAILURE_UNREACHABLE)
     824             :  */
     825             : static int
     826         253 : intro_point_is_usable(const ed25519_public_key_t *service_pk,
     827             :                       const hs_desc_intro_point_t *ip)
     828             : {
     829         253 :   const hs_cache_intro_state_t *state;
     830             : 
     831         253 :   tor_assert(service_pk);
     832         253 :   tor_assert(ip);
     833             : 
     834         506 :   state = hs_cache_client_intro_state_find(service_pk,
     835         253 :                                            &ip->auth_key_cert->signed_key);
     836         253 :   if (state == NULL) {
     837             :     /* This means we've never encountered any problem thus usable. */
     838         136 :     goto usable;
     839             :   }
     840         117 :   if (state->error) {
     841         116 :     log_info(LD_REND, "Intro point with auth key %s had an error. Not usable",
     842             :              safe_str_client(ed25519_fmt(&ip->auth_key_cert->signed_key)));
     843         116 :     goto not_usable;
     844             :   }
     845           1 :   if (state->timed_out) {
     846           1 :     log_info(LD_REND, "Intro point with auth key %s timed out. Not usable",
     847             :              safe_str_client(ed25519_fmt(&ip->auth_key_cert->signed_key)));
     848           1 :     goto not_usable;
     849             :   }
     850           0 :   if (state->unreachable_count >= MAX_INTRO_POINT_REACHABILITY_FAILURES) {
     851           0 :     log_info(LD_REND, "Intro point with auth key %s unreachable. Not usable",
     852             :              safe_str_client(ed25519_fmt(&ip->auth_key_cert->signed_key)));
     853           0 :     goto not_usable;
     854             :   }
     855             : 
     856           0 :  usable:
     857             :   return 1;
     858             :  not_usable:
     859             :   return 0;
     860             : }
     861             : 
     862             : /** Using a descriptor desc, return a newly allocated extend_info_t object of a
     863             :  * randomly picked introduction point from its list. Return NULL if none are
     864             :  * usable. */
     865             : STATIC extend_info_t *
     866          68 : client_get_random_intro(const ed25519_public_key_t *service_pk)
     867             : {
     868          68 :   extend_info_t *ei = NULL, *ei_excluded = NULL;
     869          68 :   smartlist_t *usable_ips = NULL;
     870          68 :   const hs_descriptor_t *desc;
     871          68 :   const hs_desc_encrypted_data_t *enc_data;
     872          68 :   const or_options_t *options = get_options();
     873             :   /* Calculate the onion address for logging purposes */
     874          68 :   char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
     875             : 
     876          68 :   tor_assert(service_pk);
     877             : 
     878          68 :   desc = hs_cache_lookup_as_client(service_pk);
     879             :   /* Assume the service is v3 if the descriptor is missing. This is ok,
     880             :    * because we only use the address in log messages */
     881         135 :   hs_build_address(service_pk,
     882          67 :                    desc ? desc->plaintext_data.version : HS_VERSION_THREE,
     883             :                    onion_address);
     884          68 :   if (desc == NULL || !hs_client_any_intro_points_usable(service_pk,
     885             :                                                          desc)) {
     886           3 :     log_info(LD_REND, "Unable to randomly select an introduction point "
     887             :              "for service %s because descriptor %s. We can't connect.",
     888             :              safe_str_client(onion_address),
     889             :              (desc) ? "doesn't have any usable intro points"
     890             :                     : "is missing (assuming v3 onion address)");
     891           2 :     goto end;
     892             :   }
     893             : 
     894          66 :   enc_data = &desc->encrypted_data;
     895          66 :   usable_ips = smartlist_new();
     896          66 :   smartlist_add_all(usable_ips, enc_data->intro_points);
     897         168 :   while (smartlist_len(usable_ips) != 0) {
     898         167 :     int idx;
     899         167 :     const hs_desc_intro_point_t *ip;
     900             : 
     901             :     /* Pick a random intro point and immediately remove it from the usable
     902             :      * list so we don't pick it again if we have to iterate more. */
     903         167 :     idx = crypto_rand_int(smartlist_len(usable_ips));
     904         167 :     ip = smartlist_get(usable_ips, idx);
     905         167 :     smartlist_del(usable_ips, idx);
     906             : 
     907             :     /* We need to make sure we have a usable intro points which is in a good
     908             :      * state in our cache. */
     909         167 :     if (!intro_point_is_usable(service_pk, ip)) {
     910          97 :       continue;
     911             :     }
     912             : 
     913             :     /* Generate an extend info object from the intro point object. */
     914          70 :     ei = desc_intro_point_to_extend_info(ip);
     915          70 :     if (ei == NULL) {
     916             :       /* We can get here for instance if the intro point is a private address
     917             :        * and we aren't allowed to extend to those. */
     918           2 :       log_info(LD_REND, "Unable to select introduction point with auth key %s "
     919             :                "for service %s, because we could not extend to it.",
     920             :                safe_str_client(ed25519_fmt(&ip->auth_key_cert->signed_key)),
     921             :                safe_str_client(onion_address));
     922           2 :       continue;
     923             :     }
     924             : 
     925             :     /* Test the pick against ExcludeNodes. */
     926          68 :     if (routerset_contains_extendinfo(options->ExcludeNodes, ei)) {
     927             :       /* If this pick is in the ExcludeNodes list, we keep its reference so if
     928             :        * we ever end up not being able to pick anything else and StrictNodes is
     929             :        * unset, we'll use it. */
     930           3 :       if (ei_excluded) {
     931             :         /* If something was already here free it. After the loop is gone we
     932             :          * will examine the last excluded intro point, and that's fine since
     933             :          * that's random anyway */
     934           2 :         extend_info_free(ei_excluded);
     935             :       }
     936           3 :       ei_excluded = ei;
     937           3 :       continue;
     938             :     }
     939             : 
     940             :     /* Good pick! Let's go with this. */
     941          65 :     goto end;
     942             :   }
     943             : 
     944             :   /* Reaching this point means a couple of things. Either we can't use any of
     945             :    * the intro point listed because the IP address can't be extended to or it
     946             :    * is listed in the ExcludeNodes list. In the later case, if StrictNodes is
     947             :    * set, we are forced to not use anything. */
     948           1 :   ei = ei_excluded;
     949           1 :   if (options->StrictNodes) {
     950           1 :     log_warn(LD_REND, "Every introduction point for service %s is in the "
     951             :              "ExcludeNodes set and StrictNodes is set. We can't connect.",
     952             :              safe_str_client(onion_address));
     953           1 :     extend_info_free(ei);
     954           1 :     ei = NULL;
     955             :   } else {
     956           0 :     log_fn(LOG_PROTOCOL_WARN, LD_REND, "Every introduction point for service "
     957             :            "%s is unusable or we can't extend to it. We can't connect.",
     958             :            safe_str_client(onion_address));
     959             :   }
     960             : 
     961          68 :  end:
     962          68 :   smartlist_free(usable_ips);
     963          68 :   memwipe(onion_address, 0, sizeof(onion_address));
     964          68 :   return ei;
     965             : }
     966             : 
     967             : /** Return true iff all intro points for the given service have timed out. */
     968             : static bool
     969           4 : intro_points_all_timed_out(const ed25519_public_key_t *service_pk)
     970             : {
     971           4 :   bool ret = false;
     972             : 
     973           4 :   tor_assert(service_pk);
     974             : 
     975           4 :   const hs_descriptor_t *desc = hs_cache_lookup_as_client(service_pk);
     976           4 :   if (BUG(!desc)) {
     977             :     /* We can't introduce without a descriptor so ending up here means somehow
     978             :      * between the introduction failure and this, the cache entry was removed
     979             :      * which shouldn't be possible in theory. */
     980           0 :     goto end;
     981             :   }
     982             : 
     983           8 :   SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points,
     984             :                           const hs_desc_intro_point_t *, ip) {
     985           7 :     const hs_cache_intro_state_t *state =
     986          14 :       hs_cache_client_intro_state_find(service_pk,
     987           7 :                                        &ip->auth_key_cert->signed_key);
     988           7 :     if (!state || !state->timed_out) {
     989             :       /* No state or if this intro point has not timed out, we are done since
     990             :        * clearly not all of them have timed out. */
     991           3 :       goto end;
     992             :     }
     993           4 :   } SMARTLIST_FOREACH_END(ip);
     994             : 
     995             :   /* Exiting the loop here means that all intro points we've looked at have
     996             :    * timed out. Note that we can _not_ have a descriptor without intro points
     997             :    * in the client cache. */
     998             :   ret = true;
     999             : 
    1000           4 :  end:
    1001           4 :   return ret;
    1002             : }
    1003             : 
    1004             : /** Called when a rendezvous circuit has timed out. Every stream attached to
    1005             :  * the circuit will get set with the SOCKS5_HS_REND_FAILED (0xF3) extended
    1006             :  * error code so if the connection to the rendezvous point ends up not
    1007             :  * working, this code could be sent back as a reason. */
    1008             : static void
    1009           1 : socks_mark_rend_circuit_timed_out(const origin_circuit_t *rend_circ)
    1010             : {
    1011           1 :   tor_assert(rend_circ);
    1012             : 
    1013             :   /* For each entry connection attached to this rendezvous circuit, report
    1014             :    * the error. */
    1015           2 :   for (edge_connection_t *edge = rend_circ->p_streams; edge;
    1016           1 :        edge = edge->next_stream) {
    1017           1 :      entry_connection_t *entry = EDGE_TO_ENTRY_CONN(edge);
    1018           1 :      if (entry->socks_request) {
    1019           1 :        entry->socks_request->socks_extended_error_code =
    1020             :          SOCKS5_HS_REND_FAILED;
    1021             :      }
    1022             :   }
    1023           1 : }
    1024             : 
    1025             : /** Called when introduction has failed meaning there is no more usable
    1026             :  * introduction points to be used (either NACKed or failed) for the given
    1027             :  * entry connection.
    1028             :  *
    1029             :  * This function only reports back the SOCKS5_HS_INTRO_FAILED (0xF2) code or
    1030             :  * SOCKS5_HS_INTRO_TIMEDOUT (0xF7) if all intros have timed out. The caller
    1031             :  * has to make sure to close the entry connections. */
    1032             : static void
    1033           4 : socks_mark_introduction_failed(entry_connection_t *conn,
    1034             :                                  const ed25519_public_key_t *identity_pk)
    1035             : {
    1036           4 :   socks5_reply_status_t code = SOCKS5_HS_INTRO_FAILED;
    1037             : 
    1038           4 :   tor_assert(conn);
    1039           4 :   tor_assert(conn->socks_request);
    1040           4 :   tor_assert(identity_pk);
    1041             : 
    1042           4 :   if (intro_points_all_timed_out(identity_pk)) {
    1043           1 :     code = SOCKS5_HS_INTRO_TIMEDOUT;
    1044             :   }
    1045           4 :   conn->socks_request->socks_extended_error_code = code;
    1046           4 : }
    1047             : 
    1048             : /** For this introduction circuit, we'll look at if we have any usable
    1049             :  * introduction point left for this service. If so, we'll use the circuit to
    1050             :  * re-extend to a new intro point. Else, we'll close the circuit and its
    1051             :  * corresponding rendezvous circuit. Return 0 if we are re-extending else -1
    1052             :  * if we are closing the circuits.
    1053             :  *
    1054             :  * This is called when getting an INTRODUCE_ACK cell with a NACK. */
    1055             : static int
    1056           0 : close_or_reextend_intro_circ(origin_circuit_t *intro_circ)
    1057             : {
    1058           0 :   int ret = -1;
    1059           0 :   const hs_descriptor_t *desc;
    1060           0 :   origin_circuit_t *rend_circ;
    1061             : 
    1062           0 :   tor_assert(intro_circ);
    1063             : 
    1064           0 :   desc = hs_cache_lookup_as_client(&intro_circ->hs_ident->identity_pk);
    1065           0 :   if (desc == NULL) {
    1066             :     /* We can't continue without a descriptor. This is possible if the cache
    1067             :      * was cleaned up between the intro point established and the reception of
    1068             :      * the introduce ack. */
    1069           0 :     goto close;
    1070             :   }
    1071             :   /* We still have the descriptor, great! Let's try to see if we can
    1072             :    * re-extend by looking up if there are any usable intro points. */
    1073           0 :   if (!hs_client_any_intro_points_usable(&intro_circ->hs_ident->identity_pk,
    1074             :                                          desc)) {
    1075           0 :     goto close;
    1076             :   }
    1077             :   /* Try to re-extend now. */
    1078           0 :   if (hs_client_reextend_intro_circuit(intro_circ) < 0) {
    1079           0 :     goto close;
    1080             :   }
    1081             :   /* Success on re-extending. Don't return an error. */
    1082           0 :   ret = 0;
    1083           0 :   goto end;
    1084             : 
    1085           0 :  close:
    1086             :   /* Change the intro circuit purpose before so we don't report an intro point
    1087             :    * failure again triggering an extra descriptor fetch. The circuit can
    1088             :    * already be closed on failure to re-extend. */
    1089           0 :   if (!TO_CIRCUIT(intro_circ)->marked_for_close) {
    1090           0 :     circuit_change_purpose(TO_CIRCUIT(intro_circ),
    1091             :                            CIRCUIT_PURPOSE_C_INTRODUCE_ACKED);
    1092           0 :     circuit_mark_for_close(TO_CIRCUIT(intro_circ), END_CIRC_REASON_FINISHED);
    1093             :   }
    1094             :   /* Close the related rendezvous circuit. */
    1095           0 :   rend_circ = hs_circuitmap_get_rend_circ_client_side(
    1096           0 :                                      intro_circ->hs_ident->rendezvous_cookie);
    1097             :   /* The rendezvous circuit might have collapsed while the INTRODUCE_ACK was
    1098             :    * inflight so we can't expect one every time. */
    1099           0 :   if (rend_circ) {
    1100           0 :     circuit_mark_for_close(TO_CIRCUIT(rend_circ), END_CIRC_REASON_FINISHED);
    1101             :   }
    1102             : 
    1103           0 :  end:
    1104           0 :   return ret;
    1105             : }
    1106             : 
    1107             : /** Called when we get an INTRODUCE_ACK success status code. Do the appropriate
    1108             :  * actions for the rendezvous point and finally close intro_circ. */
    1109             : static void
    1110           0 : handle_introduce_ack_success(origin_circuit_t *intro_circ)
    1111             : {
    1112           0 :   origin_circuit_t *rend_circ = NULL;
    1113             : 
    1114           0 :   tor_assert(intro_circ);
    1115             : 
    1116           0 :   log_info(LD_REND, "Received INTRODUCE_ACK ack! Informing rendezvous");
    1117             : 
    1118             :   /* Get the rendezvous circuit for this rendezvous cookie. */
    1119           0 :   uint8_t *rendezvous_cookie = intro_circ->hs_ident->rendezvous_cookie;
    1120           0 :   rend_circ =
    1121           0 :   hs_circuitmap_get_established_rend_circ_client_side(rendezvous_cookie);
    1122           0 :   if (rend_circ == NULL) {
    1123           0 :     log_info(LD_REND, "Can't find any rendezvous circuit. Stopping");
    1124           0 :     goto end;
    1125             :   }
    1126             : 
    1127           0 :   assert_circ_anonymity_ok(rend_circ, get_options());
    1128             : 
    1129             :   /* It is possible to get a RENDEZVOUS2 cell before the INTRODUCE_ACK which
    1130             :    * means that the circuit will be joined and already transmitting data. In
    1131             :    * that case, simply skip the purpose change and close the intro circuit
    1132             :    * like it should be. */
    1133           0 :   if (TO_CIRCUIT(rend_circ)->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
    1134           0 :     goto end;
    1135             :   }
    1136           0 :   circuit_change_purpose(TO_CIRCUIT(rend_circ),
    1137             :                          CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED);
    1138             :   /* Set timestamp_dirty, because circuit_expire_building expects it to
    1139             :    * specify when a circuit entered the
    1140             :    * CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED state. */
    1141           0 :   TO_CIRCUIT(rend_circ)->timestamp_dirty = time(NULL);
    1142             : 
    1143           0 :  end:
    1144             :   /* We don't need the intro circuit anymore. It did what it had to do! */
    1145           0 :   circuit_change_purpose(TO_CIRCUIT(intro_circ),
    1146             :                          CIRCUIT_PURPOSE_C_INTRODUCE_ACKED);
    1147           0 :   circuit_mark_for_close(TO_CIRCUIT(intro_circ), END_CIRC_REASON_FINISHED);
    1148             : 
    1149             :   /* XXX: Close pending intro circuits we might have in parallel. */
    1150           0 :   return;
    1151             : }
    1152             : 
    1153             : /** Called when we get an INTRODUCE_ACK failure status code. Depending on our
    1154             :  * failure cache status, either close the circuit or re-extend to a new
    1155             :  * introduction point. */
    1156             : static void
    1157           0 : handle_introduce_ack_bad(origin_circuit_t *circ, int status)
    1158             : {
    1159           0 :   tor_assert(circ);
    1160             : 
    1161           0 :   log_info(LD_REND, "Received INTRODUCE_ACK nack by %s. Reason: %u",
    1162             :       safe_str_client(extend_info_describe(circ->build_state->chosen_exit)),
    1163             :       status);
    1164             : 
    1165             :   /* It's a NAK. The introduction point didn't relay our request. */
    1166           0 :   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_INTRODUCING);
    1167             : 
    1168             :   /* Note down this failure in the intro point failure cache. Depending on how
    1169             :    * many times we've tried this intro point, close it or reextend. */
    1170           0 :   hs_cache_client_intro_state_note(&circ->hs_ident->identity_pk,
    1171           0 :                                    &circ->hs_ident->intro_auth_pk,
    1172             :                                    INTRO_POINT_FAILURE_GENERIC);
    1173           0 : }
    1174             : 
    1175             : /** Called when we get an INTRODUCE_ACK on the intro circuit circ. The encoded
    1176             :  * cell is in payload of length payload_len. Return 0 on success else a
    1177             :  * negative value. The circuit is either close or reuse to re-extend to a new
    1178             :  * introduction point. */
    1179             : static int
    1180           0 : handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload,
    1181             :                      size_t payload_len)
    1182             : {
    1183           0 :   int status, ret = -1;
    1184             : 
    1185           0 :   tor_assert(circ);
    1186           0 :   tor_assert(circ->build_state);
    1187           0 :   tor_assert(circ->build_state->chosen_exit);
    1188           0 :   assert_circ_anonymity_ok(circ, get_options());
    1189           0 :   tor_assert(payload);
    1190             : 
    1191           0 :   status = hs_cell_parse_introduce_ack(payload, payload_len);
    1192           0 :   switch (status) {
    1193           0 :   case TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS:
    1194           0 :     ret = 0;
    1195           0 :     handle_introduce_ack_success(circ);
    1196           0 :     goto end;
    1197           0 :   case TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID:
    1198             :   case TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT:
    1199             :   /* It is possible that the intro point can send us an unknown status code
    1200             :    * for the NACK that we do not know about like a new code for instance.
    1201             :    * Just fallthrough so we can note down the NACK and re-extend. */
    1202             :   default:
    1203           0 :     handle_introduce_ack_bad(circ, status);
    1204             :     /* We are going to see if we have to close the circuits (IP and RP) or we
    1205             :      * can re-extend to a new intro point. */
    1206           0 :     ret = close_or_reextend_intro_circ(circ);
    1207           0 :     break;
    1208             :   }
    1209             : 
    1210           0 :  end:
    1211           0 :   return ret;
    1212             : }
    1213             : 
    1214             : /** Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The
    1215             :  * encoded cell is in payload of length payload_len. Return 0 on success or a
    1216             :  * negative value on error. On error, the circuit is marked for close. */
    1217             : STATIC int
    1218           1 : handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
    1219             :                    size_t payload_len)
    1220             : {
    1221           1 :   int ret = -1;
    1222           1 :   curve25519_public_key_t server_pk;
    1223           1 :   uint8_t auth_mac[DIGEST256_LEN] = {0};
    1224           1 :   uint8_t handshake_info[CURVE25519_PUBKEY_LEN + sizeof(auth_mac)] = {0};
    1225           1 :   hs_ntor_rend_cell_keys_t keys;
    1226           1 :   const hs_ident_circuit_t *ident;
    1227             : 
    1228           1 :   tor_assert(circ);
    1229           1 :   tor_assert(payload);
    1230             : 
    1231             :   /* Make things easier. */
    1232           1 :   ident = circ->hs_ident;
    1233           1 :   tor_assert(ident);
    1234             : 
    1235           1 :   if (hs_cell_parse_rendezvous2(payload, payload_len, handshake_info,
    1236             :                                 sizeof(handshake_info)) < 0) {
    1237           0 :     goto err;
    1238             :   }
    1239             :   /* Get from the handshake info the SERVER_PK and AUTH_MAC. */
    1240           1 :   memcpy(&server_pk, handshake_info, CURVE25519_PUBKEY_LEN);
    1241           1 :   memcpy(auth_mac, handshake_info + CURVE25519_PUBKEY_LEN, sizeof(auth_mac));
    1242             : 
    1243             :   /* Generate the handshake info. */
    1244           1 :   if (hs_ntor_client_get_rendezvous1_keys(&ident->intro_auth_pk,
    1245           1 :                                           &ident->rendezvous_client_kp,
    1246           1 :                                           &ident->intro_enc_pk, &server_pk,
    1247             :                                           &keys) < 0) {
    1248           0 :     log_info(LD_REND, "Unable to compute the rendezvous keys.");
    1249           0 :     goto err;
    1250             :   }
    1251             : 
    1252             :   /* Critical check, make sure that the MAC matches what we got with what we
    1253             :    * computed just above. */
    1254           1 :   if (!hs_ntor_client_rendezvous2_mac_is_good(&keys, auth_mac)) {
    1255           0 :     log_info(LD_REND, "Invalid MAC in RENDEZVOUS2. Rejecting cell.");
    1256           0 :     goto err;
    1257             :   }
    1258             : 
    1259             :   /* Setup the e2e encryption on the circuit and finalize its state. */
    1260           1 :   if (hs_circuit_setup_e2e_rend_circ(circ, keys.ntor_key_seed,
    1261             :                                      sizeof(keys.ntor_key_seed), 0) < 0) {
    1262           0 :     log_info(LD_REND, "Unable to setup the e2e encryption.");
    1263           0 :     goto err;
    1264             :   }
    1265             :   /* Success. Hidden service connection finalized! */
    1266           1 :   ret = 0;
    1267           1 :   goto end;
    1268             : 
    1269           0 :  err:
    1270           0 :   circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
    1271           1 :  end:
    1272           1 :   memwipe(&keys, 0, sizeof(keys));
    1273           1 :   return ret;
    1274             : }
    1275             : 
    1276             : /** Return true iff the client can fetch a descriptor for this service public
    1277             :  * identity key and status_out if not NULL is untouched. If the client can
    1278             :  * _not_ fetch the descriptor and if status_out is not NULL, it is set with
    1279             :  * the fetch status code. */
    1280             : static unsigned int
    1281           6 : can_client_refetch_desc(const ed25519_public_key_t *identity_pk,
    1282             :                         hs_client_fetch_status_t *status_out)
    1283             : {
    1284           6 :   hs_client_fetch_status_t status;
    1285             : 
    1286           6 :   tor_assert(identity_pk);
    1287             : 
    1288             :   /* Are we configured to fetch descriptors? */
    1289           6 :   if (!get_options()->FetchHidServDescriptors) {
    1290           1 :     log_warn(LD_REND, "We received an onion address for a hidden service "
    1291             :                       "descriptor but we are configured to not fetch.");
    1292           1 :     status = HS_CLIENT_FETCH_NOT_ALLOWED;
    1293           1 :     goto cannot;
    1294             :   }
    1295             : 
    1296             :   /* Without a usable consensus we can't do any client actions. It is needed
    1297             :    * to compute the hashring for a service. */
    1298           5 :   if (!networkstatus_get_reasonably_live_consensus(approx_time(),
    1299             :                                          usable_consensus_flavor())) {
    1300           2 :     log_info(LD_REND, "Can't fetch descriptor for service %s because we "
    1301             :                       "are missing a live consensus. Stalling connection.",
    1302             :              safe_str_client(ed25519_fmt(identity_pk)));
    1303           2 :     status = HS_CLIENT_FETCH_MISSING_INFO;
    1304           2 :     goto cannot;
    1305             :   }
    1306             : 
    1307           3 :   if (!router_have_minimum_dir_info()) {
    1308           1 :     log_info(LD_REND, "Can't fetch descriptor for service %s because we "
    1309             :                       "dont have enough descriptors. Stalling connection.",
    1310             :              safe_str_client(ed25519_fmt(identity_pk)));
    1311           1 :     status = HS_CLIENT_FETCH_MISSING_INFO;
    1312           1 :     goto cannot;
    1313             :   }
    1314             : 
    1315             :   /* Check if fetching a desc for this HS is useful to us right now */
    1316             :   {
    1317           2 :     const hs_descriptor_t *cached_desc = NULL;
    1318           2 :     cached_desc = hs_cache_lookup_as_client(identity_pk);
    1319           2 :     if (cached_desc && hs_client_any_intro_points_usable(identity_pk,
    1320             :                                                          cached_desc)) {
    1321           0 :       log_info(LD_GENERAL, "We would fetch a v3 hidden service descriptor "
    1322             :                            "but we already have a usable descriptor.");
    1323           0 :       status = HS_CLIENT_FETCH_HAVE_DESC;
    1324           0 :       goto cannot;
    1325             :     }
    1326             :   }
    1327             : 
    1328             :   /* Don't try to refetch while we have a pending request for it. */
    1329           2 :   if (directory_request_is_pending(identity_pk)) {
    1330           1 :     log_info(LD_REND, "Already a pending directory request. Waiting on it.");
    1331           1 :     status = HS_CLIENT_FETCH_PENDING;
    1332           1 :     goto cannot;
    1333             :   }
    1334             : 
    1335             :   /* Yes, client can fetch! */
    1336             :   return 1;
    1337           5 :  cannot:
    1338           5 :   if (status_out) {
    1339           5 :     *status_out = status;
    1340             :   }
    1341             :   return 0;
    1342             : }
    1343             : 
    1344             : /** Purge the client authorization cache of all ephemeral entries that is the
    1345             :  * entries that are not flagged with CLIENT_AUTH_FLAG_IS_PERMANENT.
    1346             :  *
    1347             :  * This is called from the hs_client_purge_state() used by a SIGNEWNYM. */
    1348             : STATIC void
    1349           2 : purge_ephemeral_client_auth(void)
    1350             : {
    1351           4 :   DIGEST256MAP_FOREACH_MODIFY(client_auths, key,
    1352             :                               hs_client_service_authorization_t *, auth) {
    1353             :     /* Cleanup every entry that are _NOT_ permanent that is ephemeral. */
    1354           2 :     if (!(auth->flags & CLIENT_AUTH_FLAG_IS_PERMANENT)) {
    1355           1 :       MAP_DEL_CURRENT(key);
    1356           2 :       client_service_authorization_free(auth);
    1357             :     }
    1358           2 :   } DIGESTMAP_FOREACH_END;
    1359             : 
    1360           2 :   log_info(LD_REND, "Client onion service ephemeral authorization "
    1361             :                     "cache has been purged.");
    1362           2 : }
    1363             : 
    1364             : /** Return the client auth in the map using the service identity public key.
    1365             :  * Return NULL if it does not exist in the map. */
    1366             : static hs_client_service_authorization_t *
    1367          18 : find_client_auth(const ed25519_public_key_t *service_identity_pk)
    1368             : {
    1369             :   /* If the map is not allocated, we can assume that we do not have any client
    1370             :    * auth information. */
    1371          18 :   if (!client_auths) {
    1372             :     return NULL;
    1373             :   }
    1374           3 :   return digest256map_get(client_auths, service_identity_pk->pubkey);
    1375             : }
    1376             : 
    1377             : /** This is called when a descriptor has arrived following a fetch request and
    1378             :  * has been stored in the client cache. The given entry connections, matching
    1379             :  * the service identity key, will get attached to the service circuit. */
    1380             : static void
    1381           4 : client_desc_has_arrived(const smartlist_t *entry_conns)
    1382             : {
    1383           4 :   time_t now = time(NULL);
    1384             : 
    1385           4 :   tor_assert(entry_conns);
    1386             : 
    1387           8 :   SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
    1388           4 :     const hs_descriptor_t *desc;
    1389           4 :     edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
    1390           4 :     const ed25519_public_key_t *identity_pk =
    1391           4 :       &edge_conn->hs_ident->identity_pk;
    1392             : 
    1393             :     /* We were just called because we stored the descriptor for this service
    1394             :      * so not finding a descriptor means we have a bigger problem. */
    1395           4 :     desc = hs_cache_lookup_as_client(identity_pk);
    1396           4 :     if (BUG(desc == NULL)) {
    1397           0 :       goto end;
    1398             :     }
    1399             : 
    1400           4 :     if (!hs_client_any_intro_points_usable(identity_pk, desc)) {
    1401           4 :       log_info(LD_REND, "Hidden service descriptor is unusable. "
    1402             :                         "Closing streams.");
    1403             :       /* Report the extended socks error code that we were unable to introduce
    1404             :        * to the service. */
    1405           4 :       socks_mark_introduction_failed(entry_conn, identity_pk);
    1406             : 
    1407           4 :       connection_mark_unattached_ap(entry_conn,
    1408             :                                     END_STREAM_REASON_RESOLVEFAILED);
    1409             :       /* We are unable to use the descriptor so remove the directory request
    1410             :        * from the cache so the next connection can try again. */
    1411           4 :       note_connection_attempt_succeeded(edge_conn->hs_ident);
    1412           4 :       continue;
    1413             :     }
    1414             : 
    1415           0 :     log_info(LD_REND, "Descriptor has arrived. Launching circuits.");
    1416             : 
    1417             :     /* Mark connection as waiting for a circuit since we do have a usable
    1418             :      * descriptor now. */
    1419           0 :     mark_conn_as_waiting_for_circuit(&edge_conn->base_, now);
    1420           4 :   } SMARTLIST_FOREACH_END(entry_conn);
    1421             : 
    1422           4 :  end:
    1423           4 :   return;
    1424             : }
    1425             : 
    1426             : /** This is called when a descriptor fetch was successful but the descriptor
    1427             :  * couldn't be decrypted due to missing or bad client authorization. */
    1428             : static void
    1429           2 : client_desc_missing_bad_client_auth(const smartlist_t *entry_conns,
    1430             :                                     hs_desc_decode_status_t status)
    1431             : {
    1432           2 :   tor_assert(entry_conns);
    1433             : 
    1434           4 :   SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
    1435           2 :     socks5_reply_status_t code;
    1436           2 :     if (status == HS_DESC_DECODE_BAD_CLIENT_AUTH) {
    1437             :       code = SOCKS5_HS_BAD_CLIENT_AUTH;
    1438           1 :     } else if (status == HS_DESC_DECODE_NEED_CLIENT_AUTH) {
    1439             :       code = SOCKS5_HS_MISSING_CLIENT_AUTH;
    1440             :     } else {
    1441             :       /* We should not be called with another type of status. Recover by
    1442             :        * sending a generic error. */
    1443           0 :       tor_assert_nonfatal_unreached();
    1444           0 :       code = SOCKS5_GENERAL_ERROR;
    1445             :     }
    1446           2 :     entry_conn->socks_request->socks_extended_error_code = code;
    1447           2 :     connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_MISC);
    1448           2 :   } SMARTLIST_FOREACH_END(entry_conn);
    1449           2 : }
    1450             : 
    1451             : /** Called when we get a 200 directory fetch status code. */
    1452             : static void
    1453           6 : client_dir_fetch_200(dir_connection_t *dir_conn,
    1454             :                      const smartlist_t *entry_conns, const char *body)
    1455             : {
    1456           6 :   hs_desc_decode_status_t decode_status;
    1457             : 
    1458           6 :   tor_assert(dir_conn);
    1459           6 :   tor_assert(entry_conns);
    1460           6 :   tor_assert(body);
    1461             : 
    1462             :   /* We got something: Try storing it in the cache. */
    1463          12 :   decode_status = hs_cache_store_as_client(body,
    1464           6 :                                            &dir_conn->hs_ident->identity_pk);
    1465           6 :   switch (decode_status) {
    1466           6 :   case HS_DESC_DECODE_OK:
    1467             :   case HS_DESC_DECODE_NEED_CLIENT_AUTH:
    1468             :   case HS_DESC_DECODE_BAD_CLIENT_AUTH:
    1469           6 :     log_info(LD_REND, "Stored hidden service descriptor successfully.");
    1470           6 :     TO_CONN(dir_conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
    1471           6 :     if (decode_status == HS_DESC_DECODE_OK) {
    1472           4 :       client_desc_has_arrived(entry_conns);
    1473             :     } else {
    1474             :       /* This handles both client auth decode status. */
    1475           2 :       client_desc_missing_bad_client_auth(entry_conns, decode_status);
    1476           3 :       log_info(LD_REND, "Stored hidden service descriptor requires "
    1477             :                          "%s client authorization.",
    1478             :                decode_status == HS_DESC_DECODE_NEED_CLIENT_AUTH ? "missing"
    1479             :                                                                 : "new");
    1480             :     }
    1481             :     /* Fire control port RECEIVED event. */
    1482           6 :     hs_control_desc_event_received(dir_conn->hs_ident,
    1483           6 :                                    dir_conn->identity_digest);
    1484           6 :     hs_control_desc_event_content(dir_conn->hs_ident,
    1485             :                                   dir_conn->identity_digest, body);
    1486           6 :     break;
    1487           0 :   case HS_DESC_DECODE_ENCRYPTED_ERROR:
    1488             :   case HS_DESC_DECODE_SUPERENC_ERROR:
    1489             :   case HS_DESC_DECODE_PLAINTEXT_ERROR:
    1490             :   case HS_DESC_DECODE_GENERIC_ERROR:
    1491             :   default:
    1492           0 :     log_info(LD_REND, "Failed to store hidden service descriptor. "
    1493             :                       "Descriptor decoding status: %d", decode_status);
    1494             :     /* Fire control port FAILED event. */
    1495           0 :     hs_control_desc_event_failed(dir_conn->hs_ident,
    1496           0 :                                  dir_conn->identity_digest, "BAD_DESC");
    1497           0 :     hs_control_desc_event_content(dir_conn->hs_ident,
    1498             :                                   dir_conn->identity_digest, NULL);
    1499           0 :     break;
    1500             :   }
    1501           6 : }
    1502             : 
    1503             : /** Called when we get a 404 directory fetch status code. */
    1504             : static void
    1505           0 : client_dir_fetch_404(dir_connection_t *dir_conn,
    1506             :                      const smartlist_t *entry_conns)
    1507             : {
    1508           0 :   tor_assert(entry_conns);
    1509             : 
    1510             :   /* Not there. We'll retry when connection_about_to_close_connection() tries
    1511             :    * to clean this conn up. */
    1512           0 :   log_info(LD_REND, "Fetching hidden service v3 descriptor not found: "
    1513             :                     "Retrying at another directory.");
    1514             :   /* Fire control port FAILED event. */
    1515           0 :   hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
    1516             :                                "NOT_FOUND");
    1517           0 :   hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
    1518             :                                 NULL);
    1519             : 
    1520             :   /* Flag every entry connections that the descriptor was not found. */
    1521           0 :   SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
    1522           0 :     entry_conn->socks_request->socks_extended_error_code =
    1523             :       SOCKS5_HS_NOT_FOUND;
    1524           0 :   } SMARTLIST_FOREACH_END(entry_conn);
    1525           0 : }
    1526             : 
    1527             : /** Called when we get a 400 directory fetch status code. */
    1528             : static void
    1529           0 : client_dir_fetch_400(dir_connection_t *dir_conn, const char *reason)
    1530             : {
    1531           0 :   tor_assert(dir_conn);
    1532             : 
    1533           0 :   log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
    1534             :                     "http status 400 (%s). Dirserver didn't like our "
    1535             :                     "query? Retrying at another directory.",
    1536             :            escaped(reason));
    1537             : 
    1538             :   /* Fire control port FAILED event. */
    1539           0 :   hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
    1540             :                                "QUERY_REJECTED");
    1541           0 :   hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
    1542             :                                 NULL);
    1543           0 : }
    1544             : 
    1545             : /** Called when we get an unexpected directory fetch status code. */
    1546             : static void
    1547           0 : client_dir_fetch_unexpected(dir_connection_t *dir_conn, const char *reason,
    1548             :                             const int status_code)
    1549             : {
    1550           0 :   tor_assert(dir_conn);
    1551             : 
    1552           0 :   log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
    1553             :                     "http status %d (%s) response unexpected from HSDir "
    1554             :                     "server %s'. Retrying at another directory.",
    1555             :            status_code, escaped(reason),
    1556             :            connection_describe_peer(TO_CONN(dir_conn)));
    1557             :   /* Fire control port FAILED event. */
    1558           0 :   hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
    1559             :                                "UNEXPECTED");
    1560           0 :   hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
    1561             :                                 NULL);
    1562           0 : }
    1563             : 
    1564             : /** Get the full filename for storing the client auth credentials for the
    1565             :  *  service in <b>onion_address</b>. The base directory is <b>dir</b>.
    1566             :  *  This function never returns NULL. */
    1567             : static char *
    1568           3 : get_client_auth_creds_filename(const char *onion_address,
    1569             :                                const char *dir)
    1570             : {
    1571           3 :   char *full_fname = NULL;
    1572           3 :   char *fname;
    1573             : 
    1574           3 :   tor_asprintf(&fname, "%s.auth_private", onion_address);
    1575           3 :   full_fname = hs_path_from_filename(dir, fname);
    1576           3 :   tor_free(fname);
    1577             : 
    1578           3 :   return full_fname;
    1579             : }
    1580             : 
    1581             : /** Permanently store the credentials in <b>creds</b> to disk.
    1582             :  *
    1583             :  *  Return -1 if there was an error while storing the credentials, otherwise
    1584             :  *  return 0.
    1585             :  */
    1586             : static int
    1587           4 : store_permanent_client_auth_credentials(
    1588             :                               const hs_client_service_authorization_t *creds)
    1589             : {
    1590           4 :   const or_options_t *options = get_options();
    1591           4 :   char *full_fname = NULL;
    1592           4 :   char *file_contents = NULL;
    1593           4 :   char priv_key_b32[BASE32_NOPAD_LEN(CURVE25519_PUBKEY_LEN)+1];
    1594           4 :   int retval = -1;
    1595             : 
    1596           4 :   tor_assert(creds->flags & CLIENT_AUTH_FLAG_IS_PERMANENT);
    1597             : 
    1598             :   /* We need ClientOnionAuthDir to be set, otherwise we can't proceed */
    1599           4 :   if (!options->ClientOnionAuthDir) {
    1600           1 :     log_warn(LD_GENERAL, "Can't register permanent client auth credentials "
    1601             :              "for %s without ClientOnionAuthDir option. Discarding.",
    1602             :              creds->onion_address);
    1603           1 :     goto err;
    1604             :   }
    1605             : 
    1606             :   /* Make sure the directory exists and is private enough. */
    1607           3 :   if (check_private_dir(options->ClientOnionAuthDir, 0, options->User) < 0) {
    1608           0 :     goto err;
    1609             :   }
    1610             : 
    1611             :   /* Get filename that we should store the credentials */
    1612           6 :   full_fname = get_client_auth_creds_filename(creds->onion_address,
    1613           3 :                                               options->ClientOnionAuthDir);
    1614             : 
    1615             :   /* Encode client private key */
    1616           3 :   base32_encode(priv_key_b32, sizeof(priv_key_b32),
    1617           3 :                 (char*)creds->enc_seckey.secret_key,
    1618             :                 sizeof(creds->enc_seckey.secret_key));
    1619             : 
    1620             :   /* Get the full file contents and write it to disk! */
    1621           3 :   tor_asprintf(&file_contents, "%s:descriptor:x25519:%s",
    1622             :                creds->onion_address, priv_key_b32);
    1623           3 :   if (write_str_to_file(full_fname, file_contents, 0) < 0) {
    1624           0 :     log_warn(LD_GENERAL, "Failed to write client auth creds file for %s!",
    1625             :              creds->onion_address);
    1626           0 :     goto err;
    1627             :   }
    1628             : 
    1629             :   retval = 0;
    1630             : 
    1631           4 :  err:
    1632           4 :   tor_free(file_contents);
    1633           4 :   tor_free(full_fname);
    1634             : 
    1635           4 :   return retval;
    1636             : }
    1637             : 
    1638             : /** Register the credential <b>creds</b> as part of the client auth subsystem.
    1639             :  *
    1640             :  * Takes ownership of <b>creds</b>.
    1641             :  **/
    1642             : hs_client_register_auth_status_t
    1643           8 : hs_client_register_auth_credentials(hs_client_service_authorization_t *creds)
    1644             : {
    1645           8 :   ed25519_public_key_t service_identity_pk;
    1646           8 :   hs_client_service_authorization_t *old_creds = NULL;
    1647           8 :   hs_client_register_auth_status_t retval = REGISTER_SUCCESS;
    1648             : 
    1649           8 :   tor_assert(creds);
    1650             : 
    1651           8 :   if (!client_auths) {
    1652           3 :     client_auths = digest256map_new();
    1653             :   }
    1654             : 
    1655           8 :   if (hs_parse_address(creds->onion_address, &service_identity_pk,
    1656             :                        NULL, NULL) < 0) {
    1657           0 :     client_service_authorization_free(creds);
    1658           0 :     return REGISTER_FAIL_BAD_ADDRESS;
    1659             :   }
    1660             : 
    1661             :   /* If we reach this point, the credentials will be stored one way or another:
    1662             :    * Make them permanent if the user asked us to. */
    1663           8 :   if (creds->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
    1664           4 :     if (store_permanent_client_auth_credentials(creds) < 0) {
    1665           1 :       client_service_authorization_free(creds);
    1666           1 :       return REGISTER_FAIL_PERMANENT_STORAGE;
    1667             :     }
    1668             :   }
    1669             : 
    1670           7 :   old_creds = digest256map_get(client_auths, service_identity_pk.pubkey);
    1671           7 :   if (old_creds) {
    1672           1 :     digest256map_remove(client_auths, service_identity_pk.pubkey);
    1673           1 :     client_service_authorization_free(old_creds);
    1674           1 :     retval = REGISTER_SUCCESS_ALREADY_EXISTS;
    1675             :   }
    1676             : 
    1677           7 :   digest256map_set(client_auths, service_identity_pk.pubkey, creds);
    1678             : 
    1679             :   /** Now that we set the new credentials, also try to decrypt any cached
    1680             :    *  descriptors. */
    1681           7 :   if (hs_cache_client_new_auth_parse(&service_identity_pk)) {
    1682           0 :     retval = REGISTER_SUCCESS_AND_DECRYPTED;
    1683             :   }
    1684             : 
    1685             :   return retval;
    1686             : }
    1687             : 
    1688             : /** Load a client authorization file with <b>filename</b> that is stored under
    1689             :  *  the global client auth directory, and return a newly-allocated credentials
    1690             :  *  object if it parsed well. Otherwise, return NULL.
    1691             :  */
    1692             : static hs_client_service_authorization_t *
    1693           8 : get_creds_from_client_auth_filename(const char *filename,
    1694             :                                     const or_options_t *options)
    1695             : {
    1696           8 :   hs_client_service_authorization_t *auth = NULL;
    1697           8 :   char *client_key_file_path = NULL;
    1698           8 :   char *client_key_str = NULL;
    1699             : 
    1700           8 :   log_info(LD_REND, "Loading a client authorization key file %s...",
    1701             :            filename);
    1702             : 
    1703           8 :   if (!auth_key_filename_is_valid(filename)) {
    1704           2 :     log_notice(LD_REND, "Client authorization unrecognized filename %s. "
    1705             :                "File must end in .auth_private. Ignoring.",
    1706             :                filename);
    1707           2 :     goto err;
    1708             :   }
    1709             : 
    1710             :   /* Create a full path for a file. */
    1711           6 :   client_key_file_path = hs_path_from_filename(options->ClientOnionAuthDir,
    1712             :                                                filename);
    1713             : 
    1714           6 :   client_key_str = read_file_to_str(client_key_file_path, 0, NULL);
    1715           6 :   if (!client_key_str) {
    1716           0 :     log_warn(LD_REND, "The file %s cannot be read.", filename);
    1717           0 :     goto err;
    1718             :   }
    1719             : 
    1720           6 :   auth = parse_auth_file_content(client_key_str);
    1721           6 :   if (!auth) {
    1722           0 :     goto err;
    1723             :   }
    1724             : 
    1725           6 :  err:
    1726           8 :   tor_free(client_key_str);
    1727           8 :   tor_free(client_key_file_path);
    1728             : 
    1729           8 :   return auth;
    1730             : }
    1731             : 
    1732             : /*
    1733             :  * Remove the file in <b>filename</b> under the global client auth credential
    1734             :  * storage.
    1735             :  */
    1736             : static void
    1737           1 : remove_client_auth_creds_file(const char *filename)
    1738             : {
    1739           1 :   char *creds_file_path = NULL;
    1740           1 :   const or_options_t *options = get_options();
    1741             : 
    1742           1 :   creds_file_path = hs_path_from_filename(options->ClientOnionAuthDir,
    1743             :                                           filename);
    1744           1 :   if (tor_unlink(creds_file_path) != 0) {
    1745           0 :     log_warn(LD_REND, "Failed to remove client auth file (%s).",
    1746             :              creds_file_path);
    1747           0 :     goto end;
    1748             :   }
    1749             : 
    1750           1 :   log_warn(LD_REND, "Successfully removed client auth file (%s).",
    1751             :            creds_file_path);
    1752             : 
    1753           1 :  end:
    1754           1 :   tor_free(creds_file_path);
    1755           1 : }
    1756             : 
    1757             : /**
    1758             :  * Find the filesystem file corresponding to the permanent client auth
    1759             :  * credentials in <b>cred</b> and remove it.
    1760             :  */
    1761             : static void
    1762           1 : find_and_remove_client_auth_creds_file(
    1763             :                                  const hs_client_service_authorization_t *cred)
    1764             : {
    1765           1 :   smartlist_t *file_list = NULL;
    1766           1 :   const or_options_t *options = get_options();
    1767             : 
    1768           1 :   tor_assert(cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT);
    1769             : 
    1770           1 :   if (!options->ClientOnionAuthDir) {
    1771           0 :     log_warn(LD_REND, "Found permanent credential but no ClientOnionAuthDir "
    1772             :              "configured. There is no file to be removed.");
    1773           0 :     goto end;
    1774             :   }
    1775             : 
    1776           1 :   file_list = tor_listdir(options->ClientOnionAuthDir);
    1777           1 :   if (file_list == NULL) {
    1778           0 :     log_warn(LD_REND, "Client authorization key directory %s can't be listed.",
    1779             :              options->ClientOnionAuthDir);
    1780           0 :     goto end;
    1781             :   }
    1782             : 
    1783           1 :   SMARTLIST_FOREACH_BEGIN(file_list, const char *, filename) {
    1784           1 :     hs_client_service_authorization_t *tmp_cred = NULL;
    1785             : 
    1786           1 :     tmp_cred = get_creds_from_client_auth_filename(filename, options);
    1787           1 :     if (!tmp_cred) {
    1788           0 :       continue;
    1789             :     }
    1790             : 
    1791             :     /* Find the right file for this credential */
    1792           1 :     if (!strcmp(tmp_cred->onion_address, cred->onion_address)) {
    1793             :       /* Found it! Remove the file! */
    1794           1 :       remove_client_auth_creds_file(filename);
    1795             :       /* cleanup and get out of here */
    1796           1 :       client_service_authorization_free(tmp_cred);
    1797           1 :       break;
    1798             :     }
    1799             : 
    1800           0 :     client_service_authorization_free(tmp_cred);
    1801           0 :   } SMARTLIST_FOREACH_END(filename);
    1802             : 
    1803           0 :  end:
    1804           1 :   if (file_list) {
    1805           2 :     SMARTLIST_FOREACH(file_list, char *, s, tor_free(s));
    1806           1 :     smartlist_free(file_list);
    1807             :   }
    1808           1 : }
    1809             : 
    1810             : /** Remove client auth credentials for the service <b>hs_address</b>. */
    1811             : hs_client_removal_auth_status_t
    1812           5 : hs_client_remove_auth_credentials(const char *hsaddress)
    1813             : {
    1814           5 :   ed25519_public_key_t service_identity_pk;
    1815             : 
    1816           5 :   if (!client_auths) {
    1817             :     return REMOVAL_SUCCESS_NOT_FOUND;
    1818             :   }
    1819             : 
    1820           5 :   if (hs_parse_address(hsaddress, &service_identity_pk, NULL, NULL) < 0) {
    1821             :     return REMOVAL_BAD_ADDRESS;
    1822             :   }
    1823             : 
    1824           5 :   hs_client_service_authorization_t *cred = NULL;
    1825           5 :   cred = digest256map_remove(client_auths, service_identity_pk.pubkey);
    1826             : 
    1827             :   /* digestmap_remove() returns the previously stored data if there were any */
    1828           5 :   if (cred) {
    1829           4 :     if (cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
    1830             :       /* These creds are stored on disk: remove the corresponding file. */
    1831           1 :       find_and_remove_client_auth_creds_file(cred);
    1832             :     }
    1833             : 
    1834             :     /* Remove associated descriptor if any. */
    1835           4 :     hs_cache_remove_as_client(&service_identity_pk);
    1836             : 
    1837           4 :     client_service_authorization_free(cred);
    1838           4 :     return REMOVAL_SUCCESS;
    1839             :   }
    1840             : 
    1841             :   return REMOVAL_SUCCESS_NOT_FOUND;
    1842             : }
    1843             : 
    1844             : /** Get the HS client auth map. */
    1845             : digest256map_t *
    1846          14 : get_hs_client_auths_map(void)
    1847             : {
    1848          14 :   return client_auths;
    1849             : }
    1850             : 
    1851             : /* ========== */
    1852             : /* Public API */
    1853             : /* ========== */
    1854             : 
    1855             : /** Called when a circuit was just cleaned up. This is done right before the
    1856             :  * circuit is marked for close. */
    1857             : void
    1858           5 : hs_client_circuit_cleanup_on_close(const circuit_t *circ)
    1859             : {
    1860           5 :   bool has_timed_out;
    1861             : 
    1862           5 :   tor_assert(circ);
    1863           5 :   tor_assert(CIRCUIT_IS_ORIGIN(circ));
    1864             : 
    1865           5 :   has_timed_out =
    1866           5 :     (circ->marked_for_close_orig_reason == END_CIRC_REASON_TIMEOUT);
    1867             : 
    1868           5 :   switch (circ->purpose) {
    1869           1 :   case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
    1870             :   case CIRCUIT_PURPOSE_C_REND_READY:
    1871             :   case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
    1872             :   case CIRCUIT_PURPOSE_C_REND_JOINED:
    1873             :     /* Report extended SOCKS error code when a rendezvous circuit times out.
    1874             :      * This MUST be done on_close() because it is possible the entry
    1875             :      * connection would get closed before the circuit is freed and thus
    1876             :      * would fail to report the error code. */
    1877           1 :     if (has_timed_out) {
    1878           1 :       socks_mark_rend_circuit_timed_out(CONST_TO_ORIGIN_CIRCUIT(circ));
    1879             :     }
    1880             :     break;
    1881             :   default:
    1882             :     break;
    1883             :   }
    1884           5 : }
    1885             : 
    1886             : /** Called when a circuit was just cleaned up. This is done right before the
    1887             :  * circuit is freed. */
    1888             : void
    1889           9 : hs_client_circuit_cleanup_on_free(const circuit_t *circ)
    1890             : {
    1891           9 :   bool has_timed_out;
    1892           9 :   rend_intro_point_failure_t failure = INTRO_POINT_FAILURE_GENERIC;
    1893           9 :   const origin_circuit_t *orig_circ = NULL;
    1894             : 
    1895           9 :   tor_assert(circ);
    1896           9 :   tor_assert(CIRCUIT_IS_ORIGIN(circ));
    1897             : 
    1898           9 :   orig_circ = CONST_TO_ORIGIN_CIRCUIT(circ);
    1899           9 :   tor_assert(orig_circ->hs_ident);
    1900             : 
    1901           9 :   has_timed_out =
    1902           9 :     (circ->marked_for_close_orig_reason == END_CIRC_REASON_TIMEOUT);
    1903           9 :   if (has_timed_out) {
    1904           3 :     failure = INTRO_POINT_FAILURE_TIMEOUT;
    1905             :   }
    1906             : 
    1907           9 :   switch (circ->purpose) {
    1908           1 :   case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
    1909           1 :     log_info(LD_REND, "Failed v3 intro circ for service %s to intro point %s "
    1910             :                       "(awaiting ACK). Failure code: %d",
    1911             :         safe_str_client(ed25519_fmt(&orig_circ->hs_ident->identity_pk)),
    1912             :         safe_str_client(build_state_get_exit_nickname(orig_circ->build_state)),
    1913             :         failure);
    1914           1 :     hs_cache_client_intro_state_note(&orig_circ->hs_ident->identity_pk,
    1915           1 :                                      &orig_circ->hs_ident->intro_auth_pk,
    1916             :                                      failure);
    1917           1 :     break;
    1918           5 :   case CIRCUIT_PURPOSE_C_INTRODUCING:
    1919           5 :     if (has_timed_out || !orig_circ->build_state) {
    1920             :       break;
    1921             :     }
    1922           1 :     failure = INTRO_POINT_FAILURE_UNREACHABLE;
    1923           1 :     log_info(LD_REND, "Failed v3 intro circ for service %s to intro point %s "
    1924             :                       "(while building circuit). Marking as unreachable.",
    1925             :        safe_str_client(ed25519_fmt(&orig_circ->hs_ident->identity_pk)),
    1926             :        safe_str_client(build_state_get_exit_nickname(orig_circ->build_state)));
    1927           1 :     hs_cache_client_intro_state_note(&orig_circ->hs_ident->identity_pk,
    1928           1 :                                      &orig_circ->hs_ident->intro_auth_pk,
    1929             :                                      failure);
    1930           1 :     break;
    1931             :   default:
    1932             :     break;
    1933             :   }
    1934           9 : }
    1935             : 
    1936             : /** A circuit just finished connecting to a hidden service that the stream
    1937             :  *  <b>conn</b> has been waiting for. Let the HS subsystem know about this. */
    1938             : void
    1939           1 : hs_client_note_connection_attempt_succeeded(const edge_connection_t *conn)
    1940             : {
    1941           1 :   tor_assert(connection_edge_is_rendezvous_stream(conn));
    1942             : 
    1943           1 :   if (conn->hs_ident) { /* It's v3: pass it to the prop224 handler */
    1944           1 :     note_connection_attempt_succeeded(conn->hs_ident);
    1945           1 :     return;
    1946             :   }
    1947             : }
    1948             : 
    1949             : /** With the given encoded descriptor in desc_str and the service key in
    1950             :  * service_identity_pk, decode the descriptor and set the desc pointer with a
    1951             :  * newly allocated descriptor object.
    1952             :  *
    1953             :  * On success, HS_DESC_DECODE_OK is returned and desc is set to the decoded
    1954             :  * descriptor. On error, desc is set to NULL and a decoding error status is
    1955             :  * returned depending on what was the issue. */
    1956             : hs_desc_decode_status_t
    1957          18 : hs_client_decode_descriptor(const char *desc_str,
    1958             :                             const ed25519_public_key_t *service_identity_pk,
    1959             :                             hs_descriptor_t **desc)
    1960             : {
    1961          18 :   hs_desc_decode_status_t ret;
    1962          18 :   hs_subcredential_t subcredential;
    1963          18 :   ed25519_public_key_t blinded_pubkey;
    1964          18 :   hs_client_service_authorization_t *client_auth = NULL;
    1965          18 :   curve25519_secret_key_t *client_auth_sk = NULL;
    1966             : 
    1967          18 :   tor_assert(desc_str);
    1968          18 :   tor_assert(service_identity_pk);
    1969          18 :   tor_assert(desc);
    1970             : 
    1971             :   /* Check if we have a client authorization for this service in the map. */
    1972          18 :   client_auth = find_client_auth(service_identity_pk);
    1973          18 :   if (client_auth) {
    1974           3 :     client_auth_sk = &client_auth->enc_seckey;
    1975             :   }
    1976             : 
    1977             :   /* Create subcredential for this HS so that we can decrypt */
    1978             :   {
    1979          18 :     uint64_t current_time_period = hs_get_time_period_num(0);
    1980          18 :     hs_build_blinded_pubkey(service_identity_pk, NULL, 0, current_time_period,
    1981             :                             &blinded_pubkey);
    1982          18 :     hs_get_subcredential(service_identity_pk, &blinded_pubkey, &subcredential);
    1983             :   }
    1984             : 
    1985             :   /* Parse descriptor */
    1986          18 :   ret = hs_desc_decode_descriptor(desc_str, &subcredential,
    1987             :                                   client_auth_sk, desc);
    1988          18 :   memwipe(&subcredential, 0, sizeof(subcredential));
    1989          18 :   if (ret != HS_DESC_DECODE_OK) {
    1990           7 :     goto err;
    1991             :   }
    1992             : 
    1993             :   /* Make sure the descriptor signing key cross certifies with the computed
    1994             :    * blinded key. Without this validation, anyone knowing the subcredential
    1995             :    * and onion address can forge a descriptor. */
    1996          11 :   tor_cert_t *cert = (*desc)->plaintext_data.signing_key_cert;
    1997          11 :   if (tor_cert_checksig(cert,
    1998             :                         &blinded_pubkey, approx_time()) < 0) {
    1999           0 :     log_warn(LD_GENERAL, "Descriptor signing key certificate signature "
    2000             :              "doesn't validate with computed blinded key: %s",
    2001             :              tor_cert_describe_signature_status(cert));
    2002           0 :     ret = HS_DESC_DECODE_GENERIC_ERROR;
    2003           0 :     goto err;
    2004             :   }
    2005             : 
    2006             :   return HS_DESC_DECODE_OK;
    2007             :  err:
    2008             :   return ret;
    2009             : }
    2010             : 
    2011             : /** Return true iff there are at least one usable intro point in the service
    2012             :  * descriptor desc. */
    2013             : int
    2014          71 : hs_client_any_intro_points_usable(const ed25519_public_key_t *service_pk,
    2015             :                                   const hs_descriptor_t *desc)
    2016             : {
    2017          71 :   tor_assert(service_pk);
    2018          71 :   tor_assert(desc);
    2019             : 
    2020          91 :   SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points,
    2021             :                           const hs_desc_intro_point_t *, ip) {
    2022          86 :     if (intro_point_is_usable(service_pk, ip)) {
    2023          66 :       goto usable;
    2024             :     }
    2025          20 :   } SMARTLIST_FOREACH_END(ip);
    2026             : 
    2027             :   return 0;
    2028          66 :  usable:
    2029          66 :   return 1;
    2030             : }
    2031             : 
    2032             : /** Launch a connection to a hidden service directory to fetch a hidden
    2033             :  * service descriptor using <b>identity_pk</b> to get the necessary keys.
    2034             :  *
    2035             :  * A hs_client_fetch_status_t code is returned. */
    2036             : int
    2037           6 : hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk)
    2038             : {
    2039           6 :   hs_client_fetch_status_t status;
    2040             : 
    2041           6 :   tor_assert(identity_pk);
    2042             : 
    2043           6 :   if (!can_client_refetch_desc(identity_pk, &status)) {
    2044           5 :     return status;
    2045             :   }
    2046             : 
    2047             :   /* Try to fetch the desc and if we encounter an unrecoverable error, mark
    2048             :    * the desc as unavailable for now. */
    2049           1 :   status = fetch_v3_desc(identity_pk);
    2050           1 :   if (fetch_status_should_close_socks(status)) {
    2051           1 :     close_all_socks_conns_waiting_for_desc(identity_pk, status,
    2052             :                                            END_STREAM_REASON_RESOLVEFAILED);
    2053             :     /* Remove HSDir fetch attempts so that we can retry later if the user
    2054             :      * wants us to regardless of if we closed any connections. */
    2055           1 :     purge_hid_serv_request(identity_pk);
    2056             :   }
    2057             :   return status;
    2058             : }
    2059             : 
    2060             : /** This is called when we are trying to attach an AP connection to these
    2061             :  * hidden service circuits from connection_ap_handshake_attach_circuit().
    2062             :  * Return 0 on success, -1 for a transient error that is actions were
    2063             :  * triggered to recover or -2 for a permenent error where both circuits will
    2064             :  * marked for close.
    2065             :  *
    2066             :  * The following supports every hidden service version. */
    2067             : int
    2068           0 : hs_client_send_introduce1(origin_circuit_t *intro_circ,
    2069             :                           origin_circuit_t *rend_circ)
    2070             : {
    2071           0 :   return send_introduce1(intro_circ, rend_circ);
    2072             : }
    2073             : 
    2074             : /** Called when the client circuit circ has been established. It can be either
    2075             :  * an introduction or rendezvous circuit. This function handles all hidden
    2076             :  * service versions. */
    2077             : void
    2078           0 : hs_client_circuit_has_opened(origin_circuit_t *circ)
    2079             : {
    2080           0 :   tor_assert(circ);
    2081             : 
    2082           0 :   switch (TO_CIRCUIT(circ)->purpose) {
    2083           0 :   case CIRCUIT_PURPOSE_C_INTRODUCING:
    2084           0 :     if (circ->hs_ident) {
    2085           0 :       client_intro_circ_has_opened(circ);
    2086             :     }
    2087             :     break;
    2088           0 :   case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
    2089           0 :     if (circ->hs_ident) {
    2090           0 :       client_rendezvous_circ_has_opened(circ);
    2091             :     }
    2092             :     break;
    2093           0 :   default:
    2094           0 :     tor_assert_nonfatal_unreached();
    2095             :   }
    2096           0 : }
    2097             : 
    2098             : /** Called when we receive a RENDEZVOUS_ESTABLISHED cell. Change the state of
    2099             :  * the circuit to CIRCUIT_PURPOSE_C_REND_READY. Return 0 on success else a
    2100             :  * negative value and the circuit marked for close. */
    2101             : int
    2102           1 : hs_client_receive_rendezvous_acked(origin_circuit_t *circ,
    2103             :                                    const uint8_t *payload, size_t payload_len)
    2104             : {
    2105           1 :   tor_assert(circ);
    2106           1 :   tor_assert(payload);
    2107             : 
    2108           1 :   (void) payload_len;
    2109             : 
    2110           1 :   if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
    2111           0 :     log_warn(LD_PROTOCOL, "Got a RENDEZVOUS_ESTABLISHED but we were not "
    2112             :                           "expecting one. Closing circuit.");
    2113           0 :     goto err;
    2114             :   }
    2115             : 
    2116           1 :   log_info(LD_REND, "Received an RENDEZVOUS_ESTABLISHED. This circuit is "
    2117             :                     "now ready for rendezvous.");
    2118           1 :   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_REND_READY);
    2119             : 
    2120             :   /* Set timestamp_dirty, because circuit_expire_building expects it to
    2121             :    * specify when a circuit entered the _C_REND_READY state. */
    2122           1 :   TO_CIRCUIT(circ)->timestamp_dirty = time(NULL);
    2123             : 
    2124             :   /* From a path bias point of view, this circuit is now successfully used.
    2125             :    * Waiting any longer opens us up to attacks from malicious hidden services.
    2126             :    * They could induce the client to attempt to connect to their hidden
    2127             :    * service and never reply to the client's rend requests */
    2128           1 :   pathbias_mark_use_success(circ);
    2129             : 
    2130             :   /* If we already have the introduction circuit built, make sure we send
    2131             :    * the INTRODUCE cell _now_ */
    2132           1 :   connection_ap_attach_pending(1);
    2133             : 
    2134           1 :   return 0;
    2135           0 :  err:
    2136           0 :   circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
    2137           0 :   return -1;
    2138             : }
    2139             : 
    2140             : void
    2141          27 : client_service_authorization_free_(hs_client_service_authorization_t *auth)
    2142             : {
    2143          27 :   if (!auth) {
    2144             :     return;
    2145             :   }
    2146             : 
    2147          21 :   tor_free(auth->client_name);
    2148             : 
    2149          21 :   memwipe(auth, 0, sizeof(*auth));
    2150          21 :   tor_free(auth);
    2151             : }
    2152             : 
    2153             : /** Helper for digest256map_free. */
    2154             : static void
    2155           8 : client_service_authorization_free_void(void *auth)
    2156             : {
    2157           8 :   client_service_authorization_free_(auth);
    2158           8 : }
    2159             : 
    2160             : static void
    2161         289 : client_service_authorization_free_all(void)
    2162             : {
    2163         289 :   if (!client_auths) {
    2164             :     return;
    2165             :   }
    2166          11 :   digest256map_free(client_auths, client_service_authorization_free_void);
    2167             : }
    2168             : 
    2169             : /** Check if the auth key file name is valid or not. Return 1 if valid,
    2170             :  * otherwise return 0. */
    2171             : STATIC int
    2172          12 : auth_key_filename_is_valid(const char *filename)
    2173             : {
    2174          12 :   int ret = 1;
    2175          12 :   const char *valid_extension = ".auth_private";
    2176             : 
    2177          12 :   tor_assert(filename);
    2178             : 
    2179             :   /* The length of the filename must be greater than the length of the
    2180             :    * extension and the valid extension must be at the end of filename. */
    2181          12 :   if (!strcmpend(filename, valid_extension) &&
    2182           9 :       strlen(filename) != strlen(valid_extension)) {
    2183             :     ret = 1;
    2184             :   } else {
    2185           4 :     ret = 0;
    2186             :   }
    2187             : 
    2188          12 :   return ret;
    2189             : }
    2190             : 
    2191             : /** Parse the client auth credentials off a string in <b>client_key_str</b>
    2192             :  *  based on the file format documented in the "Client side configuration"
    2193             :  *  section of rend-spec-v3.txt.
    2194             :  *
    2195             :  *  Return NULL if there was an error, otherwise return a newly allocated
    2196             :  *  hs_client_service_authorization_t structure.
    2197             :  */
    2198             : STATIC hs_client_service_authorization_t *
    2199          13 : parse_auth_file_content(const char *client_key_str)
    2200             : {
    2201          13 :   char *onion_address = NULL;
    2202          13 :   char *auth_type = NULL;
    2203          13 :   char *key_type = NULL;
    2204          13 :   char *seckey_b32 = NULL;
    2205          13 :   hs_client_service_authorization_t *auth = NULL;
    2206          13 :   smartlist_t *fields = smartlist_new();
    2207             : 
    2208          13 :   tor_assert(client_key_str);
    2209             : 
    2210          13 :   smartlist_split_string(fields, client_key_str, ":",
    2211             :                          SPLIT_SKIP_SPACE, 0);
    2212             :   /* Wrong number of fields. */
    2213          13 :   if (smartlist_len(fields) != 4) {
    2214           1 :     goto err;
    2215             :   }
    2216             : 
    2217          12 :   onion_address = smartlist_get(fields, 0);
    2218          12 :   auth_type = smartlist_get(fields, 1);
    2219          12 :   key_type = smartlist_get(fields, 2);
    2220          12 :   seckey_b32 = smartlist_get(fields, 3);
    2221             : 
    2222             :   /* Currently, the only supported auth type is "descriptor" and the only
    2223             :    * supported key type is "x25519". */
    2224          12 :   if (strcmp(auth_type, "descriptor") || strcmp(key_type, "x25519")) {
    2225           2 :     goto err;
    2226             :   }
    2227             : 
    2228          10 :   if (strlen(seckey_b32) != BASE32_NOPAD_LEN(CURVE25519_SECKEY_LEN)) {
    2229           2 :     log_warn(LD_REND, "Client authorization encoded base32 private key "
    2230             :                       "length is invalid: %s", seckey_b32);
    2231           2 :     goto err;
    2232             :   }
    2233             : 
    2234           8 :   auth = tor_malloc_zero(sizeof(hs_client_service_authorization_t));
    2235           8 :   if (base32_decode((char *) auth->enc_seckey.secret_key,
    2236             :                     sizeof(auth->enc_seckey.secret_key),
    2237             :                     seckey_b32, strlen(seckey_b32)) !=
    2238             :       sizeof(auth->enc_seckey.secret_key)) {
    2239           0 :     log_warn(LD_REND, "Client authorization encoded base32 private key "
    2240             :                       "can't be decoded: %s", seckey_b32);
    2241           0 :     goto err;
    2242             :   }
    2243             : 
    2244           8 :   if (fast_mem_is_zero((const char*)auth->enc_seckey.secret_key,
    2245             :                        sizeof(auth->enc_seckey.secret_key))) {
    2246           1 :     log_warn(LD_REND, "Client authorization private key can't be all-zeroes");
    2247           1 :     goto err;
    2248             :   }
    2249             : 
    2250           7 :   strncpy(auth->onion_address, onion_address, HS_SERVICE_ADDR_LEN_BASE32);
    2251             : 
    2252             :   /* We are reading this from the disk, so set the permanent flag anyway. */
    2253           7 :   auth->flags |= CLIENT_AUTH_FLAG_IS_PERMANENT;
    2254             : 
    2255             :   /* Success. */
    2256           7 :   goto done;
    2257             : 
    2258           6 :  err:
    2259           6 :   client_service_authorization_free(auth);
    2260          13 :  done:
    2261             :   /* It is also a good idea to wipe the private key. */
    2262          13 :   if (seckey_b32) {
    2263          12 :     memwipe(seckey_b32, 0, strlen(seckey_b32));
    2264             :   }
    2265          13 :   tor_assert(fields);
    2266          63 :   SMARTLIST_FOREACH(fields, char *, s, tor_free(s));
    2267          13 :   smartlist_free(fields);
    2268          13 :   return auth;
    2269             : }
    2270             : 
    2271             : /** From a set of <b>options</b>, setup every client authorization detail
    2272             :  * found. Return 0 on success or -1 on failure. If <b>validate_only</b>
    2273             :  * is set, parse, warn and return as normal, but don't actually change
    2274             :  * the configuration. */
    2275             : int
    2276         436 : hs_config_client_authorization(const or_options_t *options,
    2277             :                                int validate_only)
    2278             : {
    2279         436 :   int ret = -1;
    2280         436 :   digest256map_t *auths = digest256map_new();
    2281         436 :   smartlist_t *file_list = NULL;
    2282             : 
    2283         436 :   tor_assert(options);
    2284             : 
    2285             :   /* There is no client auth configured. We can just silently ignore this
    2286             :    * function. */
    2287         436 :   if (!options->ClientOnionAuthDir) {
    2288         433 :     ret = 0;
    2289         433 :     goto end;
    2290             :   }
    2291             : 
    2292             :   /* Make sure the directory exists and is private enough. */
    2293           3 :   if (check_private_dir(options->ClientOnionAuthDir, 0, options->User) < 0) {
    2294           0 :     goto end;
    2295             :   }
    2296             : 
    2297           3 :   file_list = tor_listdir(options->ClientOnionAuthDir);
    2298           3 :   if (file_list == NULL) {
    2299           0 :     log_warn(LD_REND, "Client authorization key directory %s can't be listed.",
    2300             :              options->ClientOnionAuthDir);
    2301           0 :     goto end;
    2302             :   }
    2303             : 
    2304          10 :   SMARTLIST_FOREACH_BEGIN(file_list, const char *, filename) {
    2305           7 :     hs_client_service_authorization_t *auth = NULL;
    2306           7 :     ed25519_public_key_t identity_pk;
    2307             : 
    2308           7 :     auth = get_creds_from_client_auth_filename(filename, options);
    2309           7 :     if (!auth) {
    2310           2 :       continue;
    2311             :     }
    2312             : 
    2313             :     /* Parse the onion address to get an identity public key and use it
    2314             :      * as a key of global map in the future. */
    2315           5 :     if (hs_parse_address(auth->onion_address, &identity_pk,
    2316             :                          NULL, NULL) < 0) {
    2317           0 :       log_warn(LD_REND, "The onion address \"%s\" is invalid in "
    2318             :                "file %s", filename, auth->onion_address);
    2319           0 :       client_service_authorization_free(auth);
    2320           0 :       continue;
    2321             :     }
    2322             : 
    2323           5 :     if (digest256map_get(auths, identity_pk.pubkey)) {
    2324           0 :         log_warn(LD_REND, "Duplicate authorization for the same hidden "
    2325             :                  "service address %s.",
    2326             :                  safe_str_client_opts(options, auth->onion_address));
    2327           0 :         client_service_authorization_free(auth);
    2328           0 :         goto end;
    2329             :     }
    2330             : 
    2331           5 :     digest256map_set(auths, identity_pk.pubkey, auth);
    2332           5 :     log_info(LD_REND, "Loaded a client authorization key file %s.",
    2333             :              filename);
    2334           7 :   } SMARTLIST_FOREACH_END(filename);
    2335             : 
    2336             :   /* Success. */
    2337             :   ret = 0;
    2338             : 
    2339           3 :  end:
    2340         436 :   if (file_list) {
    2341          10 :     SMARTLIST_FOREACH(file_list, char *, s, tor_free(s));
    2342           3 :     smartlist_free(file_list);
    2343             :   }
    2344             : 
    2345         436 :   if (!validate_only && ret == 0) {
    2346           7 :     client_service_authorization_free_all();
    2347           7 :     client_auths = auths;
    2348             :   } else {
    2349         429 :     digest256map_free(auths, client_service_authorization_free_void);
    2350             :   }
    2351             : 
    2352         436 :   return ret;
    2353             : }
    2354             : 
    2355             : /** Called when a descriptor directory fetch is done.
    2356             :  *
    2357             :  * Act accordingly on all entry connections depending on the HTTP status code
    2358             :  * we got. In case of an error, the SOCKS error is set (if ExtendedErrors is
    2359             :  * set).
    2360             :  *
    2361             :  * The reason is a human readable string returned by the directory server
    2362             :  * which can describe the status of the request. The body is the response
    2363             :  * content, on 200 code it is the descriptor itself. Finally, the status_code
    2364             :  * is the HTTP code returned by the directory server. */
    2365             : void
    2366           6 : hs_client_dir_fetch_done(dir_connection_t *dir_conn, const char *reason,
    2367             :                          const char *body, const int status_code)
    2368             : {
    2369           6 :   smartlist_t *entry_conns;
    2370             : 
    2371           6 :   tor_assert(dir_conn);
    2372           6 :   tor_assert(body);
    2373             : 
    2374             :   /* Get all related entry connections. */
    2375           6 :   entry_conns = find_entry_conns(&dir_conn->hs_ident->identity_pk);
    2376             : 
    2377           6 :   switch (status_code) {
    2378           6 :   case 200:
    2379           6 :     client_dir_fetch_200(dir_conn, entry_conns, body);
    2380           6 :     break;
    2381           0 :   case 404:
    2382           0 :     client_dir_fetch_404(dir_conn, entry_conns);
    2383           0 :     break;
    2384           0 :   case 400:
    2385           0 :     client_dir_fetch_400(dir_conn, reason);
    2386           0 :     break;
    2387           0 :   default:
    2388           0 :     client_dir_fetch_unexpected(dir_conn, reason, status_code);
    2389           0 :     break;
    2390             :   }
    2391             : 
    2392             :   /* We don't have ownership of the objects in this list. */
    2393           6 :   smartlist_free(entry_conns);
    2394           6 : }
    2395             : 
    2396             : /** Return a newly allocated extend_info_t for a randomly chosen introduction
    2397             :  * point for the given edge connection identifier ident. Return NULL if we
    2398             :  * can't pick any usable introduction points. */
    2399             : extend_info_t *
    2400           0 : hs_client_get_random_intro_from_edge(const edge_connection_t *edge_conn)
    2401             : {
    2402           0 :   tor_assert(edge_conn);
    2403             : 
    2404           0 :   return client_get_random_intro(&edge_conn->hs_ident->identity_pk);
    2405             : }
    2406             : 
    2407             : /** Called when get an INTRODUCE_ACK cell on the introduction circuit circ.
    2408             :  * Return 0 on success else a negative value is returned. The circuit will be
    2409             :  * closed or reuse to extend again to another intro point. */
    2410             : int
    2411           0 : hs_client_receive_introduce_ack(origin_circuit_t *circ,
    2412             :                                 const uint8_t *payload, size_t payload_len)
    2413             : {
    2414           0 :   int ret = -1;
    2415             : 
    2416           0 :   tor_assert(circ);
    2417           0 :   tor_assert(payload);
    2418             : 
    2419           0 :   if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
    2420           0 :     log_warn(LD_PROTOCOL, "Unexpected INTRODUCE_ACK on circuit %u.",
    2421             :              (unsigned int) TO_CIRCUIT(circ)->n_circ_id);
    2422           0 :     circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
    2423           0 :     goto end;
    2424             :   }
    2425             : 
    2426           0 :   ret = handle_introduce_ack(circ, payload, payload_len);
    2427             :   /* For path bias: This circuit was used successfully. NACK or ACK counts. */
    2428           0 :   pathbias_mark_use_success(circ);
    2429             : 
    2430           0 :  end:
    2431           0 :   return ret;
    2432             : }
    2433             : 
    2434             : /** Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ.  Return
    2435             :  * 0 on success else a negative value is returned. The circuit will be closed
    2436             :  * on error. */
    2437             : int
    2438           0 : hs_client_receive_rendezvous2(origin_circuit_t *circ,
    2439             :                               const uint8_t *payload, size_t payload_len)
    2440             : {
    2441           0 :   int ret = -1;
    2442             : 
    2443           0 :   tor_assert(circ);
    2444           0 :   tor_assert(payload);
    2445             : 
    2446             :   /* Circuit can possibly be in both state because we could receive a
    2447             :    * RENDEZVOUS2 cell before the INTRODUCE_ACK has been received. */
    2448           0 :   if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
    2449             :       TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
    2450           0 :     log_warn(LD_PROTOCOL, "Unexpected RENDEZVOUS2 cell on circuit %u. "
    2451             :                           "Closing circuit.",
    2452             :              (unsigned int) TO_CIRCUIT(circ)->n_circ_id);
    2453           0 :     circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
    2454           0 :     goto end;
    2455             :   }
    2456             : 
    2457           0 :   log_info(LD_REND, "Got RENDEZVOUS2 cell from hidden service on circuit %u.",
    2458             :            TO_CIRCUIT(circ)->n_circ_id);
    2459             : 
    2460           0 :   ret = handle_rendezvous2(circ, payload, payload_len);
    2461             : 
    2462           0 :  end:
    2463           0 :   return ret;
    2464             : }
    2465             : 
    2466             : /** Extend the introduction circuit circ to another valid introduction point
    2467             :  * for the hidden service it is trying to connect to, or mark it and launch a
    2468             :  * new circuit if we can't extend it.  Return 0 on success or possible
    2469             :  * success. Return -1 and mark the introduction circuit for close on permanent
    2470             :  * failure.
    2471             :  *
    2472             :  * On failure, the caller is responsible for marking the associated rendezvous
    2473             :  * circuit for close. */
    2474             : int
    2475           0 : hs_client_reextend_intro_circuit(origin_circuit_t *circ)
    2476             : {
    2477           0 :   int ret = -1;
    2478           0 :   extend_info_t *ei;
    2479             : 
    2480           0 :   tor_assert(circ);
    2481             : 
    2482           0 :   ei = client_get_random_intro(&circ->hs_ident->identity_pk);
    2483           0 :   if (ei == NULL) {
    2484           0 :     log_warn(LD_REND, "No usable introduction points left. Closing.");
    2485           0 :     circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
    2486           0 :     goto end;
    2487             :   }
    2488             : 
    2489           0 :   if (circ->remaining_relay_early_cells) {
    2490           0 :     log_info(LD_REND, "Re-extending circ %u, this time to %s.",
    2491             :              (unsigned int) TO_CIRCUIT(circ)->n_circ_id,
    2492             :              safe_str_client(extend_info_describe(ei)));
    2493           0 :     ret = circuit_extend_to_new_exit(circ, ei);
    2494           0 :     if (ret == 0) {
    2495             :       /* We were able to extend so update the timestamp so we avoid expiring
    2496             :        * this circuit too early. The intro circuit is short live so the
    2497             :        * linkability issue is minimized, we just need the circuit to hold a
    2498             :        * bit longer so we can introduce. */
    2499           0 :       TO_CIRCUIT(circ)->timestamp_dirty = time(NULL);
    2500             :     }
    2501             :   } else {
    2502           0 :     log_info(LD_REND, "Closing intro circ %u (out of RELAY_EARLY cells).",
    2503             :              (unsigned int) TO_CIRCUIT(circ)->n_circ_id);
    2504           0 :     circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
    2505             :     /* connection_ap_handshake_attach_circuit will launch a new intro circ. */
    2506           0 :     ret = 0;
    2507             :   }
    2508             : 
    2509           0 :  end:
    2510           0 :   extend_info_free(ei);
    2511           0 :   return ret;
    2512             : }
    2513             : 
    2514             : /** Close all client introduction circuits related to the given descriptor.
    2515             :  * This is called with a descriptor that is about to get replaced in the
    2516             :  * client cache.
    2517             :  *
    2518             :  * Even though the introduction point might be exactly the same, we'll rebuild
    2519             :  * them if needed but the odds are very low that an existing matching
    2520             :  * introduction circuit exists at that stage. */
    2521             : void
    2522           4 : hs_client_close_intro_circuits_from_desc(const hs_descriptor_t *desc)
    2523             : {
    2524           4 :   origin_circuit_t *ocirc = NULL;
    2525             : 
    2526           4 :   tor_assert(desc);
    2527             : 
    2528             :   /* We iterate over all client intro circuits because they aren't kept in the
    2529             :    * HS circuitmap. That is probably something we want to do one day. */
    2530           6 :   while ((ocirc = circuit_get_next_intro_circ(ocirc, true))) {
    2531           2 :     if (ocirc->hs_ident == NULL) {
    2532             :       /* Not a v3 circuit, ignore it. */
    2533           0 :       continue;
    2534             :     }
    2535             : 
    2536             :     /* Does it match any IP in the given descriptor? If not, ignore. */
    2537           2 :     if (find_desc_intro_point_by_ident(ocirc->hs_ident, desc) == NULL) {
    2538           0 :       continue;
    2539             :     }
    2540             : 
    2541             :     /* We have a match. Close the circuit as consider it expired. */
    2542           2 :     circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
    2543             :   }
    2544           4 : }
    2545             : 
    2546             : /** Release all the storage held by the client subsystem. */
    2547             : void
    2548         282 : hs_client_free_all(void)
    2549             : {
    2550             :   /* Purge the hidden service request cache. */
    2551         282 :   hs_purge_last_hid_serv_requests();
    2552         282 :   client_service_authorization_free_all();
    2553         282 : }
    2554             : 
    2555             : /** Purge all potentially remotely-detectable state held in the hidden
    2556             :  * service client code. Called on SIGNAL NEWNYM. */
    2557             : void
    2558           0 : hs_client_purge_state(void)
    2559             : {
    2560             :   /* Cancel all descriptor fetches. Do this first so once done we are sure
    2561             :    * that our descriptor cache won't modified. */
    2562           0 :   cancel_descriptor_fetches();
    2563             :   /* Purge the introduction point state cache. */
    2564           0 :   hs_cache_client_intro_state_purge();
    2565             :   /* Purge the descriptor cache. */
    2566           0 :   hs_cache_purge_as_client();
    2567             :   /* Purge the last hidden service request cache. */
    2568           0 :   hs_purge_last_hid_serv_requests();
    2569             :   /* Purge ephemeral client authorization. */
    2570           0 :   purge_ephemeral_client_auth();
    2571             : 
    2572           0 :   log_info(LD_REND, "Hidden service client state has been purged.");
    2573           0 : }
    2574             : 
    2575             : /** Called when our directory information has changed. */
    2576             : void
    2577       45174 : hs_client_dir_info_changed(void)
    2578             : {
    2579             :   /* We have possibly reached the minimum directory information or new
    2580             :    * consensus so retry all pending SOCKS connection in
    2581             :    * AP_CONN_STATE_RENDDESC_WAIT state in order to fetch the descriptor. */
    2582       45174 :   retry_all_socks_conn_waiting_for_desc();
    2583       45174 : }
    2584             : 
    2585             : #ifdef TOR_UNIT_TESTS
    2586             : 
    2587             : STATIC void
    2588           1 : set_hs_client_auths_map(digest256map_t *map)
    2589             : {
    2590           1 :   client_auths = map;
    2591           1 : }
    2592             : 
    2593             : #endif /* defined(TOR_UNIT_TESTS) */

Generated by: LCOV version 1.14