[tor-commits] [tor/release-0.3.2] Merge branch 'bug24895_029_02' into bug24895_031_02

nickm at torproject.org nickm at torproject.org
Fri Jan 19 21:32:22 UTC 2018


commit f98f7ca89865d1a477fc65165b92c86b9d8437fa
Merge: f406b9df0 490ae26b2
Author: David Goulet <dgoulet at torproject.org>
Date:   Fri Jan 19 16:21:55 2018 -0500

    Merge branch 'bug24895_029_02' into bug24895_031_02

 changes/bug24895     |  8 ++++++++
 src/or/hs_common.c   | 17 +++++++++++++++++
 src/or/hs_common.h   |  1 +
 src/or/hs_service.c  |  1 +
 src/or/rendservice.c | 10 ++++++++--
 5 files changed, 35 insertions(+), 2 deletions(-)

diff --cc src/or/hs_common.c
index 7cef5a8e2,000000000..c9af3f688
mode 100644,000000..100644
--- a/src/or/hs_common.c
+++ b/src/or/hs_common.c
@@@ -1,346 -1,0 +1,363 @@@
 +/* Copyright (c) 2016-2017, The Tor Project, Inc. */
 +/* See LICENSE for licensing information */
 +
 +/**
 + * \file hs_common.c
 + * \brief Contains code shared between different HS protocol version as well
 + *        as useful data structures and accessors used by other subsystems.
 + *        The rendcommon.c should only contains code relating to the v2
 + *        protocol.
 + **/
 +
 +#define HS_COMMON_PRIVATE
 +
 +#include "or.h"
 +
 +#include "config.h"
 +#include "networkstatus.h"
 +#include "hs_common.h"
 +#include "rendcommon.h"
 +
 +/* Make sure that the directory for <b>service</b> is private, using the config
 + * <b>username</b>.
 + * If <b>create</b> is true:
 + *  - if the directory exists, change permissions if needed,
 + *  - if the directory does not exist, create it with the correct permissions.
 + * If <b>create</b> is false:
 + *  - if the directory exists, check permissions,
 + *  - if the directory does not exist, check if we think we can create it.
 + * Return 0 on success, -1 on failure. */
 +int
 +hs_check_service_private_dir(const char *username, const char *path,
 +                             unsigned int dir_group_readable,
 +                             unsigned int create)
 +{
 +  cpd_check_t check_opts = CPD_NONE;
 +
 +  tor_assert(path);
 +
 +  if (create) {
 +    check_opts |= CPD_CREATE;
 +  } else {
 +    check_opts |= CPD_CHECK_MODE_ONLY;
 +    check_opts |= CPD_CHECK;
 +  }
 +  if (dir_group_readable) {
 +    check_opts |= CPD_GROUP_READ;
 +  }
 +  /* Check/create directory */
 +  if (check_private_dir(path, check_opts, username) < 0) {
 +    return -1;
 +  }
 +  return 0;
 +}
 +
 +/** Get the default HS time period length in minutes from the consensus. */
 +STATIC uint64_t
 +get_time_period_length(void)
 +{
 +  int32_t time_period_length = networkstatus_get_param(NULL, "hsdir_interval",
 +                                             HS_TIME_PERIOD_LENGTH_DEFAULT,
 +                                             HS_TIME_PERIOD_LENGTH_MIN,
 +                                             HS_TIME_PERIOD_LENGTH_MAX);
 +  /* Make sure it's a positive value. */
 +  tor_assert(time_period_length >= 0);
 +  /* uint64_t will always be able to contain a int32_t */
 +  return (uint64_t) time_period_length;
 +}
 +
 +/** Get the HS time period number at time <b>now</b> */
 +STATIC uint64_t
 +get_time_period_num(time_t now)
 +{
 +  uint64_t time_period_num;
 +  uint64_t time_period_length = get_time_period_length();
 +  uint64_t minutes_since_epoch = now / 60;
 +
 +  /* Now subtract half a day to fit the prop224 time period schedule (see
 +   * section [TIME-PERIODS]). */
 +  tor_assert(minutes_since_epoch > HS_TIME_PERIOD_ROTATION_OFFSET);
 +  minutes_since_epoch -= HS_TIME_PERIOD_ROTATION_OFFSET;
 +
 +  /* Calculate the time period */
 +  time_period_num = minutes_since_epoch / time_period_length;
 +  return time_period_num;
 +}
 +
 +/** Get the number of the _upcoming_ HS time period, given that the current
 + *  time is <b>now</b>. */
 +uint64_t
 +hs_get_next_time_period_num(time_t now)
 +{
 +  return get_time_period_num(now) + 1;
 +}
 +
 +/* Create a new rend_data_t for a specific given <b>version</b>.
 + * Return a pointer to the newly allocated data structure. */
 +static rend_data_t *
 +rend_data_alloc(uint32_t version)
 +{
 +  rend_data_t *rend_data = NULL;
 +
 +  switch (version) {
 +  case HS_VERSION_TWO:
 +  {
 +    rend_data_v2_t *v2 = tor_malloc_zero(sizeof(*v2));
 +    v2->base_.version = HS_VERSION_TWO;
 +    v2->base_.hsdirs_fp = smartlist_new();
 +    rend_data = &v2->base_;
 +    break;
 +  }
 +  default:
 +    tor_assert(0);
 +    break;
 +  }
 +
 +  return rend_data;
 +}
 +
 +/** Free all storage associated with <b>data</b> */
 +void
 +rend_data_free(rend_data_t *data)
 +{
 +  if (!data) {
 +    return;
 +  }
 +  /* By using our allocation function, this should always be set. */
 +  tor_assert(data->hsdirs_fp);
 +  /* Cleanup the HSDir identity digest. */
 +  SMARTLIST_FOREACH(data->hsdirs_fp, char *, d, tor_free(d));
 +  smartlist_free(data->hsdirs_fp);
 +  /* Depending on the version, cleanup. */
 +  switch (data->version) {
 +  case HS_VERSION_TWO:
 +  {
 +    rend_data_v2_t *v2_data = TO_REND_DATA_V2(data);
 +    tor_free(v2_data);
 +    break;
 +  }
 +  default:
 +    tor_assert(0);
 +  }
 +}
 +
 +/* Allocate and return a deep copy of <b>data</b>. */
 +rend_data_t *
 +rend_data_dup(const rend_data_t *data)
 +{
 +  rend_data_t *data_dup = NULL;
 +  smartlist_t *hsdirs_fp = smartlist_new();
 +
 +  tor_assert(data);
 +  tor_assert(data->hsdirs_fp);
 +
 +  SMARTLIST_FOREACH(data->hsdirs_fp, char *, fp,
 +                    smartlist_add(hsdirs_fp, tor_memdup(fp, DIGEST_LEN)));
 +
 +  switch (data->version) {
 +  case HS_VERSION_TWO:
 +  {
 +    rend_data_v2_t *v2_data = tor_memdup(TO_REND_DATA_V2(data),
 +                                         sizeof(*v2_data));
 +    data_dup = &v2_data->base_;
 +    data_dup->hsdirs_fp = hsdirs_fp;
 +    break;
 +  }
 +  default:
 +    tor_assert(0);
 +    break;
 +  }
 +
 +  return data_dup;
 +}
 +
 +/* Compute the descriptor ID for each HS descriptor replica and save them. A
 + * valid onion address must be present in the <b>rend_data</b>.
 + *
 + * Return 0 on success else -1. */
 +static int
 +compute_desc_id(rend_data_t *rend_data)
 +{
 +  int ret = 0;
 +  unsigned replica;
 +  time_t now = time(NULL);
 +
 +  tor_assert(rend_data);
 +
 +  switch (rend_data->version) {
 +  case HS_VERSION_TWO:
 +  {
 +    rend_data_v2_t *v2_data = TO_REND_DATA_V2(rend_data);
 +    /* Compute descriptor ID for each replicas. */
 +    for (replica = 0; replica < ARRAY_LENGTH(v2_data->descriptor_id);
 +         replica++) {
 +      ret = rend_compute_v2_desc_id(v2_data->descriptor_id[replica],
 +                                    v2_data->onion_address,
 +                                    v2_data->descriptor_cookie,
 +                                    now, replica);
 +      if (ret < 0) {
 +        goto end;
 +      }
 +    }
 +    break;
 +  }
 +  default:
 +    tor_assert(0);
 +  }
 +
 + end:
 +  return ret;
 +}
 +
 +/* Allocate and initialize a rend_data_t object for a service using the
 + * provided arguments. All arguments are optional (can be NULL), except from
 + * <b>onion_address</b> which MUST be set. The <b>pk_digest</b> is the hash of
 + * the service private key. The <b>cookie</b> is the rendezvous cookie and
 + * <b>auth_type</b> is which authentiation this service is configured with.
 + *
 + * Return a valid rend_data_t pointer. This only returns a version 2 object of
 + * rend_data_t. */
 +rend_data_t *
 +rend_data_service_create(const char *onion_address, const char *pk_digest,
 +                         const uint8_t *cookie, rend_auth_type_t auth_type)
 +{
 +  /* Create a rend_data_t object for version 2. */
 +  rend_data_t *rend_data = rend_data_alloc(HS_VERSION_TWO);
 +  rend_data_v2_t *v2= TO_REND_DATA_V2(rend_data);
 +
 +  /* We need at least one else the call is wrong. */
 +  tor_assert(onion_address != NULL);
 +
 +  if (pk_digest) {
 +    memcpy(v2->rend_pk_digest, pk_digest, sizeof(v2->rend_pk_digest));
 +  }
 +  if (cookie) {
 +    memcpy(rend_data->rend_cookie, cookie, sizeof(rend_data->rend_cookie));
 +  }
 +
 +  strlcpy(v2->onion_address, onion_address, sizeof(v2->onion_address));
 +  v2->auth_type = auth_type;
 +
 +  return rend_data;
 +}
 +
 +/* Allocate and initialize a rend_data_t object for a client request using the
 + * given arguments. Either an onion address or a descriptor ID is needed. Both
 + * can be given but in this case only the onion address will be used to make
 + * the descriptor fetch. The <b>cookie</b> is the rendezvous cookie and
 + * <b>auth_type</b> is which authentiation the service is configured with.
 + *
 + * Return a valid rend_data_t pointer or NULL on error meaning the
 + * descriptor IDs couldn't be computed from the given data. */
 +rend_data_t *
 +rend_data_client_create(const char *onion_address, const char *desc_id,
 +                        const char *cookie, rend_auth_type_t auth_type)
 +{
 +  /* Create a rend_data_t object for version 2. */
 +  rend_data_t *rend_data = rend_data_alloc(HS_VERSION_TWO);
 +  rend_data_v2_t *v2= TO_REND_DATA_V2(rend_data);
 +
 +  /* We need at least one else the call is wrong. */
 +  tor_assert(onion_address != NULL || desc_id != NULL);
 +
 +  if (cookie) {
 +    memcpy(v2->descriptor_cookie, cookie, sizeof(v2->descriptor_cookie));
 +  }
 +  if (desc_id) {
 +    memcpy(v2->desc_id_fetch, desc_id, sizeof(v2->desc_id_fetch));
 +  }
 +  if (onion_address) {
 +    strlcpy(v2->onion_address, onion_address, sizeof(v2->onion_address));
 +    if (compute_desc_id(rend_data) < 0) {
 +      goto error;
 +    }
 +  }
 +
 +  v2->auth_type = auth_type;
 +
 +  return rend_data;
 +
 + error:
 +  rend_data_free(rend_data);
 +  return NULL;
 +}
 +
 +/* Return the onion address from the rend data. Depending on the version,
 + * the size of the address can vary but it's always NUL terminated. */
 +const char *
 +rend_data_get_address(const rend_data_t *rend_data)
 +{
 +  tor_assert(rend_data);
 +
 +  switch (rend_data->version) {
 +  case HS_VERSION_TWO:
 +    return TO_REND_DATA_V2(rend_data)->onion_address;
 +  default:
 +    /* We should always have a supported version. */
 +    tor_assert(0);
 +  }
 +}
 +
 +/* Return the descriptor ID for a specific replica number from the rend
 + * data. The returned data is a binary digest and depending on the version its
 + * size can vary. The size of the descriptor ID is put in <b>len_out</b> if
 + * non NULL. */
 +const char *
 +rend_data_get_desc_id(const rend_data_t *rend_data, uint8_t replica,
 +                      size_t *len_out)
 +{
 +  tor_assert(rend_data);
 +
 +  switch (rend_data->version) {
 +  case HS_VERSION_TWO:
 +    tor_assert(replica < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS);
 +    if (len_out) {
 +      *len_out = DIGEST_LEN;
 +    }
 +    return TO_REND_DATA_V2(rend_data)->descriptor_id[replica];
 +  default:
 +    /* We should always have a supported version. */
 +    tor_assert(0);
 +  }
 +}
 +
 +/* Return the public key digest using the given <b>rend_data</b>. The size of
 + * the digest is put in <b>len_out</b> (if set) which can differ depending on
 + * the version. */
 +const uint8_t *
 +rend_data_get_pk_digest(const rend_data_t *rend_data, size_t *len_out)
 +{
 +  tor_assert(rend_data);
 +
 +  switch (rend_data->version) {
 +  case HS_VERSION_TWO:
 +  {
 +    const rend_data_v2_t *v2_data = TO_REND_DATA_V2(rend_data);
 +    if (len_out) {
 +      *len_out = sizeof(v2_data->rend_pk_digest);
 +    }
 +    return (const uint8_t *) v2_data->rend_pk_digest;
 +  }
 +  default:
 +    /* We should always have a supported version. */
 +    tor_assert(0);
 +  }
 +}
 +
++/* Default, minimum and maximum values for the maximum rendezvous failures
++ * consensus parameter. */
++#define MAX_REND_FAILURES_DEFAULT 2
++#define MAX_REND_FAILURES_MIN 1
++#define MAX_REND_FAILURES_MAX 10
++
++/** How many times will a hidden service operator attempt to connect to
++ * a requested rendezvous point before giving up? */
++int
++hs_get_service_max_rend_failures(void)
++{
++  return networkstatus_get_param(NULL, "hs_service_max_rdv_failures",
++                                 MAX_REND_FAILURES_DEFAULT,
++                                 MAX_REND_FAILURES_MIN,
++                                 MAX_REND_FAILURES_MAX);
++}
++
diff --cc src/or/hs_common.h
index a8fded652,000000000..7eef5fc97
mode 100644,000000..100644
--- a/src/or/hs_common.h
+++ b/src/or/hs_common.h
@@@ -1,86 -1,0 +1,87 @@@
 +/* Copyright (c) 2016-2017, The Tor Project, Inc. */
 +/* See LICENSE for licensing information */
 +
 +/**
 + * \file hs_common.h
 + * \brief Header file containing common data for the whole HS subsytem.
 + **/
 +
 +#ifndef TOR_HS_COMMON_H
 +#define TOR_HS_COMMON_H
 +
 +#include "or.h"
 +
 +/* Protocol version 2. Use this instead of hardcoding "2" in the code base,
 + * this adds a clearer semantic to the value when used. */
 +#define HS_VERSION_TWO 2
 +/* Version 3 of the protocol (prop224). */
 +#define HS_VERSION_THREE 3
 +
 +/** Try to maintain this many intro points per service by default. */
 +#define NUM_INTRO_POINTS_DEFAULT 3
 +/** Maximum number of intro points per service. */
 +#define NUM_INTRO_POINTS_MAX 10
 +/** Number of extra intro points we launch if our set of intro nodes is empty.
 + * See proposal 155, section 4. */
 +#define NUM_INTRO_POINTS_EXTRA 2
 +
 +/** If we can't build our intro circuits, don't retry for this long. */
 +#define INTRO_CIRC_RETRY_PERIOD (60*5)
 +/** Don't try to build more than this many circuits before giving up for a
 + * while.*/
 +#define MAX_INTRO_CIRCS_PER_PERIOD 10
 +/** How many times will a hidden service operator attempt to connect to a
 + * requested rendezvous point before giving up? */
 +#define MAX_REND_FAILURES 1
 +/** How many seconds should we spend trying to connect to a requested
 + * rendezvous point before giving up? */
 +#define MAX_REND_TIMEOUT 30
 +
 +/* String prefix for the signature of ESTABLISH_INTRO */
 +#define ESTABLISH_INTRO_SIG_PREFIX "Tor establish-intro cell v1"
 +
 +/* The default HS time period length */
 +#define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */
 +/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
 +#define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */
 +/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
 +#define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */
 +/* The time period rotation offset as seen in prop224 section [TIME-PERIODS] */
 +#define HS_TIME_PERIOD_ROTATION_OFFSET (12 * 60) /* minutes */
 +
 +int hs_check_service_private_dir(const char *username, const char *path,
 +                                 unsigned int dir_group_readable,
 +                                 unsigned int create);
++int hs_get_service_max_rend_failures(void);
 +
 +void rend_data_free(rend_data_t *data);
 +rend_data_t *rend_data_dup(const rend_data_t *data);
 +rend_data_t *rend_data_client_create(const char *onion_address,
 +                                     const char *desc_id,
 +                                     const char *cookie,
 +                                     rend_auth_type_t auth_type);
 +rend_data_t *rend_data_service_create(const char *onion_address,
 +                                      const char *pk_digest,
 +                                      const uint8_t *cookie,
 +                                      rend_auth_type_t auth_type);
 +const char *rend_data_get_address(const rend_data_t *rend_data);
 +const char *rend_data_get_desc_id(const rend_data_t *rend_data,
 +                                  uint8_t replica, size_t *len_out);
 +const uint8_t *rend_data_get_pk_digest(const rend_data_t *rend_data,
 +                                       size_t *len_out);
 +
 +uint64_t hs_get_next_time_period_num(time_t now);
 +
 +#ifdef HS_COMMON_PRIVATE
 +
 +#ifdef TOR_UNIT_TESTS
 +
 +STATIC uint64_t get_time_period_length(void);
 +STATIC uint64_t get_time_period_num(time_t now);
 +
 +#endif /* TOR_UNIT_TESTS */
 +
 +#endif /* HS_COMMON_PRIVATE */
 +
 +#endif /* TOR_HS_COMMON_H */
 +
diff --cc src/or/hs_service.c
index 205ef11c9,000000000..b3eec1304
mode 100644,000000..100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@@ -1,174 -1,0 +1,175 @@@
 +/* Copyright (c) 2016-2017, The Tor Project, Inc. */
 +/* See LICENSE for licensing information */
 +
 +/**
 + * \file hs_service.c
 + * \brief Implement next generation hidden service functionality
 + **/
 +
 +#include "or.h"
 +#include "relay.h"
 +#include "rendservice.h"
 +#include "circuitlist.h"
 +#include "circpathbias.h"
++#include "networkstatus.h"
 +
 +#include "hs_intropoint.h"
 +#include "hs_service.h"
 +#include "hs_common.h"
 +
 +#include "hs/cell_establish_intro.h"
 +#include "hs/cell_common.h"
 +
 +/* XXX We don't currently use these functions, apart from generating unittest
 +   data. When we start implementing the service-side support for prop224 we
 +   should revisit these functions and use them. */
 +
 +/** Given an ESTABLISH_INTRO <b>cell</b>, encode it and place its payload in
 + *  <b>buf_out</b> which has size <b>buf_out_len</b>. Return the number of
 + *  bytes written, or a negative integer if there was an error. */
 +ssize_t
 +get_establish_intro_payload(uint8_t *buf_out, size_t buf_out_len,
 +                            const trn_cell_establish_intro_t *cell)
 +{
 +  ssize_t bytes_used = 0;
 +
 +  if (buf_out_len < RELAY_PAYLOAD_SIZE) {
 +    return -1;
 +  }
 +
 +  bytes_used = trn_cell_establish_intro_encode(buf_out, buf_out_len,
 +                                              cell);
 +  return bytes_used;
 +}
 +
 +/* Set the cell extensions of <b>cell</b>. */
 +static void
 +set_trn_cell_extensions(trn_cell_establish_intro_t *cell)
 +{
 +  trn_cell_extension_t *trn_cell_extensions = trn_cell_extension_new();
 +
 +  /* For now, we don't use extensions at all. */
 +  trn_cell_extensions->num = 0; /* It's already zeroed, but be explicit. */
 +  trn_cell_establish_intro_set_extensions(cell, trn_cell_extensions);
 +}
 +
 +/** Given the circuit handshake info in <b>circuit_key_material</b>, create and
 + *  return an ESTABLISH_INTRO cell. Return NULL if something went wrong.  The
 + *  returned cell is allocated on the heap and it's the responsibility of the
 + *  caller to free it. */
 +trn_cell_establish_intro_t *
 +generate_establish_intro_cell(const uint8_t *circuit_key_material,
 +                              size_t circuit_key_material_len)
 +{
 +  trn_cell_establish_intro_t *cell = NULL;
 +  ssize_t encoded_len;
 +
 +  log_warn(LD_GENERAL,
 +           "Generating ESTABLISH_INTRO cell (key_material_len: %u)",
 +           (unsigned) circuit_key_material_len);
 +
 +  /* Generate short-term keypair for use in ESTABLISH_INTRO */
 +  ed25519_keypair_t key_struct;
 +  if (ed25519_keypair_generate(&key_struct, 0) < 0) {
 +    goto err;
 +  }
 +
 +  cell = trn_cell_establish_intro_new();
 +
 +  /* Set AUTH_KEY_TYPE: 2 means ed25519 */
 +  trn_cell_establish_intro_set_auth_key_type(cell,
 +                                             HS_INTRO_AUTH_KEY_TYPE_ED25519);
 +
 +  /* Set AUTH_KEY_LEN field */
 +  /* Must also set byte-length of AUTH_KEY to match */
 +  int auth_key_len = ED25519_PUBKEY_LEN;
 +  trn_cell_establish_intro_set_auth_key_len(cell, auth_key_len);
 +  trn_cell_establish_intro_setlen_auth_key(cell, auth_key_len);
 +
 +  /* Set AUTH_KEY field */
 +  uint8_t *auth_key_ptr = trn_cell_establish_intro_getarray_auth_key(cell);
 +  memcpy(auth_key_ptr, key_struct.pubkey.pubkey, auth_key_len);
 +
 +  /* No cell extensions needed */
 +  set_trn_cell_extensions(cell);
 +
 +  /* Set signature size.
 +     We need to do this up here, because _encode() needs it and we need to call
 +     _encode() to calculate the MAC and signature.
 +  */
 +  int sig_len = ED25519_SIG_LEN;
 +  trn_cell_establish_intro_set_sig_len(cell, sig_len);
 +  trn_cell_establish_intro_setlen_sig(cell, sig_len);
 +
 +  /* XXX How to make this process easier and nicer? */
 +
 +  /* Calculate the cell MAC (aka HANDSHAKE_AUTH). */
 +  {
 +    /* To calculate HANDSHAKE_AUTH, we dump the cell in bytes, and then derive
 +       the MAC from it. */
 +    uint8_t cell_bytes_tmp[RELAY_PAYLOAD_SIZE] = {0};
 +    uint8_t mac[TRUNNEL_SHA3_256_LEN];
 +
 +    encoded_len = trn_cell_establish_intro_encode(cell_bytes_tmp,
 +                                                 sizeof(cell_bytes_tmp),
 +                                                 cell);
 +    if (encoded_len < 0) {
 +      log_warn(LD_OR, "Unable to pre-encode ESTABLISH_INTRO cell.");
 +      goto err;
 +    }
 +
 +    /* sanity check */
 +    tor_assert(encoded_len > ED25519_SIG_LEN + 2 + TRUNNEL_SHA3_256_LEN);
 +
 +    /* Calculate MAC of all fields before HANDSHAKE_AUTH */
 +    crypto_mac_sha3_256(mac, sizeof(mac),
 +                        circuit_key_material, circuit_key_material_len,
 +                        cell_bytes_tmp,
 +                        encoded_len -
 +                          (ED25519_SIG_LEN + 2 + TRUNNEL_SHA3_256_LEN));
 +    /* Write the MAC to the cell */
 +    uint8_t *handshake_ptr =
 +      trn_cell_establish_intro_getarray_handshake_mac(cell);
 +    memcpy(handshake_ptr, mac, sizeof(mac));
 +  }
 +
 +  /* Calculate the cell signature */
 +  {
 +    /* To calculate the sig we follow the same procedure as above. We first
 +       dump the cell up to the sig, and then calculate the sig */
 +    uint8_t cell_bytes_tmp[RELAY_PAYLOAD_SIZE] = {0};
 +    ed25519_signature_t sig;
 +
 +    encoded_len = trn_cell_establish_intro_encode(cell_bytes_tmp,
 +                                                 sizeof(cell_bytes_tmp),
 +                                                 cell);
 +    if (encoded_len < 0) {
 +      log_warn(LD_OR, "Unable to pre-encode ESTABLISH_INTRO cell (2).");
 +      goto err;
 +    }
 +
 +    tor_assert(encoded_len > ED25519_SIG_LEN);
 +
 +    if (ed25519_sign_prefixed(&sig,
 +                              cell_bytes_tmp,
 +                              encoded_len -
 +                                (ED25519_SIG_LEN + sizeof(cell->sig_len)),
 +                              ESTABLISH_INTRO_SIG_PREFIX,
 +                              &key_struct)) {
 +      log_warn(LD_BUG, "Unable to gen signature for ESTABLISH_INTRO cell.");
 +      goto err;
 +    }
 +
 +    /* And write the signature to the cell */
 +    uint8_t *sig_ptr = trn_cell_establish_intro_getarray_sig(cell);
 +    memcpy(sig_ptr, sig.sig, sig_len);
 +  }
 +
 +  /* We are done! Return the cell! */
 +  return cell;
 +
 + err:
 +  trn_cell_establish_intro_free(cell);
 +  return NULL;
 +}
 +
diff --cc src/or/rendservice.c
index b1e8a2f0c,da200d138..2a3594918
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@@ -2159,7 -2041,8 +2159,8 @@@ rend_service_receive_introduction(origi
  
    /* Launch a circuit to the client's chosen rendezvous point.
     */
-   for (i=0;i<MAX_REND_FAILURES;i++) {
 -  int max_rend_failures=get_max_rend_failures();
++  int max_rend_failures=hs_get_service_max_rend_failures();
+   for (i=0;i<max_rend_failures;i++) {
      int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL;
      if (circ_needs_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
      /* A Single Onion Service only uses a direct connection if its
@@@ -3067,8 -2944,13 +3068,13 @@@ rend_service_relaunch_rendezvous(origin
    }
    oldcirc->hs_service_side_rend_circ_has_been_relaunched = 1;
  
 -  /* We check failure_count >= get_max_rend_failures()-1 below, and the -1
 -   * is because we increment the failure count for our current failure
++  /* We check failure_count >= hs_get_service_max_rend_failures()-1 below, and
++   * the -1 is because we increment the failure count for our current failure
+    * *after* this clause. */
 -  int max_rend_failures = get_max_rend_failures() - 1;
++  int max_rend_failures = hs_get_service_max_rend_failures() - 1;
+ 
    if (!oldcirc->build_state ||
-       oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
+       oldcirc->build_state->failure_count >= max_rend_failures ||
        oldcirc->build_state->expiry_time < time(NULL)) {
      log_info(LD_REND,
               "Attempt to build circuit to %s for rendezvous has failed "





More information about the tor-commits mailing list