Exemple #1
0
static void
test_rend_cache_failure_clean(void *data)
{
  rend_cache_failure_t *failure;
  rend_cache_failure_intro_t *ip_one, *ip_two;

  const char key_one[DIGEST_LEN] = "ip1";
  const char key_two[DIGEST_LEN] = "ip2";

  (void)data;

  rend_cache_init();

  // Test with empty failure cache
  rend_cache_failure_clean(time(NULL));
  tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0);

  // Test with one empty failure entry
  failure = rend_cache_failure_entry_new();
  strmap_set_lc(rend_cache_failure, "foo1", failure);
  rend_cache_failure_clean(time(NULL));
  tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0);

  // Test with one new intro point
  failure = rend_cache_failure_entry_new();
  ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT);
  digestmap_set(failure->intro_failures, key_one, ip_one);
  strmap_set_lc(rend_cache_failure, "foo1", failure);
  rend_cache_failure_clean(time(NULL));
  tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 1);

  // Test with one old intro point
  rend_cache_failure_purge();
  failure = rend_cache_failure_entry_new();
  ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT);
  ip_one->created_ts = time(NULL) - 7*60;
  digestmap_set(failure->intro_failures, key_one, ip_one);
  strmap_set_lc(rend_cache_failure, "foo1", failure);
  rend_cache_failure_clean(time(NULL));
  tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0);

  // Test with one old intro point and one new one
  rend_cache_failure_purge();
  failure = rend_cache_failure_entry_new();
  ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT);
  ip_one->created_ts = time(NULL) - 7*60;
  digestmap_set(failure->intro_failures, key_one, ip_one);
  ip_two = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT);
  ip_two->created_ts = time(NULL) - 2*60;
  digestmap_set(failure->intro_failures, key_two, ip_two);
  strmap_set_lc(rend_cache_failure, "foo1", failure);
  rend_cache_failure_clean(time(NULL));
  tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 1);
  tt_int_op(digestmap_size(failure->intro_failures), OP_EQ, 1);

 done:
  rend_cache_free_all();
}
int
replaycache_add_and_test_internal(
    time_t present, replaycache_t *r, const void *data, int len,
    time_t *elapsed)
{
  int rv = 0;
  char digest[DIGEST_LEN];
  time_t *access_time;

  /* sanity check */
  if (present <= 0 || !r || !data || len <= 0) {
    log_info(LD_BUG, "replaycache_add_and_test_internal() called with stupid"
        " parameters; please fix this.");
    goto done;
  }

  /* compute digest */
  crypto_digest(digest, (const char *)data, len);

  /* check map */
  access_time = digestmap_get(r->digests_seen, digest);

  /* seen before? */
  if (access_time != NULL) {
    /*
     * If it's far enough in the past, no hit.  If the horizon is zero, we
     * never expire.
     */
    if (*access_time >= present - r->horizon || r->horizon == 0) {
      /* replay cache hit, return 1 */
      rv = 1;
      /* If we want to output an elapsed time, do so */
      if (elapsed) {
        if (present >= *access_time) {
          *elapsed = present - *access_time;
        } else {
          /* We shouldn't really be seeing hits from the future, but... */
          *elapsed = 0;
        }
      }
    }
    /*
     * If it's ahead of the cached time, update
     */
    if (*access_time < present) {
      *access_time = present;
    }
  } else {
    /* No, so no hit and update the digest map with the current time */
    access_time = tor_malloc(sizeof(*access_time));
    *access_time = present;
    digestmap_set(r->digests_seen, digest, access_time);
  }

  /* now scrub the cache if it's time */
  replaycache_scrub_if_needed_internal(present, r);

 done:
  return rv;
}
Exemple #3
0
static void
test_rend_cache_validate_intro_point_failure(void *data)
{
  (void)data;
  rend_service_descriptor_t *desc = NULL;
  char *service_id = NULL;
  rend_intro_point_t *intro = NULL;
  const char *identity = NULL;
  rend_cache_failure_t *failure;
  rend_cache_failure_intro_t *ip;

  rend_cache_init();

  create_descriptor(&desc, &service_id, 3);
  desc->timestamp = time(NULL) + RECENT_TIME;

  intro = (rend_intro_point_t *)smartlist_get(desc->intro_nodes, 0);
  identity = intro->extend_info->identity_digest;

  failure = rend_cache_failure_entry_new();
  ip = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT);
  digestmap_set(failure->intro_failures, identity, ip);
  strmap_set_lc(rend_cache_failure, service_id, failure);

  // Test when we have an intro point in our cache
  validate_intro_point_failure(desc, service_id);
  tt_int_op(smartlist_len(desc->intro_nodes), OP_EQ, 2);

 done:
  rend_cache_free_all();
  rend_service_descriptor_free(desc);
  tor_free(service_id);
}
Exemple #4
0
/** If conn is listed in orconn_identity_map, remove it, and clear
 * conn->identity_digest.  Otherwise do nothing. */
void
connection_or_remove_from_identity_map(or_connection_t *conn)
{
  or_connection_t *tmp;
  tor_assert(conn);
  if (!orconn_identity_map)
    return;
  tmp = digestmap_get(orconn_identity_map, conn->identity_digest);
  if (!tmp) {
    if (!tor_digest_is_zero(conn->identity_digest)) {
      log_warn(LD_BUG, "Didn't find connection '%s' on identity map when "
               "trying to remove it.",
               conn->nickname ? conn->nickname : "NULL");
    }
    return;
  }
  if (conn == tmp) {
    if (conn->next_with_same_id)
      digestmap_set(orconn_identity_map, conn->identity_digest,
                    conn->next_with_same_id);
    else
      digestmap_remove(orconn_identity_map, conn->identity_digest);
  } else {
    while (tmp->next_with_same_id) {
      if (tmp->next_with_same_id == conn) {
        tmp->next_with_same_id = conn->next_with_same_id;
        break;
      }
      tmp = tmp->next_with_same_id;
    }
  }
  memset(conn->identity_digest, 0, DIGEST_LEN);
  conn->next_with_same_id = NULL;
}
Exemple #5
0
/** Store a measured bandwidth cache entry when reading the measured
 * bandwidths file. */
STATIC void
dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
                          time_t as_of)
{
  mbw_cache_entry_t *e = NULL;

  tor_assert(parsed_line);

  /* Allocate a cache if we need */
  if (!mbw_cache) mbw_cache = digestmap_new();

  /* Check if we have an existing entry */
  e = digestmap_get(mbw_cache, parsed_line->node_id);
  /* If we do, we can re-use it */
  if (e) {
    /* Check that we really are newer, and update */
    if (as_of > e->as_of) {
      e->mbw_kb = parsed_line->bw_kb;
      e->as_of = as_of;
    }
  } else {
    /* We'll have to insert a new entry */
    e = tor_malloc(sizeof(*e));
    e->mbw_kb = parsed_line->bw_kb;
    e->as_of = as_of;
    digestmap_set(mbw_cache, parsed_line->node_id, e);
  }
}
Exemple #6
0
/** Parse the string <b>s</b> to create a set of routerset entries, and add
 * them to <b>target</b>.  In log messages, refer to the string as
 * <b>description</b>.  Return 0 on success, -1 on failure.
 *
 * Three kinds of elements are allowed in routersets: nicknames, IP address
 * patterns, and fingerprints.  They may be surrounded by optional space, and
 * must be separated by commas.
 */
int
routerset_parse(routerset_t *target, const char *s, const char *description)
{
  int r = 0;
  int added_countries = 0;
  char *countryname;
  smartlist_t *list = smartlist_new();
  int malformed_list;
  smartlist_split_string(list, s, ",",
                         SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0);
  SMARTLIST_FOREACH_BEGIN(list, char *, nick) {
      addr_policy_t *p;
      /* if it doesn't pass our validation, assume it's malformed */
      malformed_list = 1;
      if (is_legal_hexdigest(nick)) {
        char d[DIGEST_LEN];
        if (*nick == '$')
          ++nick;
        log_debug(LD_CONFIG, "Adding identity %s to %s", nick, description);
        base16_decode(d, sizeof(d), nick, HEX_DIGEST_LEN);
        digestmap_set(target->digests, d, (void*)1);
      } else if (is_legal_nickname(nick)) {
        log_debug(LD_CONFIG, "Adding nickname %s to %s", nick, description);
        strmap_set_lc(target->names, nick, (void*)1);
      } else if ((countryname = routerset_get_countryname(nick)) != NULL) {
        log_debug(LD_CONFIG, "Adding country %s to %s", nick,
                  description);
        smartlist_add(target->country_names, countryname);
        added_countries = 1;
      } else if ((strchr(nick,'.') || strchr(nick, ':') ||  strchr(nick, '*'))
                 && (p = router_parse_addr_policy_item_from_string(
                                     nick, ADDR_POLICY_REJECT,
                                     &malformed_list))) {
        /* IPv4 addresses contain '.', IPv6 addresses contain ':',
         * and wildcard addresses contain '*'. */
        log_debug(LD_CONFIG, "Adding address %s to %s", nick, description);
        smartlist_add(target->policies, p);
      } else if (malformed_list) {
        log_warn(LD_CONFIG, "Entry '%s' in %s is malformed. Discarding entire"
                 " list.", nick, description);
        r = -1;
        tor_free(nick);
        SMARTLIST_DEL_CURRENT(list, nick);
      } else {
        log_notice(LD_CONFIG, "Entry '%s' in %s is ignored. Using the"
                   " remainder of the list.", nick, description);
        tor_free(nick);
        SMARTLIST_DEL_CURRENT(list, nick);
      }
  } SMARTLIST_FOREACH_END(nick);
Exemple #7
0
static void
NS(test_main)(void *arg)
{
  routerset_t *set = routerset_new();
  int contains;
  uint8_t bar[20] = { 9, 10, 11, 55 };
  (void)arg;

  digestmap_set(set->digests, (const char*)bar, (void *)1);
  contains = routerset_contains(set, NULL, 0, NULL, NULL, 0);
  routerset_free(set);

  tt_int_op(contains, ==, 0);
  done:
    ;
}
Exemple #8
0
static void
NS(test_main)(void *arg)
{
  routerset_t *set = routerset_new();
  int contains;
  uint8_t foo[20] = { 2, 3, 4 };
  (void)arg;

  digestmap_set(set->digests, (const char*)foo, (void *)1);
  contains = routerset_contains(set, NULL, 0, NULL, (const char*)foo, 0);
  routerset_free(set);

  tt_int_op(contains, ==, 4);
  done:
    ;
}
/* Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit
 * and there shouldn't be a commit from the same authority in the state
 * already else verification hasn't been done prior. This takes ownership of
 * the commit once in our state. */
static void
commit_add_to_state(sr_commit_t *commit, sr_state_t *state)
{
  sr_commit_t *saved_commit;

  tor_assert(commit);
  tor_assert(state);

  saved_commit = digestmap_set(state->commits, commit->rsa_identity,
                               commit);
  if (saved_commit != NULL) {
    /* This means we already have that commit in our state so adding twice
     * the same commit is either a code flow error, a corrupted disk state
     * or some new unknown issue. */
    log_warn(LD_DIR, "SR: Commit from %s exists in our state while "
                     "adding it: '%s'", sr_commit_get_rsa_fpr(commit),
                     commit->encoded_commit);
    sr_commit_free(saved_commit);
  }
}
Exemple #10
0
static void
test_rend_cache_failure_intro_lookup(void *data)
{
  (void)data;
  int ret;
  rend_cache_failure_t *failure;
  rend_cache_failure_intro_t *ip;
  rend_cache_failure_intro_t *entry;
  const char key_ip_one[DIGEST_LEN] = "ip1";
  const char key_ip_two[DIGEST_LEN] = "ip2";
  const char key_foo[DIGEST_LEN] = "foo1";

  rend_cache_init();

  failure = rend_cache_failure_entry_new();
  ip = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT);
  digestmap_set(failure->intro_failures, key_ip_one, ip);
  strmap_set_lc(rend_cache_failure, "foo1", failure);

  // Test not found
  ret = cache_failure_intro_lookup((const uint8_t *) key_foo, "foo2", NULL);
  tt_int_op(ret, OP_EQ, 0);

  // Test found with no intro failures in it
  ret = cache_failure_intro_lookup((const uint8_t *) key_ip_two, "foo1", NULL);
  tt_int_op(ret, OP_EQ, 0);

  // Test found
  ret = cache_failure_intro_lookup((const uint8_t *) key_ip_one, "foo1", NULL);
  tt_int_op(ret, OP_EQ, 1);

  // Test found and asking for entry
  cache_failure_intro_lookup((const uint8_t *) key_ip_one, "foo1", &entry);
  tt_assert(entry);
  tt_assert(entry == ip);

 done:
  rend_cache_free_all();
}
Exemple #11
0
/** Parse the string <b>s</b> to create a set of routerset entries, and add
 * them to <b>target</b>.  In log messages, refer to the string as
 * <b>description</b>.  Return 0 on success, -1 on failure.
 *
 * Three kinds of elements are allowed in routersets: nicknames, IP address
 * patterns, and fingerprints.  They may be surrounded by optional space, and
 * must be separated by commas.
 */
int
routerset_parse(routerset_t *target, const char *s, const char *description)
{
  int r = 0;
  int added_countries = 0;
  char *countryname;
  smartlist_t *list = smartlist_new();
  smartlist_split_string(list, s, ",",
                         SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0);
  SMARTLIST_FOREACH_BEGIN(list, char *, nick) {
      addr_policy_t *p;
      if (is_legal_hexdigest(nick)) {
        char d[DIGEST_LEN];
        if (*nick == '$')
          ++nick;
        log_debug(LD_CONFIG, "Adding identity %s to %s", nick, description);
        base16_decode(d, sizeof(d), nick, HEX_DIGEST_LEN);
        digestmap_set(target->digests, d, (void*)1);
      } else if (is_legal_nickname(nick)) {
        log_debug(LD_CONFIG, "Adding nickname %s to %s", nick, description);
        strmap_set_lc(target->names, nick, (void*)1);
      } else if ((countryname = routerset_get_countryname(nick)) != NULL) {
        log_debug(LD_CONFIG, "Adding country %s to %s", nick,
                  description);
        smartlist_add(target->country_names, countryname);
        added_countries = 1;
      } else if ((strchr(nick,'.') || strchr(nick, '*')) &&
                 (p = router_parse_addr_policy_item_from_string(
                                     nick, ADDR_POLICY_REJECT))) {
        log_debug(LD_CONFIG, "Adding address %s to %s", nick, description);
        smartlist_add(target->policies, p);
      } else {
        log_warn(LD_CONFIG, "Entry '%s' in %s is malformed.", nick,
                 description);
        r = -1;
        tor_free(nick);
        SMARTLIST_DEL_CURRENT(list, nick);
      }
  } SMARTLIST_FOREACH_END(nick);
Exemple #12
0
static void
test_rend_cache_clean_v2_descs_as_dir(void *data)
{
  rend_cache_entry_t *e;
  time_t now, cutoff;
  rend_service_descriptor_t *desc;
  now = time(NULL);
  cutoff = now - (REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW);
  const char key[DIGEST_LEN] = "abcde";

  (void)data;

  rend_cache_init();

  // Test running with an empty cache
  rend_cache_clean_v2_descs_as_dir(cutoff);
  tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0);

  // Test with only one new entry
  e = tor_malloc_zero(sizeof(rend_cache_entry_t));
  e->last_served = now;
  desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
  desc->timestamp = now;
  desc->pk = pk_generate(0);
  e->parsed = desc;
  digestmap_set(rend_cache_v2_dir, key, e);

  /* Set the cutoff to minus 10 seconds. */
  rend_cache_clean_v2_descs_as_dir(cutoff - 10);
  tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1);

  // Test with one old entry
  desc->timestamp = cutoff - 1000;
  rend_cache_clean_v2_descs_as_dir(cutoff);
  tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0);

 done:
  rend_cache_free_all();
}
Exemple #13
0
static void
test_rend_cache_clean_v2_descs_as_dir(void *data)
{
  rend_cache_entry_t *e;
  time_t now;
  rend_service_descriptor_t *desc;
  now = time(NULL);
  const char key[DIGEST_LEN] = "abcde";

  (void)data;

  rend_cache_init();

  // Test running with an empty cache
  rend_cache_clean_v2_descs_as_dir(now, 0);
  tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0);

  // Test with only one new entry
  e = tor_malloc_zero(sizeof(rend_cache_entry_t));
  e->last_served = now;
  desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
  desc->timestamp = now;
  desc->pk = pk_generate(0);
  e->parsed = desc;
  digestmap_set(rend_cache_v2_dir, key, e);

  rend_cache_clean_v2_descs_as_dir(now, 0);
  tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1);

  // Test with one old entry
  desc->timestamp = now - (REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW + 1000);
  rend_cache_clean_v2_descs_as_dir(now, 0);
  tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0);

  // Test with one entry that has an old last served
  e = tor_malloc_zero(sizeof(rend_cache_entry_t));
  e->last_served = now - (REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW + 1000);
  desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
  desc->timestamp = now;
  desc->pk = pk_generate(0);
  e->parsed = desc;
  digestmap_set(rend_cache_v2_dir, key, e);

  rend_cache_clean_v2_descs_as_dir(now, 0);
  tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0);

  // Test a run through asking for a large force_remove
  e = tor_malloc_zero(sizeof(rend_cache_entry_t));
  e->last_served = now;
  desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
  desc->timestamp = now;
  desc->pk = pk_generate(0);
  e->parsed = desc;
  digestmap_set(rend_cache_v2_dir, key, e);

  rend_cache_clean_v2_descs_as_dir(now, 20000);
  tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1);

 done:
  rend_cache_free_all();
}