예제 #1
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);
}
예제 #2
0
static void
test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data)
{
  (void)data;

  rend_cache_store_status_t ret;
  rend_service_descriptor_t *generated = NULL;
  smartlist_t *descs = smartlist_new();
  time_t t;
  char *service_id = NULL;
  rend_encoded_v2_service_descriptor_t *desc_holder_one = NULL;
  rend_encoded_v2_service_descriptor_t *desc_holder_two = NULL;

  NS_MOCK(router_get_my_routerinfo);
  NS_MOCK(hid_serv_responsible_for_desc_id);

  rend_cache_init();

  t = time(NULL);

  create_descriptor(&generated, &service_id, 3);
  generated->timestamp = t + RECENT_TIME;
  rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0,
                             REND_NO_AUTH, NULL, NULL);
  desc_holder_one = ((rend_encoded_v2_service_descriptor_t *)
                     smartlist_get(descs, 0));
  smartlist_set(descs, 0, NULL);

  SMARTLIST_FOREACH(descs, rend_encoded_v2_service_descriptor_t *, d,
                    rend_encoded_v2_service_descriptor_free(d));
  smartlist_free(descs);
  descs = smartlist_new();

  generated->timestamp = t + RECENT_TIME;
  generated->protocols = 41;
  rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0,
                             REND_NO_AUTH, NULL, NULL);
  desc_holder_two = ((rend_encoded_v2_service_descriptor_t *)
                     smartlist_get(descs, 0));
  smartlist_set(descs, 0, NULL);

  // Test when we have another descriptor stored, with a different descriptor
  mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
  hid_serv_responsible_for_desc_id_response = 1;
  rend_cache_store_v2_desc_as_dir(desc_holder_one->desc_str);
  ret = rend_cache_store_v2_desc_as_dir(desc_holder_two->desc_str);
  tt_int_op(ret, OP_EQ, RCS_OKAY);

 done:
  NS_UNMOCK(router_get_my_routerinfo);
  NS_UNMOCK(hid_serv_responsible_for_desc_id);
  rend_cache_free_all();
  rend_service_descriptor_free(generated);
  tor_free(service_id);
  SMARTLIST_FOREACH(descs, rend_encoded_v2_service_descriptor_t *, d,
                    rend_encoded_v2_service_descriptor_free(d));
  smartlist_free(descs);
  rend_encoded_v2_service_descriptor_free(desc_holder_one);
  rend_encoded_v2_service_descriptor_free(desc_holder_two);
}
예제 #3
0
파일: rendcache.c 프로젝트: ageis/tor
/** Helper: free storage held by a single service descriptor cache entry. */
STATIC void
rend_cache_entry_free_(rend_cache_entry_t *e)
{
  if (!e)
    return;
  rend_cache_decrement_allocation(rend_cache_entry_allocation(e));
  /* We are about to remove a descriptor from the cache so remove the entry
   * in the failure cache. */
  rend_cache_failure_remove(e->parsed);
  rend_service_descriptor_free(e->parsed);
  tor_free(e->desc);
  tor_free(e);
}
예제 #4
0
파일: fuzz_hsdescv2.c 프로젝트: Samdney/tor
int
fuzz_main(const uint8_t *data, size_t sz)
{
  rend_service_descriptor_t *desc = NULL;
  char desc_id[64];
  char *ipts = NULL;
  size_t ipts_size, esize;
  const char *next;
  char *str = tor_memdup_nulterm(data, sz);
  (void) rend_parse_v2_service_descriptor(&desc, desc_id, &ipts, &ipts_size,
                                          &esize, &next, str, 1);
  if (desc) {
    log_debug(LD_GENERAL, "Parsing okay");
    rend_service_descriptor_free(desc);
  } else {
    log_debug(LD_GENERAL, "Parsing failed");
  }
  tor_free(ipts);
  tor_free(str);
  return 0;
}
예제 #5
0
static void
test_rend_cache_failure_remove(void *data)
{
  rend_service_descriptor_t *desc;
  (void)data;

  rend_cache_init();

  // Test that it deals well with a NULL desc
  rend_cache_failure_remove(NULL);

  // Test a descriptor that isn't in the cache
  desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
  desc->pk = pk_generate(0);
  rend_cache_failure_remove(desc);

  // There seems to not exist any way of getting rend_cache_failure_remove()
  // to fail because of a problem with rend_get_service_id from here
  rend_cache_free_all();

  rend_service_descriptor_free(desc);
 /* done: */
 /*  (void)0; */
}
예제 #6
0
static void
test_rend_cache_store_v2_desc_as_dir_with_different_time(void *data)
{
  (void)data;

  int ret;
  rend_service_descriptor_t *generated = NULL;
  smartlist_t *descs = smartlist_new();
  time_t t;
  char *service_id = NULL;
  rend_encoded_v2_service_descriptor_t *desc_holder_newer;
  rend_encoded_v2_service_descriptor_t *desc_holder_older;

  NS_MOCK(router_get_my_routerinfo);

  rend_cache_init();

  t = time(NULL);

  create_descriptor(&generated, &service_id, 3);
  generated->timestamp = t + RECENT_TIME;
  rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0,
                             REND_NO_AUTH, NULL, NULL);
  desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *)
                       smartlist_get(descs, 0));
  smartlist_set(descs, 0, NULL);
  SMARTLIST_FOREACH(descs, rend_encoded_v2_service_descriptor_t *, d,
                    rend_encoded_v2_service_descriptor_free(d));
  smartlist_free(descs);
  descs = smartlist_new();

  generated->timestamp = (t + RECENT_TIME) - 20;
  rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0,
                             REND_NO_AUTH, NULL, NULL);
  desc_holder_older = ((rend_encoded_v2_service_descriptor_t *)
                       smartlist_get(descs, 0));
  smartlist_set(descs, 0, NULL);

  // Test when we have a newer descriptor stored
  mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
  rend_cache_store_v2_desc_as_dir(desc_holder_newer->desc_str);
  ret = rend_cache_store_v2_desc_as_dir(desc_holder_older->desc_str);
  tt_int_op(ret, OP_EQ, 0);

  // Test when we have an old descriptor stored
  rend_cache_purge();
  rend_cache_store_v2_desc_as_dir(desc_holder_older->desc_str);
  ret = rend_cache_store_v2_desc_as_dir(desc_holder_newer->desc_str);
  tt_int_op(ret, OP_EQ, 0);

 done:
  NS_UNMOCK(router_get_my_routerinfo);
  rend_cache_free_all();
  rend_service_descriptor_free(generated);
  tor_free(service_id);
  SMARTLIST_FOREACH(descs, rend_encoded_v2_service_descriptor_t *, d,
                    rend_encoded_v2_service_descriptor_free(d));
  smartlist_free(descs);
  rend_encoded_v2_service_descriptor_free(desc_holder_newer);
  rend_encoded_v2_service_descriptor_free(desc_holder_older);
  tor_free(mock_routerinfo);
}
예제 #7
0
static void
test_rend_cache_store_v2_desc_as_client_with_different_time(void *data)
{
  int ret;
  rend_data_t *mock_rend_query;
  char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
  rend_service_descriptor_t *generated = NULL;
  smartlist_t *descs = smartlist_new();
  time_t t;
  char *service_id = NULL;
  rend_encoded_v2_service_descriptor_t *desc_holder_newer;
  rend_encoded_v2_service_descriptor_t *desc_holder_older;

  t = time(NULL);
  rend_cache_init();

  create_descriptor(&generated, &service_id, 3);

  generated->timestamp = t + RECENT_TIME;
  rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0,
                             REND_NO_AUTH, NULL, NULL);
  desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *)
                       smartlist_get(descs, 0));
  smartlist_set(descs, 0, NULL);

  SMARTLIST_FOREACH(descs, rend_encoded_v2_service_descriptor_t *, d,
                    rend_encoded_v2_service_descriptor_free(d));
  smartlist_free(descs);
  descs = smartlist_new();

  generated->timestamp = (t + RECENT_TIME) - 20;
  rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0,
                             REND_NO_AUTH, NULL, NULL);
  desc_holder_older = ((rend_encoded_v2_service_descriptor_t *)
                       smartlist_get(descs, 0));
  smartlist_set(descs, 0, NULL);
  (void)data;

  // Test when a descriptor is already in the cache and it is newer than the
  // one we submit
  mock_rend_query = mock_rend_data(service_id);
  base32_encode(desc_id_base32, sizeof(desc_id_base32),
                desc_holder_newer->desc_id, DIGEST_LEN);
  rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str,
                                     desc_id_base32, mock_rend_query, NULL);
  ret = rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str,
                                           desc_id_base32, mock_rend_query,
                                           NULL);
  tt_int_op(ret, OP_EQ, 0);

  rend_cache_free_all();

  // Test when an old descriptor is in the cache and we submit a newer one
  rend_cache_init();
  rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str,
                                     desc_id_base32, mock_rend_query, NULL);
  ret = rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str,
                                           desc_id_base32, mock_rend_query,
                                           NULL);
  tt_int_op(ret, OP_EQ, 0);

 done:
  rend_encoded_v2_service_descriptor_free(desc_holder_newer);
  rend_encoded_v2_service_descriptor_free(desc_holder_older);
  SMARTLIST_FOREACH(descs, rend_encoded_v2_service_descriptor_t *, d,
                    rend_encoded_v2_service_descriptor_free(d));
  smartlist_free(descs);
  rend_service_descriptor_free(generated);
  tor_free(service_id);
  rend_cache_free_all();
  rend_data_free(mock_rend_query);
}
예제 #8
0
파일: rendparse.c 프로젝트: unixninja92/Tor
/** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
 * encrypted introduction points to the newly allocated
 * *<b>intro_points_encrypted_out</b>, their encrypted size to
 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
 * and -1 for failure.
 *
 * If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should
 * be strict about time formats.
 */
int
rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
                                 char *desc_id_out,
                                 char **intro_points_encrypted_out,
                                 size_t *intro_points_encrypted_size_out,
                                 size_t *encoded_size_out,
                                 const char **next_out, const char *desc,
                                 int as_hsdir)
{
  rend_service_descriptor_t *result =
                            tor_malloc_zero(sizeof(rend_service_descriptor_t));
  char desc_hash[DIGEST_LEN];
  const char *eos;
  smartlist_t *tokens = smartlist_new();
  directory_token_t *tok;
  char secret_id_part[DIGEST_LEN];
  int i, version, num_ok=1;
  smartlist_t *versions;
  char public_key_hash[DIGEST_LEN];
  char test_desc_id[DIGEST_LEN];
  memarea_t *area = NULL;
  const int strict_time_fmt = as_hsdir;

  tor_assert(desc);
  /* Check if desc starts correctly. */
  if (strcmpstart(desc, "rendezvous-service-descriptor ")) {
    log_info(LD_REND, "Descriptor does not start correctly.");
    goto err;
  }
  /* Compute descriptor hash for later validation. */
  if (router_get_hash_impl(desc, strlen(desc), desc_hash,
                           "rendezvous-service-descriptor ",
                           "\nsignature", '\n', DIGEST_SHA1) < 0) {
    log_warn(LD_REND, "Couldn't compute descriptor hash.");
    goto err;
  }
  /* Determine end of string. */
  eos = strstr(desc, "\nrendezvous-service-descriptor ");
  if (!eos)
    eos = desc + strlen(desc);
  else
    eos = eos + 1;
  /* Check length. */
  if (eos-desc > REND_DESC_MAX_SIZE) {
    /* XXXX+ If we are parsing this descriptor as a server, this
     * should be a protocol warning. */
    log_warn(LD_REND, "Descriptor length is %d which exceeds "
             "maximum rendezvous descriptor size of %d bytes.",
             (int)(eos-desc), REND_DESC_MAX_SIZE);
    goto err;
  }
  /* Tokenize descriptor. */
  area = memarea_new();
  if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
    log_warn(LD_REND, "Error tokenizing descriptor.");
    goto err;
  }
  /* Set next to next descriptor, if available. */
  *next_out = eos;
  /* Set length of encoded descriptor. */
  *encoded_size_out = eos - desc;
  /* Check min allowed length of token list. */
  if (smartlist_len(tokens) < 7) {
    log_warn(LD_REND, "Impossibly short descriptor.");
    goto err;
  }
  /* Parse base32-encoded descriptor ID. */
  tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
  tor_assert(tok == smartlist_get(tokens, 0));
  tor_assert(tok->n_args == 1);
  if (!rend_valid_descriptor_id(tok->args[0])) {
    log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
    goto err;
  }
  if (base32_decode(desc_id_out, DIGEST_LEN,
                    tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
    log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
             tok->args[0]);
    goto err;
  }
  /* Parse descriptor version. */
  tok = find_by_keyword(tokens, R_VERSION);
  tor_assert(tok->n_args == 1);
  result->version =
    (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
  if (result->version != 2 || !num_ok) {
    /* If it's <2, it shouldn't be under this format.  If the number
     * is greater than 2, we bumped it because we broke backward
     * compatibility.  See how version numbers in our other formats
     * work. */
    log_warn(LD_REND, "Unrecognized descriptor version: %s",
             escaped(tok->args[0]));
    goto err;
  }
  /* Parse public key. */
  tok = find_by_keyword(tokens, R_PERMANENT_KEY);
  result->pk = tok->key;
  tok->key = NULL; /* Prevent free */
  /* Parse secret ID part. */
  tok = find_by_keyword(tokens, R_SECRET_ID_PART);
  tor_assert(tok->n_args == 1);
  if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
      strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
    log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
    goto err;
  }
  if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
    log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
             tok->args[0]);
    goto err;
  }
  /* Parse publication time -- up-to-date check is done when storing the
   * descriptor. */
  tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
  tor_assert(tok->n_args == 1);
  if (parse_iso_time_(tok->args[0], &result->timestamp,
                      strict_time_fmt, 0) < 0) {
    log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
    goto err;
  }
  /* Parse protocol versions. */
  tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
  tor_assert(tok->n_args == 1);
  versions = smartlist_new();
  smartlist_split_string(versions, tok->args[0], ",",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  for (i = 0; i < smartlist_len(versions); i++) {
    version = (int) tor_parse_long(smartlist_get(versions, i),
                                   10, 0, INT_MAX, &num_ok, NULL);
    if (!num_ok) /* It's a string; let's ignore it. */
      continue;
    if (version >= REND_PROTOCOL_VERSION_BITMASK_WIDTH)
      /* Avoid undefined left-shift behaviour. */
      continue;
    result->protocols |= 1 << version;
  }
  SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
  smartlist_free(versions);
  /* Parse encrypted introduction points. Don't verify. */
  tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
  if (tok) {
    if (strcmp(tok->object_type, "MESSAGE")) {
      log_warn(LD_DIR, "Bad object type: introduction points should be of "
               "type MESSAGE");
      goto err;
    }
    *intro_points_encrypted_out = tor_memdup(tok->object_body,
                                             tok->object_size);
    *intro_points_encrypted_size_out = tok->object_size;
  } else {
    *intro_points_encrypted_out = NULL;
    *intro_points_encrypted_size_out = 0;
  }
  /* Parse and verify signature. */
  tok = find_by_keyword(tokens, R_SIGNATURE);
  if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0,
                            "v2 rendezvous service descriptor") < 0)
    goto err;
  /* Verify that descriptor ID belongs to public key and secret ID part. */
  if (crypto_pk_get_digest(result->pk, public_key_hash) < 0) {
    log_warn(LD_REND, "Unable to compute rend descriptor public key digest");
    goto err;
  }
  rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
                               secret_id_part);
  if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) {
    log_warn(LD_REND, "Parsed descriptor ID does not match "
             "computed descriptor ID.");
    goto err;
  }
  goto done;
 err:
  rend_service_descriptor_free(result);
  result = NULL;
 done:
  if (tokens) {
    SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
    smartlist_free(tokens);
  }
  if (area)
    memarea_drop_all(area);
  *parsed_out = result;
  if (result)
    return 0;
  return -1;
}