tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

hs_circuit.c (63569B)


      1 /* Copyright (c) 2017-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /**
      5 * \file hs_circuit.c
      6 **/
      7 
      8 #define HS_CIRCUIT_PRIVATE
      9 
     10 #include "core/or/or.h"
     11 #include "app/config/config.h"
     12 #include "core/crypto/hs_ntor.h"
     13 #include "core/or/circuitbuild.h"
     14 #include "core/or/circuitlist.h"
     15 #include "core/or/circuituse.h"
     16 #include "core/or/policies.h"
     17 #include "core/or/relay.h"
     18 #include "core/or/crypt_path.h"
     19 #include "core/or/extendinfo.h"
     20 #include "core/or/congestion_control_common.h"
     21 #include "core/crypto/onion_crypto.h"
     22 #include "feature/client/circpathbias.h"
     23 #include "feature/hs/hs_cell.h"
     24 #include "feature/hs/hs_circuit.h"
     25 #include "feature/hs/hs_common.h"
     26 #include "feature/hs/hs_ob.h"
     27 #include "feature/hs/hs_circuitmap.h"
     28 #include "feature/hs/hs_client.h"
     29 #include "feature/hs/hs_ident.h"
     30 #include "feature/hs/hs_metrics.h"
     31 #include "feature/hs/hs_service.h"
     32 #include "feature/nodelist/describe.h"
     33 #include "feature/nodelist/nodelist.h"
     34 #include "feature/stats/rephist.h"
     35 #include "lib/crypt_ops/crypto_dh.h"
     36 #include "lib/crypt_ops/crypto_rand.h"
     37 #include "lib/crypt_ops/crypto_util.h"
     38 #include "lib/time/compat_time.h"
     39 
     40 /* Trunnel. */
     41 #include "trunnel/ed25519_cert.h"
     42 #include "trunnel/hs/cell_establish_intro.h"
     43 
     44 #include "core/or/congestion_control_st.h"
     45 #include "core/or/cpath_build_state_st.h"
     46 #include "core/or/crypt_path_st.h"
     47 #include "core/or/extend_info_st.h"
     48 #include "feature/nodelist/node_st.h"
     49 #include "core/or/origin_circuit_st.h"
     50 
     51 /** Helper: Free a pending rend object. */
     52 static inline void
     53 free_pending_rend(pending_rend_t *req)
     54 {
     55  if (!req) {
     56    return;
     57  }
     58  link_specifier_smartlist_free(req->rdv_data.link_specifiers);
     59  memwipe(req, 0, sizeof(pending_rend_t));
     60  tor_free(req);
     61 }
     62 
     63 /** A circuit is about to become an e2e rendezvous circuit. Check
     64 * <b>circ_purpose</b> and ensure that it's properly set. Return true iff
     65 * circuit purpose is properly set, otherwise return false. */
     66 static int
     67 circuit_purpose_is_correct_for_rend(unsigned int circ_purpose,
     68                                    int is_service_side)
     69 {
     70  if (is_service_side) {
     71    if (circ_purpose != CIRCUIT_PURPOSE_S_CONNECT_REND) {
     72      log_warn(LD_BUG,
     73            "HS e2e circuit setup with wrong purpose (%d)", circ_purpose);
     74      return 0;
     75    }
     76  }
     77 
     78  if (!is_service_side) {
     79    if (circ_purpose != CIRCUIT_PURPOSE_C_REND_READY &&
     80        circ_purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
     81      log_warn(LD_BUG,
     82            "Client e2e circuit setup with wrong purpose (%d)", circ_purpose);
     83      return 0;
     84    }
     85  }
     86 
     87  return 1;
     88 }
     89 
     90 /** Create and return a crypt path for the final hop of a v3 prop224 rendezvous
     91 * circuit. Initialize the crypt path crypto using the output material from the
     92 * ntor key exchange at <b>ntor_key_seed</b>.
     93 *
     94 * If <b>is_service_side</b> is set, we are the hidden service and the final
     95 * hop of the rendezvous circuit is the client on the other side. */
     96 static crypt_path_t *
     97 create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len,
     98                  int is_service_side)
     99 {
    100  uint8_t keys[HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN];
    101  crypt_path_t *cpath = NULL;
    102 
    103  /* Do the key expansion */
    104  if (hs_ntor_circuit_key_expansion(ntor_key_seed, seed_len,
    105                                    keys, sizeof(keys)) < 0) {
    106    goto err;
    107  }
    108 
    109  /* Setup the cpath */
    110  cpath = tor_malloc_zero(sizeof(crypt_path_t));
    111  cpath->magic = CRYPT_PATH_MAGIC;
    112 
    113  // TODO CGO: Pick relay cell format based on capabilities.
    114  cpath->relay_cell_format = RELAY_CELL_FORMAT_V0;
    115  relay_crypto_alg_t alg = is_service_side ? RELAY_CRYPTO_ALG_TOR1_HSS :
    116    RELAY_CRYPTO_ALG_TOR1_HSC;
    117 
    118  if (cpath_init_circuit_crypto(alg, cpath, (char*)keys, sizeof(keys)) < 0) {
    119    tor_free(cpath);
    120    goto err;
    121  }
    122 
    123 err:
    124  memwipe(keys, 0, sizeof(keys));
    125  return cpath;
    126 }
    127 
    128 /** Append the final <b>hop</b> to the cpath of the rend <b>circ</b>, and mark
    129 * <b>circ</b> ready for use to transfer HS relay cells. */
    130 static void
    131 finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop,
    132                      int is_service_side)
    133 {
    134  tor_assert(circ);
    135  tor_assert(hop);
    136 
    137  /* Notify the circuit state machine that we are splicing this circuit */
    138  int new_circ_purpose = is_service_side ?
    139    CIRCUIT_PURPOSE_S_REND_JOINED : CIRCUIT_PURPOSE_C_REND_JOINED;
    140  circuit_change_purpose(TO_CIRCUIT(circ), new_circ_purpose);
    141 
    142  /* All is well. Extend the circuit. */
    143  hop->state = CPATH_STATE_OPEN;
    144  /* Set the windows to default. */
    145  hop->package_window = circuit_initial_package_window();
    146  hop->deliver_window = CIRCWINDOW_START;
    147 
    148  /* If congestion control, transfer ccontrol onto the cpath. */
    149  if (TO_CIRCUIT(circ)->ccontrol) {
    150    hop->ccontrol = TO_CIRCUIT(circ)->ccontrol;
    151    TO_CIRCUIT(circ)->ccontrol = NULL;
    152  }
    153 
    154  /* Append the hop to the cpath of this circuit */
    155  cpath_extend_linked_list(&circ->cpath, hop);
    156 
    157  /* Finally, mark circuit as ready to be used for client streams */
    158  if (!is_service_side) {
    159    circuit_try_attaching_streams(circ);
    160  }
    161 }
    162 
    163 /** For a given circuit and a service introduction point object, register the
    164 * intro circuit to the circuitmap. */
    165 static void
    166 register_intro_circ(const hs_service_intro_point_t *ip,
    167                    origin_circuit_t *circ)
    168 {
    169  tor_assert(ip);
    170  tor_assert(circ);
    171 
    172  hs_circuitmap_register_intro_circ_v3_service_side(circ,
    173                                                    &ip->auth_key_kp.pubkey);
    174 }
    175 
    176 /** Return the number of opened introduction circuit for the given circuit that
    177 * is matching its identity key. */
    178 static unsigned int
    179 count_opened_desc_intro_point_circuits(const hs_service_t *service,
    180                                       const hs_service_descriptor_t *desc)
    181 {
    182  unsigned int count = 0;
    183 
    184  tor_assert(service);
    185  tor_assert(desc);
    186 
    187  DIGEST256MAP_FOREACH(desc->intro_points.map, key,
    188                       const hs_service_intro_point_t *, ip) {
    189    const circuit_t *circ;
    190    const origin_circuit_t *ocirc = hs_circ_service_get_intro_circ(ip);
    191    if (ocirc == NULL) {
    192      continue;
    193    }
    194    circ = TO_CIRCUIT(ocirc);
    195    tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
    196               circ->purpose == CIRCUIT_PURPOSE_S_INTRO);
    197    /* Having a circuit not for the requested service is really bad. */
    198    tor_assert(ed25519_pubkey_eq(&service->keys.identity_pk,
    199                                 &ocirc->hs_ident->identity_pk));
    200    /* Only count opened circuit and skip circuit that will be closed. */
    201    if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN) {
    202      count++;
    203    }
    204  } DIGEST256MAP_FOREACH_END;
    205  return count;
    206 }
    207 
    208 /** From a given service, rendezvous cookie and handshake info, create a
    209 * rendezvous point circuit identifier. This can't fail. */
    210 STATIC hs_ident_circuit_t *
    211 create_rp_circuit_identifier(const hs_service_t *service,
    212                             const uint8_t *rendezvous_cookie,
    213                             const curve25519_public_key_t *server_pk,
    214                             const hs_ntor_rend_cell_keys_t *keys)
    215 {
    216  hs_ident_circuit_t *ident;
    217  uint8_t handshake_info[CURVE25519_PUBKEY_LEN + DIGEST256_LEN];
    218 
    219  tor_assert(service);
    220  tor_assert(rendezvous_cookie);
    221  tor_assert(server_pk);
    222  tor_assert(keys);
    223 
    224  ident = hs_ident_circuit_new(&service->keys.identity_pk);
    225  /* Copy the RENDEZVOUS_COOKIE which is the unique identifier. */
    226  memcpy(ident->rendezvous_cookie, rendezvous_cookie,
    227         sizeof(ident->rendezvous_cookie));
    228  /* Build the HANDSHAKE_INFO which looks like this:
    229   *    SERVER_PK        [32 bytes]
    230   *    AUTH_INPUT_MAC   [32 bytes]
    231   */
    232  memcpy(handshake_info, server_pk->public_key, CURVE25519_PUBKEY_LEN);
    233  memcpy(handshake_info + CURVE25519_PUBKEY_LEN, keys->rend_cell_auth_mac,
    234         DIGEST256_LEN);
    235  tor_assert(sizeof(ident->rendezvous_handshake_info) ==
    236             sizeof(handshake_info));
    237  memcpy(ident->rendezvous_handshake_info, handshake_info,
    238         sizeof(ident->rendezvous_handshake_info));
    239  /* Finally copy the NTOR_KEY_SEED for e2e encryption on the circuit. */
    240  tor_assert(sizeof(ident->rendezvous_ntor_key_seed) ==
    241             sizeof(keys->ntor_key_seed));
    242  memcpy(ident->rendezvous_ntor_key_seed, keys->ntor_key_seed,
    243         sizeof(ident->rendezvous_ntor_key_seed));
    244  return ident;
    245 }
    246 
    247 /** From a given service and service intro point, create an introduction point
    248 * circuit identifier. This can't fail. */
    249 static hs_ident_circuit_t *
    250 create_intro_circuit_identifier(const hs_service_t *service,
    251                                const hs_service_intro_point_t *ip)
    252 {
    253  hs_ident_circuit_t *ident;
    254 
    255  tor_assert(service);
    256  tor_assert(ip);
    257 
    258  ident = hs_ident_circuit_new(&service->keys.identity_pk);
    259  ed25519_pubkey_copy(&ident->intro_auth_pk, &ip->auth_key_kp.pubkey);
    260  tor_assert_nonfatal(!ed25519_public_key_is_zero(&ident->intro_auth_pk));
    261 
    262  return ident;
    263 }
    264 
    265 /** For a given introduction point and an introduction circuit, send the
    266 * ESTABLISH_INTRO cell. The service object is used for logging. This can fail
    267 * and if so, the circuit is closed and the intro point object is flagged
    268 * that the circuit is not established anymore which is important for the
    269 * retry mechanism. */
    270 static void
    271 send_establish_intro(const hs_service_t *service,
    272                     hs_service_intro_point_t *ip, origin_circuit_t *circ)
    273 {
    274  ssize_t cell_len;
    275  uint8_t payload[RELAY_PAYLOAD_SIZE_MAX];
    276 
    277  tor_assert(service);
    278  tor_assert(ip);
    279  tor_assert(circ);
    280 
    281  /* Encode establish intro cell. */
    282  cell_len = hs_cell_build_establish_intro(circ->cpath->prev->rend_circ_nonce,
    283                                           &service->config, ip, payload);
    284  if (cell_len < 0) {
    285    log_warn(LD_REND, "Unable to encode ESTABLISH_INTRO cell for service %s "
    286                      "on circuit %u. Closing circuit.",
    287             safe_str_client(service->onion_address),
    288             TO_CIRCUIT(circ)->n_circ_id);
    289    goto err;
    290  }
    291 
    292  /* Send the cell on the circuit. */
    293  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
    294                                   RELAY_COMMAND_ESTABLISH_INTRO,
    295                                   (char *) payload, cell_len,
    296                                   circ->cpath->prev) < 0) {
    297    log_info(LD_REND, "Unable to send ESTABLISH_INTRO cell for service %s "
    298                      "on circuit %u.",
    299             safe_str_client(service->onion_address),
    300             TO_CIRCUIT(circ)->n_circ_id);
    301    /* On error, the circuit has been closed. */
    302    goto done;
    303  }
    304 
    305  /* Record the attempt to use this circuit. */
    306  pathbias_count_use_attempt(circ);
    307  goto done;
    308 
    309 err:
    310  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
    311 done:
    312  memwipe(payload, 0, sizeof(payload));
    313 }
    314 
    315 /** Return a string constant describing the anonymity of service. */
    316 static const char *
    317 get_service_anonymity_string(const hs_service_t *service)
    318 {
    319  if (service->config.is_single_onion) {
    320    return "single onion";
    321  } else {
    322    return "hidden";
    323  }
    324 }
    325 
    326 /** For a given service, the ntor onion key and a rendezvous cookie, launch a
    327 * circuit to the rendezvous point specified by the link specifiers. On
    328 * success, a circuit identifier is attached to the circuit with the needed
    329 * data. This function will try to open a circuit for a maximum value of
    330 * MAX_REND_FAILURES then it will give up. */
    331 MOCK_IMPL(STATIC void,
    332 launch_rendezvous_point_circuit,(const hs_service_t *service,
    333                                 const ed25519_public_key_t *ip_auth_pubkey,
    334                                 const curve25519_keypair_t *ip_enc_key_kp,
    335                                 const hs_cell_intro_rdv_data_t *rdv_data,
    336                                 time_t now))
    337 {
    338  int circ_needs_uptime;
    339  extend_info_t *info = NULL;
    340  origin_circuit_t *circ;
    341 
    342  tor_assert(service);
    343  tor_assert(ip_auth_pubkey);
    344  tor_assert(ip_enc_key_kp);
    345  tor_assert(rdv_data);
    346 
    347  circ_needs_uptime = hs_service_requires_uptime_circ(service->config.ports);
    348 
    349  /* Get the extend info data structure for the chosen rendezvous point
    350   * specified by the given link specifiers. */
    351  info = hs_get_extend_info_from_lspecs(rdv_data->link_specifiers,
    352                                        &rdv_data->onion_pk,
    353                                        service->config.is_single_onion);
    354  if (info == NULL) {
    355    /* We are done here, we can't extend to the rendezvous point. */
    356    log_fn(LOG_PROTOCOL_WARN, LD_REND,
    357           "Not enough info to open a circuit to a rendezvous point for "
    358           "%s service %s.",
    359           get_service_anonymity_string(service),
    360           safe_str_client(service->onion_address));
    361    goto end;
    362  }
    363 
    364  for (int i = 0; i < MAX_REND_FAILURES; i++) {
    365    int circ_flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL;
    366    if (circ_needs_uptime) {
    367      circ_flags |= CIRCLAUNCH_NEED_UPTIME;
    368    }
    369    /* Firewall and policies are checked when getting the extend info.
    370     *
    371     * We only use a one-hop path on the first attempt. If the first attempt
    372     * fails, we use a 3-hop path for reachability / reliability.
    373     * See the comment in retry_service_rendezvous_point() for details. */
    374    if (service->config.is_single_onion && i == 0) {
    375      circ_flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
    376    }
    377 
    378    circ = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND, info,
    379                                         circ_flags);
    380    if (circ != NULL) {
    381      /* Stop retrying, we have a circuit! */
    382      break;
    383    }
    384  }
    385  if (circ == NULL) {
    386    log_warn(LD_REND, "Giving up on launching a rendezvous circuit to %s "
    387                      "for %s service %s",
    388             safe_str_client(extend_info_describe(info)),
    389             get_service_anonymity_string(service),
    390             safe_str_client(service->onion_address));
    391    goto end;
    392  }
    393  /* Update metrics with this new rendezvous circuit launched. */
    394  hs_metrics_new_rdv(&service->keys.identity_pk);
    395 
    396  log_info(LD_REND, "Rendezvous circuit launched to %s with cookie %s "
    397                    "for %s service %s",
    398           safe_str_client(extend_info_describe(info)),
    399           safe_str_client(hex_str((const char *)
    400                                   rdv_data->rendezvous_cookie,
    401                                   REND_COOKIE_LEN)),
    402           get_service_anonymity_string(service),
    403           safe_str_client(service->onion_address));
    404  tor_assert(circ->build_state);
    405  /* Rendezvous circuit have a specific timeout for the time spent on trying
    406   * to connect to the rendezvous point. */
    407  circ->build_state->expiry_time = now + MAX_REND_TIMEOUT;
    408 
    409  /* Create circuit identifier and key material. */
    410  {
    411    hs_ntor_rend_cell_keys_t keys;
    412    curve25519_keypair_t ephemeral_kp;
    413    /* No need for extra strong, this is only for this circuit life time. This
    414     * key will be used for the RENDEZVOUS1 cell that will be sent on the
    415     * circuit once opened. */
    416    curve25519_keypair_generate(&ephemeral_kp, 0);
    417    if (hs_ntor_service_get_rendezvous1_keys(ip_auth_pubkey,
    418                                             ip_enc_key_kp,
    419                                             &ephemeral_kp,
    420                                             &rdv_data->client_pk,
    421                                             &keys) < 0) {
    422      /* This should not really happened but just in case, don't make tor
    423       * freak out, close the circuit and move on. */
    424      log_info(LD_REND, "Unable to get RENDEZVOUS1 key material for "
    425                        "service %s",
    426               safe_str_client(service->onion_address));
    427      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
    428      goto end;
    429    }
    430    circ->hs_ident = create_rp_circuit_identifier(service,
    431                                       rdv_data->rendezvous_cookie,
    432                                       &ephemeral_kp.pubkey, &keys);
    433    memwipe(&ephemeral_kp, 0, sizeof(ephemeral_kp));
    434    memwipe(&keys, 0, sizeof(keys));
    435    tor_assert(circ->hs_ident);
    436  }
    437 
    438  /* Remember PoW state if this introduction included a valid proof of work
    439   * client puzzle extension. */
    440  if (rdv_data->pow_effort > 0) {
    441    circ->hs_pow_effort = rdv_data->pow_effort;
    442    circ->hs_with_pow_circ = 1;
    443  }
    444 
    445  /* Setup congestion control if asked by the client from the INTRO cell. */
    446  if (rdv_data->cc_enabled) {
    447    hs_circ_setup_congestion_control(circ, congestion_control_sendme_inc(),
    448                                     service->config.is_single_onion);
    449  }
    450 
    451 end:
    452  extend_info_free(info);
    453 }
    454 
    455 /** Return true iff the given service rendezvous circuit circ is allowed for a
    456 * relaunch to the rendezvous point. */
    457 static int
    458 can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
    459 {
    460  tor_assert(circ);
    461  /* This is initialized when allocating an origin circuit. */
    462  tor_assert(circ->build_state);
    463  tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
    464 
    465  /* XXX: Retrying under certain condition. This is related to #22455. */
    466 
    467  /* We check failure_count >= hs_get_service_max_rend_failures()-1 below, and
    468   * the -1 is because we increment the failure count for our current failure
    469   * *after* this clause. */
    470  int max_rend_failures = hs_get_service_max_rend_failures() - 1;
    471 
    472  /* A failure count that has reached maximum allowed or circuit that expired,
    473   * we skip relaunching. */
    474  if (circ->build_state->failure_count > max_rend_failures ||
    475      circ->build_state->expiry_time <= time(NULL)) {
    476    log_info(LD_REND, "Attempt to build a rendezvous circuit to %s has "
    477                      "failed with %d attempts and expiry time %ld. "
    478                      "Giving up building.",
    479             safe_str_client(
    480                  extend_info_describe(circ->build_state->chosen_exit)),
    481             circ->build_state->failure_count,
    482             (long int) circ->build_state->expiry_time);
    483    goto disallow;
    484  }
    485 
    486  /* Allowed to relaunch. */
    487  return 1;
    488 disallow:
    489  return 0;
    490 }
    491 
    492 /** Retry the rendezvous point of circ by launching a new circuit to it. */
    493 static void
    494 retry_service_rendezvous_point(const origin_circuit_t *circ)
    495 {
    496  int flags = 0;
    497  origin_circuit_t *new_circ;
    498  cpath_build_state_t *bstate;
    499 
    500  tor_assert(circ);
    501  /* This is initialized when allocating an origin circuit. */
    502  tor_assert(circ->build_state);
    503  tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
    504 
    505  /* Ease our life. */
    506  bstate = circ->build_state;
    507 
    508  log_info(LD_REND, "Retrying rendezvous point circuit to %s",
    509           safe_str_client(extend_info_describe(bstate->chosen_exit)));
    510 
    511  /* Get the current build state flags for the next circuit. */
    512  flags |= (bstate->need_uptime) ? CIRCLAUNCH_NEED_UPTIME : 0;
    513  flags |= (bstate->need_capacity) ? CIRCLAUNCH_NEED_CAPACITY : 0;
    514  flags |= (bstate->is_internal) ? CIRCLAUNCH_IS_INTERNAL : 0;
    515 
    516  /* We do NOT add the onehop tunnel flag even though it might be a single
    517   * onion service. The reason is that if we failed once to connect to the RP
    518   * with a direct connection, we consider that chances are that we will fail
    519   * again so try a 3-hop circuit and hope for the best. Because the service
    520   * has no anonymity (single onion), this change of behavior won't affect
    521   * security directly. */
    522 
    523  new_circ = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
    524                                           bstate->chosen_exit, flags);
    525  if (new_circ == NULL) {
    526    log_warn(LD_REND, "Failed to launch rendezvous circuit to %s",
    527             safe_str_client(extend_info_describe(bstate->chosen_exit)));
    528 
    529    hs_metrics_failed_rdv(&circ->hs_ident->identity_pk,
    530                          HS_METRICS_ERR_RDV_RETRY);
    531 
    532    goto done;
    533  }
    534 
    535  /* Transfer build state information to the new circuit state in part to
    536   * catch any other failures. */
    537  new_circ->build_state->failure_count = bstate->failure_count+1;
    538  new_circ->build_state->expiry_time = bstate->expiry_time;
    539  new_circ->hs_ident = hs_ident_circuit_dup(circ->hs_ident);
    540 
    541  /* Setup congestion control if asked by the client from the INTRO cell. */
    542  if (TO_CIRCUIT(circ)->ccontrol) {
    543    /* As per above, in this case, we are a full 3 hop rend, even if we're a
    544     * single-onion service. */
    545    hs_circ_setup_congestion_control(new_circ,
    546                                     TO_CIRCUIT(circ)->ccontrol->sendme_inc,
    547                                     false);
    548  }
    549 
    550 done:
    551  return;
    552 }
    553 
    554 /** Using the given descriptor intro point ip, the node of the
    555 * rendezvous point rp_node and the service's subcredential, populate the
    556 * already allocated intro1_data object with the needed key material and link
    557 * specifiers.
    558 *
    559 * Return 0 on success or a negative value if we couldn't properly filled the
    560 * introduce1 data from the RP node. In other word, it means the RP node is
    561 * unusable to use in the introduction. */
    562 static int
    563 setup_introduce1_data(const hs_desc_intro_point_t *ip,
    564                      const node_t *rp_node,
    565                      const hs_subcredential_t *subcredential,
    566                      hs_cell_introduce1_data_t *intro1_data)
    567 {
    568  int ret = -1;
    569  smartlist_t *rp_lspecs;
    570 
    571  tor_assert(ip);
    572  tor_assert(rp_node);
    573  tor_assert(subcredential);
    574  tor_assert(intro1_data);
    575 
    576  /* Build the link specifiers from the node at the end of the rendezvous
    577   * circuit that we opened for this introduction. */
    578  rp_lspecs = node_get_link_specifier_smartlist(rp_node, 0);
    579  if (smartlist_len(rp_lspecs) == 0) {
    580    /* We can't rendezvous without link specifiers. */
    581    smartlist_free(rp_lspecs);
    582    goto end;
    583  }
    584 
    585  /* Populate the introduce1 data object. */
    586  memset(intro1_data, 0, sizeof(hs_cell_introduce1_data_t));
    587  intro1_data->auth_pk = &ip->auth_key_cert->signed_key;
    588  intro1_data->enc_pk = &ip->enc_key;
    589  intro1_data->subcredential = subcredential;
    590  intro1_data->link_specifiers = rp_lspecs;
    591  intro1_data->onion_pk = node_get_curve25519_onion_key(rp_node);
    592  if (intro1_data->onion_pk == NULL) {
    593    /* We can't rendezvous without the curve25519 onion key. */
    594    goto end;
    595  }
    596 
    597  /* Success, we have valid introduce data. */
    598  ret = 0;
    599 
    600 end:
    601  return ret;
    602 }
    603 
    604 /** Helper: cleanup function for client circuit. This is for every HS version.
    605 * It is called from hs_circ_cleanup_on_close() entry point. */
    606 static void
    607 cleanup_on_close_client_circ(circuit_t *circ)
    608 {
    609  tor_assert(circ);
    610 
    611  if (circuit_is_hs_v3(circ)) {
    612    hs_client_circuit_cleanup_on_close(circ);
    613  }
    614  /* It is possible the circuit has an HS purpose but no identifier (hs_ident).
    615   * Thus possible that this passes through. */
    616 }
    617 
    618 /** Helper: cleanup function for client circuit. This is for every HS version.
    619 * It is called from hs_circ_cleanup_on_free() entry point. */
    620 static void
    621 cleanup_on_free_client_circ(circuit_t *circ)
    622 {
    623  tor_assert(circ);
    624 
    625  if (circuit_is_hs_v3(circ)) {
    626    hs_client_circuit_cleanup_on_free(circ);
    627  }
    628  /* It is possible the circuit has an HS purpose but no identifier (hs_ident).
    629   * Thus possible that this passes through. */
    630 }
    631 
    632 /** Return less than 0 if a precedes b, 0 if a equals b and greater than 0 if
    633 * b precedes a. Note that *higher* effort is *earlier* in the pqueue. */
    634 static int
    635 compare_rend_request_by_effort_(const void *_a, const void *_b)
    636 {
    637  const pending_rend_t *a = _a, *b = _b;
    638  if (a->rdv_data.pow_effort > b->rdv_data.pow_effort) {
    639    return -1;
    640  } else if (a->rdv_data.pow_effort == b->rdv_data.pow_effort) {
    641    /* tie-breaker! use the time it was added to the queue. older better. */
    642    if (a->enqueued_ts < b->enqueued_ts)
    643      return -1;
    644    if (a->enqueued_ts > b->enqueued_ts)
    645      return 1;
    646    return 0;
    647  } else {
    648    return 1;
    649  }
    650 }
    651 
    652 /** Return 1 if a request waiting in our service-side pqueue is old
    653 * enough that we should just discard it rather than trying to respond,
    654 * or 0 if we still like it. As a heuristic, choose half of the total
    655 * permitted time interval (so we don't approve trying to respond to
    656 * requests when we will then give up on them a moment later).
    657 */
    658 static int
    659 queued_rend_request_is_too_old(pending_rend_t *req, time_t now)
    660 {
    661  if ((req->enqueued_ts + MAX_REND_TIMEOUT/2) < now)
    662    return 1;
    663  return 0;
    664 }
    665 
    666 /** Our rendezvous request priority queue is too full; keep the first
    667 * pqueue_high_level/2 entries and discard the rest.
    668 */
    669 static void
    670 trim_rend_pqueue(hs_pow_service_state_t *pow_state, time_t now)
    671 {
    672  smartlist_t *old_pqueue = pow_state->rend_request_pqueue;
    673  smartlist_t *new_pqueue = pow_state->rend_request_pqueue = smartlist_new();
    674 
    675  log_info(LD_REND, "Rendezvous request priority queue has "
    676                    "reached capacity (%d). Discarding the bottom half.",
    677                    smartlist_len(old_pqueue));
    678 
    679  while (smartlist_len(old_pqueue) &&
    680         smartlist_len(new_pqueue) < pow_state->pqueue_high_level/2) {
    681    /* while there are still old ones, and the new one isn't full yet */
    682    pending_rend_t *req =
    683      smartlist_pqueue_pop(old_pqueue,
    684                           compare_rend_request_by_effort_,
    685                           offsetof(pending_rend_t, idx));
    686    if (queued_rend_request_is_too_old(req, now)) {
    687      log_info(LD_REND, "While trimming, rend request has been pending "
    688                        "for too long; discarding.");
    689 
    690      pow_state->max_trimmed_effort = MAX(pow_state->max_trimmed_effort,
    691                                          req->rdv_data.pow_effort);
    692 
    693      free_pending_rend(req);
    694    } else {
    695      smartlist_pqueue_add(new_pqueue,
    696                           compare_rend_request_by_effort_,
    697                           offsetof(pending_rend_t, idx), req);
    698    }
    699  }
    700 
    701  /* Ok, we have rescued all the entries we want to keep. The rest are
    702   * all excess. */
    703  SMARTLIST_FOREACH_BEGIN(old_pqueue, pending_rend_t *, req) {
    704    pow_state->max_trimmed_effort = MAX(pow_state->max_trimmed_effort,
    705                                        req->rdv_data.pow_effort);
    706    free_pending_rend(req);
    707  } SMARTLIST_FOREACH_END(req);
    708  smartlist_free(old_pqueue);
    709 }
    710 
    711 /** Count up how many pending outgoing (CIRCUIT_PURPOSE_S_CONNECT_REND)
    712 * circuits there are for this service. Used in the PoW rate limiting
    713 * world to decide whether it's time to launch any new ones.
    714 */
    715 static int
    716 count_service_rp_circuits_pending(hs_service_t *service)
    717 {
    718  origin_circuit_t *ocirc = NULL;
    719  int count = 0;
    720  while ((ocirc = circuit_get_next_by_purpose(ocirc,
    721                            CIRCUIT_PURPOSE_S_CONNECT_REND))) {
    722    /* Count up circuits that are v3 and for this service. */
    723    if (ocirc->hs_ident != NULL &&
    724        ed25519_pubkey_eq(&ocirc->hs_ident->identity_pk,
    725                          &service->keys.identity_pk)) {
    726      count++;
    727    }
    728  }
    729  return count;
    730 }
    731 
    732 /** Peek at the top entry on the pending rend pqueue, which must not be empty.
    733 * If its level of effort is at least what we're suggesting for that service
    734 * right now, return 1, else return 0.
    735 */
    736 int
    737 top_of_rend_pqueue_is_worthwhile(hs_pow_service_state_t *pow_state)
    738 {
    739  tor_assert(pow_state->rend_request_pqueue);
    740  tor_assert(smartlist_len(pow_state->rend_request_pqueue));
    741 
    742  pending_rend_t *req =
    743    smartlist_get(pow_state->rend_request_pqueue, 0);
    744 
    745  if (req->rdv_data.pow_effort >= pow_state->suggested_effort)
    746    return 1;
    747 
    748  return 0;
    749 }
    750 
    751 /** Abandon and free all pending rend requests, leaving the pqueue empty. */
    752 void
    753 rend_pqueue_clear(hs_pow_service_state_t *pow_state)
    754 {
    755  tor_assert(pow_state->rend_request_pqueue);
    756  while (smartlist_len(pow_state->rend_request_pqueue)) {
    757    pending_rend_t *req = smartlist_pop_last(pow_state->rend_request_pqueue);
    758    free_pending_rend(req);
    759  }
    760 }
    761 
    762 /** What is the threshold of in-progress (CIRCUIT_PURPOSE_S_CONNECT_REND)
    763 * rendezvous responses above which we won't launch new low-effort rendezvous
    764 * responses? (Intro2 cells with suitable PoW effort are not affected
    765 * by this threshold.) */
    766 #define MAX_CHEAP_REND_CIRCUITS_IN_PROGRESS 16
    767 
    768 static void
    769 handle_rend_pqueue_cb(mainloop_event_t *ev, void *arg)
    770 {
    771  hs_service_t *service = arg;
    772  hs_pow_service_state_t *pow_state = service->state.pow_state;
    773  time_t now = time(NULL);
    774  int in_flight = count_service_rp_circuits_pending(service);
    775 
    776  (void) ev; /* Not using the returned event, make compiler happy. */
    777 
    778  log_info(LD_REND, "Considering launching more rendezvous responses. "
    779           "%d in-flight, %d pending.",
    780           in_flight,
    781           smartlist_len(pow_state->rend_request_pqueue));
    782 
    783  /* Process only one rend request per callback, so that this work will not
    784   * be prioritized over other event loop callbacks. We may need to retry
    785   * in order to find one request that's still viable. */
    786  while (smartlist_len(pow_state->rend_request_pqueue) > 0) {
    787 
    788    /* first, peek at the top result to see if we want to pop it */
    789    if (in_flight >= MAX_CHEAP_REND_CIRCUITS_IN_PROGRESS &&
    790        !top_of_rend_pqueue_is_worthwhile(pow_state)) {
    791      /* We have queued requests, but they are all low priority, and also
    792       * we have too many in-progress rendezvous responses. Don't launch
    793       * any more. Schedule ourselves to reassess in a bit. */
    794      log_info(LD_REND, "Next request to launch is low priority, and "
    795               "%d in-flight already. Waiting to launch more.", in_flight);
    796      const struct timeval delay_tv = { 0, 100000 };
    797      mainloop_event_schedule(pow_state->pop_pqueue_ev, &delay_tv);
    798      return; /* done here! no cleanup needed. */
    799    }
    800 
    801    if (pow_state->using_pqueue_bucket) {
    802      token_bucket_ctr_refill(&pow_state->pqueue_bucket,
    803                              (uint32_t) monotime_coarse_absolute_sec());
    804 
    805      if (token_bucket_ctr_get(&pow_state->pqueue_bucket) > 0) {
    806        token_bucket_ctr_dec(&pow_state->pqueue_bucket, 1);
    807      } else {
    808        /* Waiting for pqueue rate limit to refill, come back later */
    809        const struct timeval delay_tv = { 0, 100000 };
    810        mainloop_event_schedule(pow_state->pop_pqueue_ev, &delay_tv);
    811        return;
    812      }
    813    }
    814 
    815    /* Pop next request by effort. */
    816    pending_rend_t *req =
    817      smartlist_pqueue_pop(pow_state->rend_request_pqueue,
    818                           compare_rend_request_by_effort_,
    819                           offsetof(pending_rend_t, idx));
    820 
    821    hs_metrics_pow_pqueue_rdv(service,
    822                              smartlist_len(pow_state->rend_request_pqueue));
    823 
    824    log_info(LD_REND, "Dequeued pending rendezvous request with effort: %u. "
    825                      "Waited %d. "
    826                      "Remaining requests: %u",
    827             req->rdv_data.pow_effort,
    828             (int)(now - req->enqueued_ts),
    829             smartlist_len(pow_state->rend_request_pqueue));
    830 
    831    if (queued_rend_request_is_too_old(req, now)) {
    832      log_info(LD_REND, "Top rend request has been pending for too long; "
    833                        "discarding and moving to the next one.");
    834      free_pending_rend(req);
    835      continue; /* do not increment count, this one's free */
    836    }
    837 
    838    /* Launch the rendezvous circuit. */
    839    launch_rendezvous_point_circuit(service, &req->ip_auth_pubkey,
    840                                    &req->ip_enc_key_kp, &req->rdv_data, now);
    841    free_pending_rend(req);
    842 
    843    ++pow_state->rend_handled;
    844    ++in_flight;
    845    break;
    846  }
    847 
    848  /* If there are still some pending rendezvous circuits in the pqueue then
    849   * reschedule the event in order to continue handling them. */
    850  if (smartlist_len(pow_state->rend_request_pqueue) > 0) {
    851    mainloop_event_activate(pow_state->pop_pqueue_ev);
    852 
    853    if (smartlist_len(pow_state->rend_request_pqueue) >=
    854        pow_state->pqueue_low_level) {
    855      pow_state->had_queue = 1;
    856    }
    857  }
    858 }
    859 
    860 /** Given the information needed to launch a rendezvous circuit and an
    861 * effort value, enqueue the rendezvous request in the service's PoW priority
    862 * queue with the effort being the priority.
    863 *
    864 * Return 0 if we successfully enqueued the request else -1. */
    865 static int
    866 enqueue_rend_request(const hs_service_t *service, hs_service_intro_point_t *ip,
    867                     hs_cell_introduce2_data_t *data, time_t now)
    868 {
    869  hs_pow_service_state_t *pow_state = NULL;
    870  pending_rend_t *req = NULL;
    871 
    872  tor_assert(service);
    873  tor_assert(ip);
    874  tor_assert(data);
    875 
    876  /* Ease our lives */
    877  pow_state = service->state.pow_state;
    878 
    879  req = tor_malloc_zero(sizeof(pending_rend_t));
    880 
    881  /* Copy over the rendezvous request the needed data to launch a circuit. */
    882  ed25519_pubkey_copy(&req->ip_auth_pubkey, &ip->auth_key_kp.pubkey);
    883  memcpy(&req->ip_enc_key_kp, &ip->enc_key_kp, sizeof(req->ip_enc_key_kp));
    884  memcpy(&req->rdv_data, &data->rdv_data, sizeof(req->rdv_data));
    885  /* Invalidate the link specifier pointer in the introduce2 data so it
    886   * doesn't get freed under us. */
    887  data->rdv_data.link_specifiers = NULL;
    888  req->idx = -1;
    889  req->enqueued_ts = now;
    890 
    891  /* Enqueue the rendezvous request. */
    892  smartlist_pqueue_add(pow_state->rend_request_pqueue,
    893                       compare_rend_request_by_effort_,
    894                       offsetof(pending_rend_t, idx), req);
    895 
    896  hs_metrics_pow_pqueue_rdv(service,
    897                            smartlist_len(pow_state->rend_request_pqueue));
    898 
    899  log_info(LD_REND, "Enqueued rendezvous request with effort: %u. "
    900                    "Queued requests: %u",
    901           req->rdv_data.pow_effort,
    902           smartlist_len(pow_state->rend_request_pqueue));
    903 
    904  /* Initialize the priority queue event if it hasn't been done so already. */
    905  if (pow_state->pop_pqueue_ev == NULL) {
    906    pow_state->pop_pqueue_ev =
    907        mainloop_event_postloop_new(handle_rend_pqueue_cb, (void *)service);
    908  }
    909 
    910  /* Activate event, we just enqueued a rendezvous request. */
    911  mainloop_event_activate(pow_state->pop_pqueue_ev);
    912 
    913  /* See if there are so many cells queued that we need to cull. */
    914  if (smartlist_len(pow_state->rend_request_pqueue) >=
    915        pow_state->pqueue_high_level) {
    916    trim_rend_pqueue(pow_state, now);
    917    hs_metrics_pow_pqueue_rdv(service,
    918                              smartlist_len(pow_state->rend_request_pqueue));
    919  }
    920 
    921  return 0;
    922 }
    923 
    924 /* ========== */
    925 /* Public API */
    926 /* ========== */
    927 
    928 /** Setup on the given circuit congestion control with the given parameters.
    929 *
    930 * This function assumes that congestion control is enabled on the network and
    931 * so it is the caller responsability to make sure of it. */
    932 void
    933 hs_circ_setup_congestion_control(origin_circuit_t *origin_circ,
    934                                 uint8_t sendme_inc, bool is_single_onion)
    935 {
    936  circuit_t *circ = NULL;
    937  circuit_params_t circ_params = {0};
    938 
    939  tor_assert(origin_circ);
    940 
    941  /* Ease our lives */
    942  circ = TO_CIRCUIT(origin_circ);
    943 
    944  circ_params.cc_enabled = true;
    945  circ_params.sendme_inc_cells = sendme_inc;
    946 
    947  /* It is setup on the circuit in order to indicate that congestion control is
    948   * enabled. It will be transferred to the RP crypt_path_t once the handshake
    949   * is finalized in finalize_rend_circuit() for both client and service
    950   * because the final hop is not available until then. */
    951 
    952  if (is_single_onion) {
    953    circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION_SOS);
    954  } else {
    955    if (get_options()->HSLayer3Nodes) {
    956      circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION_VG);
    957    } else {
    958      circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION);
    959    }
    960  }
    961 }
    962 
    963 /** Return an introduction point circuit matching the given intro point object.
    964 * NULL is returned is no such circuit can be found. */
    965 origin_circuit_t *
    966 hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
    967 {
    968  tor_assert(ip);
    969 
    970  return hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
    971 }
    972 
    973 /** Return an introduction point established circuit matching the given intro
    974 * point object. The circuit purpose has to be CIRCUIT_PURPOSE_S_INTRO. NULL
    975 * is returned is no such circuit can be found. */
    976 origin_circuit_t *
    977 hs_circ_service_get_established_intro_circ(const hs_service_intro_point_t *ip)
    978 {
    979  origin_circuit_t *circ;
    980 
    981  tor_assert(ip);
    982 
    983  circ = hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
    984 
    985  /* Only return circuit if it is established. */
    986  return (circ && TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO) ?
    987          circ : NULL;
    988 }
    989 
    990 /** Called when we fail building a rendezvous circuit at some point other than
    991 * the last hop: launches a new circuit to the same rendezvous point.
    992 *
    993 * We currently relaunch connections to rendezvous points if:
    994 * - A rendezvous circuit timed out before connecting to RP.
    995 * - The rendezvous circuit failed to connect to the RP.
    996 *
    997 * We avoid relaunching a connection to this rendezvous point if:
    998 * - We have already tried MAX_REND_FAILURES times to connect to this RP,
    999 * - We've been trying to connect to this RP for more than MAX_REND_TIMEOUT
   1000 *   seconds, or
   1001 * - We've already retried this specific rendezvous circuit.
   1002 */
   1003 void
   1004 hs_circ_retry_service_rendezvous_point(const origin_circuit_t *circ)
   1005 {
   1006  tor_assert(circ);
   1007  tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
   1008 
   1009  /* Check if we are allowed to relaunch to the rendezvous point of circ. */
   1010  if (!can_relaunch_service_rendezvous_point(circ)) {
   1011    goto done;
   1012  }
   1013 
   1014  /* Legacy services don't have a hidden service ident. */
   1015  if (circ->hs_ident) {
   1016    retry_service_rendezvous_point(circ);
   1017  }
   1018 
   1019 done:
   1020  return;
   1021 }
   1022 
   1023 /** For a given service and a service intro point, launch a circuit to the
   1024 * extend info ei. If the service is a single onion, and direct_conn is true,
   1025 * a one-hop circuit will be requested.
   1026 *
   1027 * Return 0 if the circuit was successfully launched and tagged
   1028 * with the correct identifier. On error, a negative value is returned. */
   1029 int
   1030 hs_circ_launch_intro_point(hs_service_t *service,
   1031                           const hs_service_intro_point_t *ip,
   1032                           extend_info_t *ei,
   1033                           bool direct_conn)
   1034 {
   1035  /* Standard flags for introduction circuit. */
   1036  int ret = -1, circ_flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
   1037  origin_circuit_t *circ;
   1038 
   1039  tor_assert(service);
   1040  tor_assert(ip);
   1041  tor_assert(ei);
   1042 
   1043  /* Update circuit flags in case of a single onion service that requires a
   1044   * direct connection. */
   1045  tor_assert_nonfatal(ip->circuit_retries > 0);
   1046  /* Only single onion services can make direct conns */
   1047  if (BUG(!service->config.is_single_onion && direct_conn)) {
   1048    goto end;
   1049  }
   1050  /* We only use a one-hop path on the first attempt. If the first attempt
   1051   * fails, we use a 3-hop path for reachability / reliability. */
   1052  if (direct_conn && ip->circuit_retries == 1) {
   1053    circ_flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
   1054  }
   1055 
   1056  log_info(LD_REND, "Launching a circuit to intro point %s for service %s.",
   1057           safe_str_client(extend_info_describe(ei)),
   1058           safe_str_client(service->onion_address));
   1059 
   1060  /* Note down the launch for the retry period. Even if the circuit fails to
   1061   * be launched, we still want to respect the retry period to avoid stress on
   1062   * the circuit subsystem. */
   1063  service->state.num_intro_circ_launched++;
   1064  circ = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
   1065                                       ei, circ_flags);
   1066  if (circ == NULL) {
   1067    goto end;
   1068  }
   1069 
   1070  /* Setup the circuit identifier and attach it to it. */
   1071  circ->hs_ident = create_intro_circuit_identifier(service, ip);
   1072  tor_assert(circ->hs_ident);
   1073  /* Register circuit in the global circuitmap. */
   1074  register_intro_circ(ip, circ);
   1075 
   1076  /* Success. */
   1077  ret = 0;
   1078 end:
   1079  return ret;
   1080 }
   1081 
   1082 /** Called when a service introduction point circuit is done building. Given
   1083 * the service and intro point object, this function will send the
   1084 * ESTABLISH_INTRO cell on the circuit. Return 0 on success. Return 1 if the
   1085 * circuit has been repurposed to General because we already have too many
   1086 * opened. */
   1087 int
   1088 hs_circ_service_intro_has_opened(hs_service_t *service,
   1089                                 hs_service_intro_point_t *ip,
   1090                                 const hs_service_descriptor_t *desc,
   1091                                 origin_circuit_t *circ)
   1092 {
   1093  int ret = 0;
   1094  unsigned int num_intro_circ, num_needed_circ;
   1095 
   1096  tor_assert(service);
   1097  tor_assert(ip);
   1098  tor_assert(desc);
   1099  tor_assert(circ);
   1100 
   1101  /* Count opened circuits that have sent ESTABLISH_INTRO cells or are already
   1102   * established introduction circuits */
   1103  num_intro_circ = count_opened_desc_intro_point_circuits(service, desc);
   1104  num_needed_circ = service->config.num_intro_points;
   1105  if (num_intro_circ > num_needed_circ) {
   1106    /* There are too many opened valid intro circuit for what the service
   1107     * needs so repurpose this one. */
   1108 
   1109    /* XXX: Legacy code checks options->ExcludeNodes and if not NULL it just
   1110     * closes the circuit. I have NO idea why it does that so it hasn't been
   1111     * added here. I can only assume in case our ExcludeNodes list changes but
   1112     * in that case, all circuit are flagged unusable (config.c). --dgoulet */
   1113 
   1114    log_info(LD_CIRC | LD_REND, "Introduction circuit just opened but we "
   1115                                "have enough for service %s. Repurposing "
   1116                                "it to general and leaving internal.",
   1117             safe_str_client(service->onion_address));
   1118    tor_assert(circ->build_state->is_internal);
   1119    /* Remove it from the circuitmap. */
   1120    hs_circuitmap_remove_circuit(TO_CIRCUIT(circ));
   1121    /* Cleaning up the hidden service identifier and repurpose. */
   1122    hs_ident_circuit_free(circ->hs_ident);
   1123    circ->hs_ident = NULL;
   1124    if (circuit_should_use_vanguards(TO_CIRCUIT(circ)->purpose))
   1125      circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_HS_VANGUARDS);
   1126    else
   1127      circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_GENERAL);
   1128 
   1129    /* Inform that this circuit just opened for this new purpose. */
   1130    circuit_has_opened(circ);
   1131    /* This return value indicate to the caller that the IP object should be
   1132     * removed from the service because it's corresponding circuit has just
   1133     * been repurposed. */
   1134    ret = 1;
   1135    goto done;
   1136  }
   1137 
   1138  log_info(LD_REND, "Introduction circuit %u established for service %s.",
   1139           TO_CIRCUIT(circ)->n_circ_id,
   1140           safe_str_client(service->onion_address));
   1141  circuit_log_path(LOG_INFO, LD_REND, circ);
   1142 
   1143  /* Time to send an ESTABLISH_INTRO cell on this circuit. On error, this call
   1144   * makes sure the circuit gets closed. */
   1145  send_establish_intro(service, ip, circ);
   1146 
   1147 done:
   1148  return ret;
   1149 }
   1150 
   1151 /** Called when a service rendezvous point circuit is done building. Given the
   1152 * service and the circuit, this function will send a RENDEZVOUS1 cell on the
   1153 * circuit using the information in the circuit identifier. If the cell can't
   1154 * be sent, the circuit is closed. */
   1155 void
   1156 hs_circ_service_rp_has_opened(const hs_service_t *service,
   1157                              origin_circuit_t *circ)
   1158 {
   1159  size_t payload_len;
   1160  uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
   1161 
   1162  tor_assert(service);
   1163  tor_assert(circ);
   1164  tor_assert(circ->hs_ident);
   1165 
   1166  /* Some useful logging. */
   1167  log_info(LD_REND, "Rendezvous circuit %u has opened with cookie %s "
   1168                    "for service %s",
   1169           TO_CIRCUIT(circ)->n_circ_id,
   1170           hex_str((const char *) circ->hs_ident->rendezvous_cookie,
   1171                   REND_COOKIE_LEN),
   1172           safe_str_client(service->onion_address));
   1173  circuit_log_path(LOG_INFO, LD_REND, circ);
   1174 
   1175  /* This can't fail. */
   1176  payload_len = hs_cell_build_rendezvous1(
   1177                        circ->hs_ident->rendezvous_cookie,
   1178                        sizeof(circ->hs_ident->rendezvous_cookie),
   1179                        circ->hs_ident->rendezvous_handshake_info,
   1180                        sizeof(circ->hs_ident->rendezvous_handshake_info),
   1181                        payload);
   1182 
   1183  /* Pad the payload with random bytes so it matches the size of a legacy cell
   1184   * which is normally always bigger. Also, the size of a legacy cell is
   1185   * always smaller than the RELAY_PAYLOAD_SIZE so this is safe. */
   1186  if (payload_len < HS_LEGACY_RENDEZVOUS_CELL_SIZE) {
   1187    crypto_rand((char *) payload + payload_len,
   1188                HS_LEGACY_RENDEZVOUS_CELL_SIZE - payload_len);
   1189    payload_len = HS_LEGACY_RENDEZVOUS_CELL_SIZE;
   1190  }
   1191 
   1192  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
   1193                                   RELAY_COMMAND_RENDEZVOUS1,
   1194                                   (const char *) payload,
   1195                                   payload_len,
   1196                                   circ->cpath->prev) < 0) {
   1197    /* On error, circuit is closed. */
   1198    log_warn(LD_REND, "Unable to send RENDEZVOUS1 cell on circuit %u "
   1199                      "for service %s",
   1200             TO_CIRCUIT(circ)->n_circ_id,
   1201             safe_str_client(service->onion_address));
   1202 
   1203    hs_metrics_failed_rdv(&service->keys.identity_pk,
   1204                          HS_METRICS_ERR_RDV_RENDEZVOUS1);
   1205    goto done;
   1206  }
   1207 
   1208  /* Setup end-to-end rendezvous circuit between the client and us. */
   1209  if (hs_circuit_setup_e2e_rend_circ(circ,
   1210                       circ->hs_ident->rendezvous_ntor_key_seed,
   1211                       sizeof(circ->hs_ident->rendezvous_ntor_key_seed),
   1212                       1) < 0) {
   1213    log_warn(LD_GENERAL, "Failed to setup circ");
   1214 
   1215    hs_metrics_failed_rdv(&service->keys.identity_pk, HS_METRICS_ERR_RDV_E2E);
   1216    goto done;
   1217  }
   1218 
   1219 done:
   1220  memwipe(payload, 0, sizeof(payload));
   1221 }
   1222 
   1223 /** Circ has been expecting an INTRO_ESTABLISHED cell that just arrived. Handle
   1224 * the INTRO_ESTABLISHED cell payload of length payload_len arriving on the
   1225 * given introduction circuit circ. The service is only used for logging
   1226 * purposes. Return 0 on success else a negative value. */
   1227 int
   1228 hs_circ_handle_intro_established(const hs_service_t *service,
   1229                                 const hs_service_intro_point_t *ip,
   1230                                 origin_circuit_t *circ,
   1231                                 const uint8_t *payload, size_t payload_len)
   1232 {
   1233  int ret = -1;
   1234 
   1235  tor_assert(service);
   1236  tor_assert(ip);
   1237  tor_assert(circ);
   1238  tor_assert(payload);
   1239 
   1240  if (BUG(TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)) {
   1241    goto done;
   1242  }
   1243 
   1244  /* Try to parse the payload into a cell making sure we do actually have a
   1245   * valid cell. */
   1246  if (hs_cell_parse_intro_established(payload, payload_len) < 0) {
   1247    log_warn(LD_REND, "Unable to parse the INTRO_ESTABLISHED cell on "
   1248                      "circuit %u for service %s",
   1249             TO_CIRCUIT(circ)->n_circ_id,
   1250             safe_str_client(service->onion_address));
   1251    goto done;
   1252  }
   1253 
   1254  /* Switch the purpose to a fully working intro point. */
   1255  circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_S_INTRO);
   1256  /* Getting a valid INTRODUCE_ESTABLISHED means we've successfully used the
   1257   * circuit so update our pathbias subsystem. */
   1258  pathbias_mark_use_success(circ);
   1259  /* Success. */
   1260  ret = 0;
   1261 
   1262 done:
   1263  return ret;
   1264 }
   1265 
   1266 /**
   1267 *  Go into <b>data</b> and add the right subcredential to be able to handle
   1268 *  this incoming cell.
   1269 *
   1270 *  <b>desc_subcred</b> is the subcredential of the descriptor that corresponds
   1271 *  to the intro point that received this intro request. This subcredential
   1272 *  should be used if we are not an onionbalance instance.
   1273 *
   1274 *  Return 0 if everything went well, or -1 in case of internal error.
   1275 */
   1276 static int
   1277 get_subcredential_for_handling_intro2_cell(const hs_service_t *service,
   1278                                        hs_cell_introduce2_data_t *data,
   1279                                        const hs_subcredential_t *desc_subcred)
   1280 {
   1281  /* Handle the simple case first: We are not an onionbalance instance and we
   1282   * should just use the regular descriptor subcredential */
   1283  if (!hs_ob_service_is_instance(service)) {
   1284    data->n_subcredentials = 1;
   1285    data->subcredentials = desc_subcred;
   1286    return 0;
   1287  }
   1288 
   1289  /* This should not happen since we should have made onionbalance
   1290   * subcredentials when we created our descriptors. */
   1291  if (BUG(!service->state.ob_subcreds)) {
   1292    return -1;
   1293  }
   1294 
   1295  /* We are an onionbalance instance: */
   1296  data->n_subcredentials = service->state.n_ob_subcreds;
   1297  data->subcredentials = service->state.ob_subcreds;
   1298 
   1299  return 0;
   1300 }
   1301 
   1302 /** We just received an INTRODUCE2 cell on the established introduction circuit
   1303 * circ.  Handle the INTRODUCE2 payload of size payload_len for the given
   1304 * circuit and service. This cell is associated with the intro point object ip
   1305 * and the subcredential. Return 0 on success else a negative value. */
   1306 int
   1307 hs_circ_handle_introduce2(const hs_service_t *service,
   1308                          const origin_circuit_t *circ,
   1309                          hs_service_intro_point_t *ip,
   1310                          const hs_subcredential_t *subcredential,
   1311                          const uint8_t *payload, size_t payload_len)
   1312 {
   1313  int ret = -1;
   1314  time_t elapsed;
   1315  hs_cell_introduce2_data_t data;
   1316  time_t now = time(NULL);
   1317 
   1318  tor_assert(service);
   1319  tor_assert(circ);
   1320  tor_assert(ip);
   1321  tor_assert(subcredential);
   1322  tor_assert(payload);
   1323 
   1324  /* Populate the data structure with everything we need for the cell to be
   1325   * parsed, decrypted and key material computed correctly. */
   1326  data.auth_pk = &ip->auth_key_kp.pubkey;
   1327  data.enc_kp = &ip->enc_key_kp;
   1328  data.payload = payload;
   1329  data.payload_len = payload_len;
   1330  data.replay_cache = ip->replay_cache;
   1331  data.rdv_data.link_specifiers = smartlist_new();
   1332  data.rdv_data.cc_enabled = 0;
   1333  data.rdv_data.pow_effort = 0;
   1334 
   1335  if (get_subcredential_for_handling_intro2_cell(service, &data,
   1336                                                 subcredential)) {
   1337    hs_metrics_reject_intro_req(service,
   1338                                HS_METRICS_ERR_INTRO_REQ_SUBCREDENTIAL);
   1339    goto done;
   1340  }
   1341 
   1342  if (hs_cell_parse_introduce2(&data, circ, service, ip) < 0) {
   1343    hs_metrics_reject_intro_req(service, HS_METRICS_ERR_INTRO_REQ_INTRODUCE2);
   1344    goto done;
   1345  }
   1346 
   1347  /* Check whether we've seen this REND_COOKIE before to detect repeats. */
   1348  if (replaycache_add_test_and_elapsed(
   1349           service->state.replay_cache_rend_cookie,
   1350           data.rdv_data.rendezvous_cookie,
   1351           sizeof(data.rdv_data.rendezvous_cookie),
   1352           &elapsed)) {
   1353    /* A Tor client will send a new INTRODUCE1 cell with the same REND_COOKIE
   1354     * as its previous one if its intro circ times out while in state
   1355     * CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT. If we received the first
   1356     * INTRODUCE1 cell (the intro-point relay converts it into an INTRODUCE2
   1357     * cell), we are already trying to connect to that rend point (and may
   1358     * have already succeeded); drop this cell. */
   1359    log_info(LD_REND, "We received an INTRODUCE2 cell with same REND_COOKIE "
   1360                      "field %ld seconds ago. Dropping cell.",
   1361             (long int) elapsed);
   1362    hs_metrics_reject_intro_req(service,
   1363                                HS_METRICS_ERR_INTRO_REQ_INTRODUCE2_REPLAY);
   1364    goto done;
   1365  }
   1366 
   1367  /* At this point, we just confirmed that the full INTRODUCE2 cell is valid
   1368   * so increment our counter that we've seen one on this intro point. */
   1369  ip->introduce2_count++;
   1370 
   1371  /* Add the rendezvous request to the priority queue if PoW defenses are
   1372   * enabled, otherwise rendezvous as usual. */
   1373  if (have_module_pow() && service->config.has_pow_defenses_enabled) {
   1374    log_info(LD_REND,
   1375             "Adding introduction request to pqueue with effort: %u",
   1376             data.rdv_data.pow_effort);
   1377    if (enqueue_rend_request(service, ip, &data, now) < 0) {
   1378      goto done;
   1379    }
   1380 
   1381    /* Track the total effort in valid requests received this period */
   1382    service->state.pow_state->total_effort += data.rdv_data.pow_effort;
   1383 
   1384    /* Successfully added rend circuit to priority queue. */
   1385    ret = 0;
   1386    goto done;
   1387  }
   1388 
   1389  /* Launch rendezvous circuit with the onion key and rend cookie. */
   1390  launch_rendezvous_point_circuit(service, &ip->auth_key_kp.pubkey,
   1391                                  &ip->enc_key_kp, &data.rdv_data, now);
   1392  /* Success. */
   1393  ret = 0;
   1394 
   1395 done:
   1396  /* Note that if PoW defenses are enabled, this is NULL. */
   1397  link_specifier_smartlist_free(data.rdv_data.link_specifiers);
   1398  memwipe(&data, 0, sizeof(data));
   1399  return ret;
   1400 }
   1401 
   1402 /** Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
   1403 * exchange output material at <b>ntor_key_seed</b> and setup <b>circ</b> to
   1404 * serve as a rendezvous end-to-end circuit between the client and the
   1405 * service. If <b>is_service_side</b> is set, then we are the hidden service
   1406 * and the other side is the client.
   1407 *
   1408 * Return 0 if the operation went well; in case of error return -1. */
   1409 int
   1410 hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ,
   1411                               const uint8_t *ntor_key_seed, size_t seed_len,
   1412                               int is_service_side)
   1413 {
   1414  if (BUG(!circuit_purpose_is_correct_for_rend(TO_CIRCUIT(circ)->purpose,
   1415                                        is_service_side))) {
   1416    return -1;
   1417  }
   1418 
   1419  crypt_path_t *hop = create_rend_cpath(ntor_key_seed, seed_len,
   1420                                        is_service_side);
   1421  if (!hop) {
   1422    log_warn(LD_REND, "Couldn't get v3 %s cpath!",
   1423             is_service_side ? "service-side" : "client-side");
   1424    return -1;
   1425  }
   1426 
   1427  finalize_rend_circuit(circ, hop, is_service_side);
   1428 
   1429  return 0;
   1430 }
   1431 
   1432 /** Given the introduction circuit intro_circ, the rendezvous circuit
   1433 * rend_circ, a descriptor intro point object ip and the service's
   1434 * subcredential, send an INTRODUCE1 cell on intro_circ.
   1435 *
   1436 * This will also setup the circuit identifier on rend_circ containing the key
   1437 * material for the handshake and e2e encryption. Return 0 on success else
   1438 * negative value. Because relay_send_command_from_edge() closes the circuit
   1439 * on error, it is possible that intro_circ is closed on error. */
   1440 int
   1441 hs_circ_send_introduce1(origin_circuit_t *intro_circ,
   1442                        origin_circuit_t *rend_circ,
   1443                        const hs_desc_intro_point_t *ip,
   1444                        const hs_subcredential_t *subcredential,
   1445                        const hs_pow_solution_t *pow_solution)
   1446 {
   1447  int ret = -1;
   1448  ssize_t payload_len;
   1449  uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
   1450  hs_cell_introduce1_data_t intro1_data;
   1451 
   1452  tor_assert(intro_circ);
   1453  tor_assert(rend_circ);
   1454  tor_assert(ip);
   1455  tor_assert(subcredential);
   1456 
   1457  /* It is undefined behavior in hs_cell_introduce1_data_clear() if intro1_data
   1458   * has been declared on the stack but not initialized. Here, we set it to 0.
   1459   */
   1460  memset(&intro1_data, 0, sizeof(hs_cell_introduce1_data_t));
   1461 
   1462  /* This takes various objects in order to populate the introduce1 data
   1463   * object which is used to build the content of the cell. */
   1464  const node_t *exit_node = build_state_get_exit_node(rend_circ->build_state);
   1465  if (exit_node == NULL) {
   1466    log_info(LD_REND, "Unable to get rendezvous point for circuit %u. "
   1467             "Failing.", TO_CIRCUIT(intro_circ)->n_circ_id);
   1468    goto done;
   1469  }
   1470 
   1471  /* We should never select an invalid rendezvous point in theory but if we
   1472   * do, this function will fail to populate the introduce data. */
   1473  if (setup_introduce1_data(ip, exit_node, subcredential, &intro1_data) < 0) {
   1474    log_info(LD_REND, "Unable to setup INTRODUCE1 data. The chosen rendezvous "
   1475                      "point is unusable. Closing circuit.");
   1476    goto close;
   1477  }
   1478 
   1479  /* Set the PoW solution if any. */
   1480  intro1_data.pow_solution = pow_solution;
   1481 
   1482  /* If the rend circ was set up for congestion control, add that to the
   1483   * intro data, to signal it in an extension */
   1484  if (TO_CIRCUIT(rend_circ)->ccontrol) {
   1485    intro1_data.cc_enabled = 1;
   1486  }
   1487 
   1488  /* Final step before we encode a cell, we setup the circuit identifier which
   1489   * will generate both the rendezvous cookie and client keypair for this
   1490   * connection. Those are put in the ident. */
   1491  intro1_data.rendezvous_cookie = rend_circ->hs_ident->rendezvous_cookie;
   1492  intro1_data.client_kp = &rend_circ->hs_ident->rendezvous_client_kp;
   1493 
   1494  memcpy(intro_circ->hs_ident->rendezvous_cookie,
   1495         rend_circ->hs_ident->rendezvous_cookie,
   1496         sizeof(intro_circ->hs_ident->rendezvous_cookie));
   1497 
   1498  /* From the introduce1 data object, this will encode the INTRODUCE1 cell
   1499   * into payload which is then ready to be sent as is. */
   1500  payload_len = hs_cell_build_introduce1(&intro1_data, payload);
   1501  if (BUG(payload_len < 0)) {
   1502    goto close;
   1503  }
   1504 
   1505  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(intro_circ),
   1506                                   RELAY_COMMAND_INTRODUCE1,
   1507                                   (const char *) payload, payload_len,
   1508                                   intro_circ->cpath->prev) < 0) {
   1509    /* On error, circuit is closed. */
   1510    log_warn(LD_REND, "Unable to send INTRODUCE1 cell on circuit %u.",
   1511             TO_CIRCUIT(intro_circ)->n_circ_id);
   1512    goto done;
   1513  }
   1514 
   1515  /* Success. */
   1516  ret = 0;
   1517  goto done;
   1518 
   1519 close:
   1520  circuit_mark_for_close(TO_CIRCUIT(rend_circ), END_CIRC_REASON_INTERNAL);
   1521 done:
   1522  hs_cell_introduce1_data_clear(&intro1_data);
   1523  memwipe(payload, 0, sizeof(payload));
   1524  return ret;
   1525 }
   1526 
   1527 /** Send an ESTABLISH_RENDEZVOUS cell along the rendezvous circuit circ. On
   1528 * success, 0 is returned else -1 and the circuit is marked for close. */
   1529 int
   1530 hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
   1531 {
   1532  ssize_t cell_len = 0;
   1533  uint8_t cell[RELAY_PAYLOAD_SIZE_MAX] = {0};
   1534 
   1535  tor_assert(circ);
   1536  tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
   1537 
   1538  log_info(LD_REND, "Send an ESTABLISH_RENDEZVOUS cell on circuit %u",
   1539           TO_CIRCUIT(circ)->n_circ_id);
   1540 
   1541  /* Set timestamp_dirty, because circuit_expire_building expects it,
   1542   * and the rend cookie also means we've used the circ. */
   1543  TO_CIRCUIT(circ)->timestamp_dirty = time(NULL);
   1544 
   1545  /* We've attempted to use this circuit. Probe it if we fail */
   1546  pathbias_count_use_attempt(circ);
   1547 
   1548  /* Generate the RENDEZVOUS_COOKIE and place it in the identifier so we can
   1549   * complete the handshake when receiving the acknowledgement. */
   1550  crypto_rand((char *) circ->hs_ident->rendezvous_cookie, HS_REND_COOKIE_LEN);
   1551  /* Generate the client keypair. No need to be extra strong, not long term */
   1552  curve25519_keypair_generate(&circ->hs_ident->rendezvous_client_kp, 0);
   1553 
   1554  cell_len =
   1555    hs_cell_build_establish_rendezvous(circ->hs_ident->rendezvous_cookie,
   1556                                       cell);
   1557  if (BUG(cell_len < 0)) {
   1558    goto err;
   1559  }
   1560 
   1561  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
   1562                                   RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
   1563                                   (const char *) cell, cell_len,
   1564                                   circ->cpath->prev) < 0) {
   1565    /* Circuit has been marked for close */
   1566    log_warn(LD_REND, "Unable to send ESTABLISH_RENDEZVOUS cell on "
   1567                      "circuit %u", TO_CIRCUIT(circ)->n_circ_id);
   1568    memwipe(cell, 0, cell_len);
   1569    goto err;
   1570  }
   1571 
   1572  memwipe(cell, 0, cell_len);
   1573  return 0;
   1574 err:
   1575  return -1;
   1576 }
   1577 
   1578 /** Circuit cleanup strategy:
   1579 *
   1580 *  What follows is a series of functions that notifies the HS subsystem of 3
   1581 *  different circuit cleanup phase: close, free and repurpose.
   1582 *
   1583 *  Tor can call any of those in any orders so they have to be safe between
   1584 *  each other. In other words, the free should never depend on close to be
   1585 *  called before.
   1586 *
   1587 *  The "on_close()" is called from circuit_mark_for_close() which is
   1588 *  considered the tor fast path and thus as little work as possible should
   1589 *  done in that function. Currently, we only remove the circuit from the HS
   1590 *  circuit map and move on.
   1591 *
   1592 *  The "on_free()" is called from circuit circuit_free_() and it is very
   1593 *  important that at the end of the function, no state or objects related to
   1594 *  this circuit remains alive.
   1595 *
   1596 *  The "on_repurpose()" is called from circuit_change_purpose() for which we
   1597 *  simply remove it from the HS circuit map. We do not have other cleanup
   1598 *  requirements after that.
   1599 *
   1600 *  NOTE: The onion service code, specifically the service code, cleans up
   1601 *  lingering objects or state if any of its circuit disappear which is why
   1602 *  our cleanup strategy doesn't involve any service specific actions. As long
   1603 *  as the circuit is removed from the HS circuit map, it won't be used.
   1604 */
   1605 
   1606 /** We are about to close this <b>circ</b>. Clean it up from any related HS
   1607 * data structures. This function can be called multiple times safely for the
   1608 * same circuit. */
   1609 void
   1610 hs_circ_cleanup_on_close(circuit_t *circ)
   1611 {
   1612  tor_assert(circ);
   1613 
   1614  if (circuit_purpose_is_hs_client(circ->purpose)) {
   1615    cleanup_on_close_client_circ(circ);
   1616  }
   1617 
   1618  if (circuit_purpose_is_hs_service(circ->purpose)) {
   1619    if (circuit_is_hs_v3(circ)) {
   1620      hs_service_circuit_cleanup_on_close(circ);
   1621    }
   1622  }
   1623 
   1624  /* On close, we simply remove it from the circuit map. It can not be used
   1625   * anymore. We keep this code path fast and lean. */
   1626 
   1627  if (circ->hs_token) {
   1628    hs_circuitmap_remove_circuit(circ);
   1629  }
   1630 }
   1631 
   1632 /** We are about to free this <b>circ</b>. Clean it up from any related HS
   1633 * data structures. This function can be called multiple times safely for the
   1634 * same circuit. */
   1635 void
   1636 hs_circ_cleanup_on_free(circuit_t *circ)
   1637 {
   1638  tor_assert(circ);
   1639 
   1640  /* NOTE: Bulk of the work of cleaning up a circuit is done here. */
   1641 
   1642  if (circuit_purpose_is_hs_client(circ->purpose)) {
   1643    cleanup_on_free_client_circ(circ);
   1644  }
   1645 
   1646  /* We have no assurance that the given HS circuit has been closed before and
   1647   * thus removed from the HS map. This actually happens in unit tests. */
   1648  if (circ->hs_token) {
   1649    hs_circuitmap_remove_circuit(circ);
   1650  }
   1651 }
   1652 
   1653 /** We are about to repurpose this <b>circ</b>. Clean it up from any related
   1654 * HS data structures. This function can be called multiple times safely for
   1655 * the same circuit. */
   1656 void
   1657 hs_circ_cleanup_on_repurpose(circuit_t *circ)
   1658 {
   1659  tor_assert(circ);
   1660 
   1661  /* On repurpose, we simply remove it from the circuit map but we do not do
   1662   * the on_free actions since we don't treat a repurpose as something we need
   1663   * to report in the client cache failure. */
   1664 
   1665  if (circ->hs_token) {
   1666    hs_circuitmap_remove_circuit(circ);
   1667  }
   1668 
   1669  switch (circ->purpose) {
   1670  case CIRCUIT_PURPOSE_S_CONNECT_REND:
   1671    /* This circuit was connecting to a rendezvous point but it is being
   1672     * repurposed so we need to relaunch an attempt else the client will be
   1673     * left hanging waiting for the rendezvous. */
   1674    hs_circ_retry_service_rendezvous_point(TO_ORIGIN_CIRCUIT(circ));
   1675    break;
   1676  default:
   1677    break;
   1678  }
   1679 }
   1680 
   1681 /** Return true iff the given established client rendezvous circuit was sent
   1682 * into the INTRODUCE1 cell. This is called so we can take a decision on
   1683 * expiring or not the circuit.
   1684 *
   1685 * The caller MUST make sure the circuit is an established client rendezvous
   1686 * circuit (purpose: CIRCUIT_PURPOSE_C_REND_READY).
   1687 *
   1688 * This function supports all onion service versions. */
   1689 bool
   1690 hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ)
   1691 {
   1692  tor_assert(circ);
   1693  /* This can only be called for a rendezvous circuit that is an established
   1694   * confirmed rendezsvous circuit but without an introduction ACK. */
   1695  tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_REND_READY);
   1696 
   1697  /* When the INTRODUCE1 cell is sent, the introduction encryption public
   1698   * key is copied in the rendezvous circuit hs identifier. If it is a valid
   1699   * key, we know that this circuit is waiting the ACK on the introduction
   1700   * circuit. We want to _not_ spare the circuit if the key was never set. */
   1701 
   1702  if (circ->hs_ident) {
   1703    /* v3. */
   1704    if (curve25519_public_key_is_ok(&circ->hs_ident->intro_enc_pk)) {
   1705      return true;
   1706    }
   1707  } else {
   1708    /* A circuit with an HS purpose without an hs_ident in theory can not
   1709     * happen. In case, scream loudly and return false to the caller that the
   1710     * rendezvous was not sent in the INTRO1 cell. */
   1711    tor_assert_nonfatal_unreached();
   1712  }
   1713 
   1714  /* The rendezvous has not been specified in the INTRODUCE1 cell. */
   1715  return false;
   1716 }