Commit 9192e592 authored by George Kadianakis's avatar George Kadianakis Committed by Nick Mathewson
Browse files

prop224 prepwork: Use of HS circuitmap in existing HS code.

The new HS circuitmap API replaces old public functions as follows:
   circuit_clear_rend_token -> hs_circuitmap_remove_circuit
   circuit_get_rendezvous -> hs_circuitmap_get_rend_circ
   circuit_get_intro_point -> hs_circuitmap_get_intro_circ_v2
   circuit_set_rendezvous_cookie -> hs_circuitmap_register_rend_circ
   circuit_set_intro_point_digest -> hs_circuitmap_register_intro_circ_v2

This commit also removes the old rendinfo code that is now unused.
It also fixes the broken rendinfo unittests.
parent 2b9abbef
Loading
Loading
Loading
Loading
+4 −175
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@
#include "connection_edge.h"
#include "connection_or.h"
#include "control.h"
#include "hs_circuitmap.h"
#include "main.h"
#include "hs_common.h"
#include "networkstatus.h"
@@ -93,9 +94,6 @@ static smartlist_t *circuits_pending_close = NULL;

static void circuit_free_cpath_node(crypt_path_t *victim);
static void cpath_ref_decref(crypt_path_reference_t *cpath_ref);
//static void circuit_set_rend_token(or_circuit_t *circ, int is_rend_circ,
//                                   const uint8_t *token);
static void circuit_clear_rend_token(or_circuit_t *circ);
static void circuit_about_to_free_atexit(circuit_t *circ);
static void circuit_about_to_free(circuit_t *circ);

@@ -866,7 +864,9 @@ circuit_free(circuit_t *circ)
    crypto_cipher_free(ocirc->n_crypto);
    crypto_digest_free(ocirc->n_digest);

    circuit_clear_rend_token(ocirc);
    if (ocirc->hs_token) {
      hs_circuitmap_remove_circuit(ocirc);
    }

    if (ocirc->rend_splice) {
      or_circuit_t *other = ocirc->rend_splice;
@@ -1409,177 +1409,6 @@ circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
  return NULL;
}

/** Map from rendezvous cookie to or_circuit_t */
static digestmap_t *rend_cookie_map = NULL;

/** Map from introduction point digest to or_circuit_t */
static digestmap_t *intro_digest_map = NULL;

/** Return the OR circuit whose purpose is <b>purpose</b>, and whose
 * rend_token is the REND_TOKEN_LEN-byte <b>token</b>. If <b>is_rend_circ</b>,
 * look for rendezvous point circuits; otherwise look for introduction point
 * circuits. */
static or_circuit_t *
circuit_get_by_rend_token_and_purpose(uint8_t purpose, int is_rend_circ,
                                      const char *token)
{
  or_circuit_t *circ;
  digestmap_t *map = is_rend_circ ? rend_cookie_map : intro_digest_map;

  if (!map)
    return NULL;

  circ = digestmap_get(map, token);
  if (!circ ||
      circ->base_.purpose != purpose ||
      circ->base_.marked_for_close)
    return NULL;

  if (!circ->rendinfo) {
    char *t = tor_strdup(hex_str(token, REND_TOKEN_LEN));
    log_warn(LD_BUG, "Wanted a circuit with %s:%d, but lookup returned a "
             "circuit with no rendinfo set.",
             safe_str(t), is_rend_circ);
    tor_free(t);
    return NULL;
  }

  if (! bool_eq(circ->rendinfo->is_rend_circ, is_rend_circ) ||
      tor_memneq(circ->rendinfo->rend_token, token, REND_TOKEN_LEN)) {
    char *t = tor_strdup(hex_str(token, REND_TOKEN_LEN));
    log_warn(LD_BUG, "Wanted a circuit with %s:%d, but lookup returned %s:%d",
             safe_str(t), is_rend_circ,
             safe_str(hex_str(circ->rendinfo->rend_token, REND_TOKEN_LEN)),
             (int)circ->rendinfo->is_rend_circ);
    tor_free(t);
    return NULL;
  }

  return circ;
}

/** Clear the rendezvous cookie or introduction point key digest that's
 * configured on <b>circ</b>, if any, and remove it from any such maps. */
static void
circuit_clear_rend_token(or_circuit_t *circ)
{
  or_circuit_t *found_circ;
  digestmap_t *map;

  if (!circ || !circ->rendinfo)
    return;

  map = circ->rendinfo->is_rend_circ ? rend_cookie_map : intro_digest_map;

  if (!map) {
    log_warn(LD_BUG, "Tried to clear rend token on circuit, but found no map");
    return;
  }

  found_circ = digestmap_get(map, circ->rendinfo->rend_token);
  if (found_circ == circ) {
    /* Great, this is the right one. */
    digestmap_remove(map, circ->rendinfo->rend_token);
  } else if (found_circ) {
    log_warn(LD_BUG, "Tried to clear rend token on circuit, but "
             "it was already replaced in the map.");
  } else {
    log_warn(LD_BUG, "Tried to clear rend token on circuit, but "
             "it not in the map at all.");
  }

  tor_free(circ->rendinfo); /* Sets it to NULL too */
}

/** Set the rendezvous cookie (if is_rend_circ), or the introduction point
 * digest (if ! is_rend_circ) of <b>circ</b> to the REND_TOKEN_LEN-byte value
 * in <b>token</b>, and add it to the appropriate map.  If it previously had a
 * token, clear it.  If another circuit previously had the same
 * cookie/intro-digest, mark that circuit and remove it from the map. */
static void
circuit_set_rend_token(or_circuit_t *circ, int is_rend_circ,
                       const uint8_t *token)
{
  digestmap_t **map_p, *map;
  or_circuit_t *found_circ;

  /* Find the right map, creating it as needed */
  map_p = is_rend_circ ? &rend_cookie_map : &intro_digest_map;

  if (!*map_p)
    *map_p = digestmap_new();

  map = *map_p;

  /* If this circuit already has a token, we need to remove that. */
  if (circ->rendinfo)
    circuit_clear_rend_token(circ);

  if (token == NULL) {
    /* We were only trying to remove this token, not set a new one. */
    return;
  }

  found_circ = digestmap_get(map, (const char *)token);
  if (found_circ) {
    tor_assert(found_circ != circ);
    circuit_clear_rend_token(found_circ);
    if (! found_circ->base_.marked_for_close) {
      circuit_mark_for_close(TO_CIRCUIT(found_circ), END_CIRC_REASON_FINISHED);
      if (is_rend_circ) {
        log_fn(LOG_PROTOCOL_WARN, LD_REND,
               "Duplicate rendezvous cookie (%s...) used on two circuits",
               hex_str((const char*)token, 4)); /* only log first 4 chars */
      }
    }
  }

  /* Now set up the rendinfo */
  circ->rendinfo = tor_malloc(sizeof(*circ->rendinfo));
  memcpy(circ->rendinfo->rend_token, token, REND_TOKEN_LEN);
  circ->rendinfo->is_rend_circ = is_rend_circ ? 1 : 0;

  digestmap_set(map, (const char *)token, circ);
}

/** Return the circuit waiting for a rendezvous with the provided cookie.
 * Return NULL if no such circuit is found.
 */
or_circuit_t *
circuit_get_rendezvous(const uint8_t *cookie)
{
  return circuit_get_by_rend_token_and_purpose(
                                     CIRCUIT_PURPOSE_REND_POINT_WAITING,
                                     1, (const char*)cookie);
}

/** Return the circuit waiting for intro cells of the given digest.
 * Return NULL if no such circuit is found.
 */
or_circuit_t *
circuit_get_intro_point(const uint8_t *digest)
{
  return circuit_get_by_rend_token_and_purpose(
                                     CIRCUIT_PURPOSE_INTRO_POINT, 0,
                                     (const char *)digest);
}

/** Set the rendezvous cookie of <b>circ</b> to <b>cookie</b>.  If another
 * circuit previously had that cookie, mark it. */
void
circuit_set_rendezvous_cookie(or_circuit_t *circ, const uint8_t *cookie)
{
  circuit_set_rend_token(circ, 1, cookie);
}

/** Set the intro point key digest of <b>circ</b> to <b>cookie</b>.  If another
 * circuit previously had that intro point digest, mark it. */
void
circuit_set_intro_point_digest(or_circuit_t *circ, const uint8_t *digest)
{
  circuit_set_rend_token(circ, 0, digest);
}

/** Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL,
 * has a timestamp_dirty value of 0, has flags matching the CIRCLAUNCH_*
 * flags in <b>flags</b>, and if info is defined, does not already use info
+0 −4
Original line number Diff line number Diff line
@@ -46,10 +46,6 @@ origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data(
  const rend_data_t *rend_data);
origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
                                     const uint8_t *digest, uint8_t purpose);
or_circuit_t *circuit_get_rendezvous(const uint8_t *cookie);
or_circuit_t *circuit_get_intro_point(const uint8_t *digest);
void circuit_set_rendezvous_cookie(or_circuit_t *circ, const uint8_t *cookie);
void circuit_set_intro_point_digest(or_circuit_t *circ, const uint8_t *digest);
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
                                              extend_info_t *info, int flags);
void circuit_mark_all_unused_circs(void);
+5 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@
#include "geoip.h"
#include "hibernate.h"
#include "hs_cache.h"
#include "hs_circuitmap.h"
#include "keypin.h"
#include "main.h"
#include "microdesc.h"
@@ -2400,6 +2401,9 @@ do_main_loop(void)
    }
  }

  /* Initialize relay-side HS circuitmap */
  hs_circuitmap_init();

  /* set up once-a-second callback. */
  if (! second_timer) {
    struct timeval one_second;
@@ -3108,6 +3112,7 @@ tor_free_all(int postfork)
  connection_edge_free_all();
  scheduler_free_all();
  nodelist_free_all();
  hs_circuitmap_free_all();
  microdesc_free_all();
  routerparse_free_all();
  ext_orport_free_all();
+0 −14
Original line number Diff line number Diff line
@@ -3393,25 +3393,11 @@ typedef struct or_circuit_t {
  uint32_t max_middle_cells;
} or_circuit_t;

typedef struct or_circuit_rendinfo_s {

#if REND_COOKIE_LEN != DIGEST_LEN
#error "The REND_TOKEN_LEN macro assumes REND_COOKIE_LEN == DIGEST_LEN"
#endif
#define REND_TOKEN_LEN DIGEST_LEN

  /** A hash of location-hidden service's PK if purpose is INTRO_POINT, or a
   * rendezvous cookie if purpose is REND_POINT_WAITING. Filled with zeroes
   * otherwise.
   */
  char rend_token[REND_TOKEN_LEN];

  /** True if this is a rendezvous point circuit; false if this is an
   * introduction point. */
  unsigned is_rend_circ;

} or_circuit_rendinfo_t;

/** Convert a circuit subtype to a circuit_t. */
#define TO_CIRCUIT(x)  (&((x)->base_))

+7 −7
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request,

  /* Close any other intro circuits with the same pk. */
  c = NULL;
  while ((c = circuit_get_intro_point((const uint8_t *)pk_digest))) {
  while ((c = hs_circuitmap_get_intro_circ_v2((const uint8_t *)pk_digest))) {
    log_info(LD_REND, "Replacing old circuit for service %s",
             safe_str(serviceid));
    circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
@@ -111,7 +111,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request,

  /* Now, set up this circuit. */
  circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT);
  circuit_set_intro_point_digest(circ, (uint8_t *)pk_digest);
  hs_circuitmap_register_intro_circ_v2(circ, (uint8_t *)pk_digest);

  log_info(LD_REND,
           "Established introduction point on circuit %u for service %s",
@@ -181,7 +181,7 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request,

  /* The first 20 bytes are all we look at: they have a hash of the service's
   * PK. */
  intro_circ = circuit_get_intro_point((const uint8_t*)request);
  intro_circ = hs_circuitmap_get_intro_circ_v2((const uint8_t*)request);
  if (!intro_circ) {
    log_info(LD_REND,
             "No intro circ found for INTRODUCE1 cell (%s) from circuit %u; "
@@ -258,7 +258,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
    goto err;
  }

  if (circuit_get_rendezvous(request)) {
  if (hs_circuitmap_get_rend_circ(request)) {
    log_warn(LD_PROTOCOL,
             "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
    goto err;
@@ -274,7 +274,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
  }

  circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_POINT_WAITING);
  circuit_set_rendezvous_cookie(circ, request);
  hs_circuitmap_register_rend_circ(circ, request);

  base16_encode(hexid,9,(char*)request,4);

@@ -323,7 +323,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
           "Got request for rendezvous from circuit %u to cookie %s.",
           (unsigned)circ->p_circ_id, hexid);

  rend_circ = circuit_get_rendezvous(request);
  rend_circ = hs_circuitmap_get_rend_circ(request);
  if (!rend_circ) {
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
         "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
@@ -358,7 +358,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
  circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_ESTABLISHED);
  circuit_change_purpose(TO_CIRCUIT(rend_circ),
                         CIRCUIT_PURPOSE_REND_ESTABLISHED);
  circuit_set_rendezvous_cookie(circ, NULL);
  hs_circuitmap_remove_circuit(circ);

  rend_circ->rend_splice = circ;
  circ->rend_splice = rend_circ;
Loading