Example #1
0
static void
test_storagedir_empty(void *arg)
{
  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  (void)arg;

  tt_int_op(FN_NOENT, OP_EQ, file_status(dirname));

  d = storage_dir_new(dirname, 10);
  tt_assert(d);

  tt_int_op(FN_DIR, OP_EQ, file_status(dirname));

  tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));

  storage_dir_free(d);
  d = storage_dir_new(dirname, 10);
  tt_assert(d);

  tt_int_op(FN_DIR, OP_EQ, file_status(dirname));

  tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));

 done:
  storage_dir_free(d);
  tor_free(dirname);
}
Example #2
0
static void
test_rend_cache_increment_allocation(void *data)
{
  (void)data;

  // Test when the cache is not overflowing
  rend_cache_total_allocation = 5;
  rend_cache_increment_allocation(3);
  tt_int_op(rend_cache_total_allocation, OP_EQ, 8);

  // Test when there are too many allocations
  rend_cache_total_allocation = SIZE_MAX-1;
  setup_full_capture_of_logs(LOG_WARN);
  rend_cache_increment_allocation(2);
  tt_u64_op(rend_cache_total_allocation, OP_EQ, SIZE_MAX);
  expect_single_log_msg_containing(
                    "Overflow in rend_cache_increment_allocation");
  teardown_capture_of_logs();

  // And again
  rend_cache_increment_allocation(2);
  tt_u64_op(rend_cache_total_allocation, OP_EQ, SIZE_MAX);

 done:
  teardown_capture_of_logs();
}
Example #3
0
static void
test_storagedir_deletion(void *arg)
{
  (void)arg;
  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  char *fn1 = NULL, *fn2 = NULL;
  char *bytes = NULL;
  int r;
  const char str1[] = "There are nine and sixty ways to disguise communiques";
  const char str2[] = "And rather more than one of them is right";

  // Make sure the directory is there. */
  d = storage_dir_new(dirname, 10);
  storage_dir_free(d);
  d = NULL;

  tor_asprintf(&fn1, "%s/1007", dirname);
  r = write_str_to_file(fn1, str1, 0);
  tt_int_op(r, OP_EQ, 0);

  tor_asprintf(&fn2, "%s/1003.tmp", dirname);
  r = write_str_to_file(fn2, str2, 0);
  tt_int_op(r, OP_EQ, 0);

  // The tempfile should be deleted the next time we list the directory.
  d = storage_dir_new(dirname, 10);
  tt_int_op(1, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(strlen(str1), OP_EQ, storage_dir_get_usage(d));
  tt_int_op(FN_FILE, OP_EQ, file_status(fn1));
  tt_int_op(FN_NOENT, OP_EQ, file_status(fn2));

  bytes = (char*) storage_dir_read(d, "1007", 1, NULL);
  tt_str_op(bytes, OP_EQ, str1);

  // Should have no effect; file already gone.
  storage_dir_remove_file(d, "1003.tmp");
  tt_int_op(1, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(strlen(str1), OP_EQ, storage_dir_get_usage(d));

  // Actually remove a file.
  storage_dir_remove_file(d, "1007");
  tt_int_op(FN_NOENT, OP_EQ, file_status(fn1));
  tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));

 done:
  tor_free(dirname);
  tor_free(fn1);
  tor_free(fn2);
  storage_dir_free(d);
  tor_free(bytes);
}
Example #4
0
static void
test_crypto_rng_range(void *arg)
{
  int got_smallest = 0, got_largest = 0;
  int i;

  (void)arg;
  for (i = 0; i < 1000; ++i) {
    int x = crypto_rand_int_range(5,9);
    tt_int_op(x, OP_GE, 5);
    tt_int_op(x, OP_LT, 9);
    if (x == 5)
      got_smallest = 1;
    if (x == 8)
      got_largest = 1;
  }
  /* These fail with probability 1/10^603. */
  tt_assert(got_smallest);
  tt_assert(got_largest);

  got_smallest = got_largest = 0;
  const uint64_t ten_billion = 10 * ((uint64_t)1000000000000);
  for (i = 0; i < 1000; ++i) {
    uint64_t x = crypto_rand_uint64_range(ten_billion, ten_billion+10);
    tt_u64_op(x, OP_GE, ten_billion);
    tt_u64_op(x, OP_LT, ten_billion+10);
    if (x == ten_billion)
      got_smallest = 1;
    if (x == ten_billion+9)
      got_largest = 1;
  }

  tt_assert(got_smallest);
  tt_assert(got_largest);

  const time_t now = time(NULL);
  for (i = 0; i < 2000; ++i) {
    time_t x = crypto_rand_time_range(now, now+60);
    tt_i64_op(x, OP_GE, now);
    tt_i64_op(x, OP_LT, now+60);
    if (x == now)
      got_smallest = 1;
    if (x == now+59)
      got_largest = 1;
  }

  tt_assert(got_smallest);
  tt_assert(got_largest);
 done:
  ;
}
Example #5
0
/** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we
 *  parse it from the receiver side. */
static void
test_gen_establish_intro_cell(void *arg)
{
  (void) arg;
  ssize_t ret;
  char circ_nonce[DIGEST_LEN] = {0};
  uint8_t buf[RELAY_PAYLOAD_SIZE];
  trn_cell_establish_intro_t *cell_in = NULL;

  crypto_rand(circ_nonce, sizeof(circ_nonce));

  /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
     attempt to parse it. */
  {
    /* We only need the auth key pair here. */
    hs_service_intro_point_t *ip = service_intro_point_new(NULL);
    /* Auth key pair is generated in the constructor so we are all set for
     * using this IP object. */
    ret = hs_cell_build_establish_intro(circ_nonce, ip, buf);
    service_intro_point_free(ip);
    tt_u64_op(ret, OP_GT, 0);
  }

  /* Check the contents of the cell */
  {
    /* First byte is the auth key type: make sure its correct */
    tt_int_op(buf[0], OP_EQ, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519);
    /* Next two bytes is auth key len */
    tt_int_op(ntohs(get_uint16(buf+1)), OP_EQ, ED25519_PUBKEY_LEN);
    /* Skip to the number of extensions: no extensions */
    tt_int_op(buf[35], OP_EQ, 0);
    /* Skip to the sig len. Make sure it's the size of an ed25519 sig */
    tt_int_op(ntohs(get_uint16(buf+35+1+32)), OP_EQ, ED25519_SIG_LEN);
  }

  /* Parse it as the receiver */
  {
    ret = trn_cell_establish_intro_parse(&cell_in, buf, sizeof(buf));
    tt_u64_op(ret, OP_GT, 0);

    ret = verify_establish_intro_cell(cell_in,
                                      (const uint8_t *) circ_nonce,
                                      sizeof(circ_nonce));
    tt_u64_op(ret, OP_EQ, 0);
  }

 done:
  trn_cell_establish_intro_free(cell_in);
}
Example #6
0
static void
test_util_format_unaligned_accessors(void *ignored)
{
  (void)ignored;
  char buf[9] = "onionsoup"; // 6f6e696f6e736f7570

  tt_u64_op(get_uint64(buf+1), OP_EQ, htonll(U64_LITERAL(0x6e696f6e736f7570)));
  tt_uint_op(get_uint32(buf+1), OP_EQ, htonl(0x6e696f6e));
  tt_uint_op(get_uint16(buf+1), OP_EQ, htons(0x6e69));
  tt_uint_op(get_uint8(buf+1), OP_EQ, 0x6e);

  set_uint8(buf+7, 0x61);
  tt_mem_op(buf, OP_EQ, "onionsoap", 9);

  set_uint16(buf+6, htons(0x746f));
  tt_mem_op(buf, OP_EQ, "onionstop", 9);

  set_uint32(buf+1, htonl(0x78696465));
  tt_mem_op(buf, OP_EQ, "oxidestop", 9);

  set_uint64(buf+1, htonll(U64_LITERAL(0x6266757363617465)));
  tt_mem_op(buf, OP_EQ, "obfuscate", 9);
 done:
  ;
}
Example #7
0
static void
test_storagedir_full(void *arg)
{
  (void)arg;

  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  const char str[] = "enemies of the peephole";
  int r;

  d = storage_dir_new(dirname, 3);
  tt_assert(d);

  r = storage_dir_save_string_to_file(d, str, 1, NULL);
  tt_int_op(r, OP_EQ, 0);
  r = storage_dir_save_string_to_file(d, str, 1, NULL);
  tt_int_op(r, OP_EQ, 0);
  r = storage_dir_save_string_to_file(d, str, 1, NULL);
  tt_int_op(r, OP_EQ, 0);

  // These should fail!
  r = storage_dir_save_string_to_file(d, str, 1, NULL);
  tt_int_op(r, OP_EQ, -1);
  r = storage_dir_save_string_to_file(d, str, 1, NULL);
  tt_int_op(r, OP_EQ, -1);

  tt_u64_op(strlen(str) * 3, OP_EQ, storage_dir_get_usage(d));

 done:
  tor_free(dirname);
  storage_dir_free(d);
}
Example #8
0
static void
test_ext_or_init_auth(void *arg)
{
  or_options_t *options = get_options_mutable();
  const char *fn;
  char *cp = NULL;
  struct stat st;
  char cookie0[32];
  (void)arg;

  /* Check default filename location */
  tor_free(options->DataDirectory);
  options->DataDirectory = tor_strdup("foo");
  cp = get_ext_or_auth_cookie_file_name();
  tt_str_op(cp, OP_EQ, "foo"PATH_SEPARATOR"extended_orport_auth_cookie");
  tor_free(cp);

  /* Shouldn't be initialized already, or our tests will be a bit
   * meaningless */
  ext_or_auth_cookie = tor_malloc_zero(32);
  tt_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32));

  /* Now make sure we use a temporary file */
  fn = get_fname("ext_cookie_file");
  options->ExtORPortCookieAuthFile = tor_strdup(fn);
  cp = get_ext_or_auth_cookie_file_name();
  tt_str_op(cp, OP_EQ, fn);
  tor_free(cp);

  /* Test the initialization function with a broken
     write_bytes_to_file(). See if the problem is handled properly. */
  MOCK(write_bytes_to_file, write_bytes_to_file_fail);
  tt_int_op(-1, OP_EQ, init_ext_or_cookie_authentication(1));
  tt_int_op(ext_or_auth_cookie_is_set, OP_EQ, 0);
  UNMOCK(write_bytes_to_file);

  /* Now do the actual initialization. */
  tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1));
  tt_int_op(ext_or_auth_cookie_is_set, OP_EQ, 1);
  cp = read_file_to_str(fn, RFTS_BIN, &st);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_u64_op((uint64_t)st.st_size, OP_EQ, 64);
  tt_mem_op(cp,OP_EQ, "! Extended ORPort Auth Cookie !\x0a", 32);
  tt_mem_op(cp+32,OP_EQ, ext_or_auth_cookie, 32);
  memcpy(cookie0, ext_or_auth_cookie, 32);
  tt_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32));

  /* Operation should be idempotent. */
  tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1));
  tt_mem_op(cookie0,OP_EQ, ext_or_auth_cookie, 32);

 done:
  tor_free(cp);
  ext_orport_free_all();
}
Example #9
0
static void
test_channel_listener(void *arg)
{
  int old_count;
  time_t now = time(NULL);
  channel_listener_t *chan = NULL;

  (void) arg;

  chan = tor_malloc_zero(sizeof(*chan));
  tt_assert(chan);
  channel_init_listener(chan);
  tt_u64_op(chan->global_identifier, OP_EQ, 1);
  tt_int_op(chan->timestamp_created, OP_GE, now);
  chan->close = test_chan_listener_close;

  /* Register it. At this point, it is not open so it will be put in the
   * finished list. */
  channel_listener_register(chan);
  tt_int_op(chan->registered, OP_EQ, 1);
  channel_listener_unregister(chan);

  /* Register it as listening now thus active. */
  chan->state = CHANNEL_LISTENER_STATE_LISTENING;
  channel_listener_register(chan);
  tt_int_op(chan->registered, OP_EQ, 1);

  /* Set the listener function. */
  channel_listener_set_listener_fn(chan, test_chan_listener_fn);
  tt_ptr_op(chan->listener, OP_EQ, test_chan_listener_fn);

  /* Put a channel in the listener incoming list and queue it.
   * function. By doing this, the listener() handler will be called. */
  channel_t *in_chan = new_fake_channel();
  old_count = test_chan_listener_fn_called;
  channel_listener_queue_incoming(chan, in_chan);
  free_fake_channel(in_chan);
  tt_int_op(test_chan_listener_fn_called, OP_EQ, old_count + 1);

  /* Put listener channel in CLOSING state. */
  old_count = test_chan_listener_close_fn_called;
  channel_listener_mark_for_close(chan);
  tt_int_op(test_chan_listener_close_fn_called, OP_EQ, old_count + 1);
  channel_listener_change_state(chan, CHANNEL_LISTENER_STATE_CLOSED);

  /* Dump stats so we at least hit the code path. */
  chan->describe_transport = test_chan_listener_describe_transport;
  /* There is a check for "now > timestamp_created" when dumping the stats so
   * make sure we go in. */
  chan->timestamp_created = now - 10;
  channel_listener_dump_statistics(chan, LOG_INFO);

 done:
  channel_free_all();
}
Example #10
0
static void
test_rend_cache_increment_allocation(void *data)
{
  (void)data;

  // Test when the cache is not overflowing
  rend_cache_total_allocation = 5;
  rend_cache_increment_allocation(3);
  tt_int_op(rend_cache_total_allocation, OP_EQ, 8);

  // Test when there are too many allocations
  rend_cache_total_allocation = SIZE_MAX-1;
  rend_cache_increment_allocation(2);
  tt_u64_op(rend_cache_total_allocation, OP_EQ, SIZE_MAX);

  // And again
  rend_cache_increment_allocation(2);
  tt_u64_op(rend_cache_total_allocation, OP_EQ, SIZE_MAX);

 done:
  (void)0;
}
Example #11
0
static void
test_crypto_rng_fast(void *arg)
{
  (void)arg;
  crypto_fast_rng_t *rng = crypto_fast_rng_new();
  tt_assert(rng);

  /* Rudimentary black-block test to make sure that our prng outputs
   * have all bits sometimes on and all bits sometimes off. */
  uint64_t m1 = 0, m2 = ~(uint64_t)0;
  const int N = 128;

  for (int i=0; i < N; ++i) {
    uint64_t v;
    crypto_fast_rng_getbytes(rng, (void*)&v, sizeof(v));
    m1 |= v;
    m2 &= v;
  }

  tt_u64_op(m1, OP_EQ, ~(uint64_t)0);
  tt_u64_op(m2, OP_EQ, 0);

  /* Check range functions. */
  int counts[5];
  memset(counts, 0, sizeof(counts));
  for (int i=0; i < N; ++i) {
    unsigned u = crypto_fast_rng_get_uint(rng, 5);
    tt_int_op(u, OP_GE, 0);
    tt_int_op(u, OP_LT, 5);
    counts[u]++;

    uint64_t u64 = crypto_fast_rng_get_uint64(rng, UINT64_C(1)<<40);
    tt_u64_op(u64, OP_GE, 0);
    tt_u64_op(u64, OP_LT, UINT64_C(1)<<40);

    double d = crypto_fast_rng_get_double(rng);
    tt_assert(d >= 0.0);
    tt_assert(d < 1.0);
  }

  /* All values should have come up once. */
  for (int i=0; i<5; ++i) {
    tt_int_op(counts[i], OP_GT, 0);
  }

  /* per-thread rand_fast shouldn't crash or leak. */
  crypto_fast_rng_t *t_rng = get_thread_fast_rng();
  for (int i = 0; i < N; ++i) {
    uint64_t u64 = crypto_fast_rng_get_uint64(t_rng, UINT64_C(1)<<40);
    tt_u64_op(u64, OP_GE, 0);
    tt_u64_op(u64, OP_LT, UINT64_C(1)<<40);
  }

 done:
  crypto_fast_rng_free(rng);
}
static void
test_cntev_sum_up_cell_stats(void *arg)
{
  or_circuit_t *or_circ;
  circuit_t *circ;
  cell_stats_t *cell_stats = NULL;
  (void)arg;

  /* This circuit is fake. */
  or_circ = tor_malloc_zero(sizeof(or_circuit_t));
  or_circ->base_.magic = OR_CIRCUIT_MAGIC;
  or_circ->base_.purpose = CIRCUIT_PURPOSE_OR;
  circ = TO_CIRCUIT(or_circ);

  /* A single RELAY cell was added to the appward queue. */
  cell_stats = tor_malloc_zero(sizeof(cell_stats_t));
  add_testing_cell_stats_entry(circ, CELL_RELAY, 0, 0, 0);
  sum_up_cell_stats_by_command(circ, cell_stats);
  tt_u64_op(1, OP_EQ, cell_stats->added_cells_appward[CELL_RELAY]);

  /* A single RELAY cell was added to the exitward queue. */
  add_testing_cell_stats_entry(circ, CELL_RELAY, 0, 0, 1);
  sum_up_cell_stats_by_command(circ, cell_stats);
  tt_u64_op(1, OP_EQ, cell_stats->added_cells_exitward[CELL_RELAY]);

  /* A single RELAY cell was removed from the appward queue where it spent
   * 20 msec. */
  add_testing_cell_stats_entry(circ, CELL_RELAY, 2, 1, 0);
  sum_up_cell_stats_by_command(circ, cell_stats);
  tt_u64_op(20, OP_EQ, cell_stats->total_time_appward[CELL_RELAY]);
  tt_u64_op(1, OP_EQ, cell_stats->removed_cells_appward[CELL_RELAY]);

  /* A single RELAY cell was removed from the exitward queue where it
   * spent 30 msec. */
  add_testing_cell_stats_entry(circ, CELL_RELAY, 3, 1, 1);
  sum_up_cell_stats_by_command(circ, cell_stats);
  tt_u64_op(30, OP_EQ, cell_stats->total_time_exitward[CELL_RELAY]);
  tt_u64_op(1, OP_EQ, cell_stats->removed_cells_exitward[CELL_RELAY]);

 done:
  tor_free(cell_stats);
  tor_free(or_circ);
}
Example #13
0
hs_desc_intro_point_t *
hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
                            const char *addr, int legacy)
{
  int ret;
  ed25519_keypair_t auth_kp;
  hs_desc_intro_point_t *intro_point = NULL;
  hs_desc_intro_point_t *ip = hs_desc_intro_point_new();

  /* For a usable intro point we need at least two link specifiers: One legacy
   * keyid and one ipv4 */
  {
    tor_addr_t a;
    tor_addr_make_unspec(&a);
    link_specifier_t *ls_legacy = link_specifier_new();
    link_specifier_t *ls_ip = link_specifier_new();
    link_specifier_set_ls_type(ls_legacy, LS_LEGACY_ID);
    memset(link_specifier_getarray_un_legacy_id(ls_legacy), 'C',
           link_specifier_getlen_un_legacy_id(ls_legacy));
    int family = tor_addr_parse(&a, addr);
    switch (family) {
    case AF_INET:
          link_specifier_set_ls_type(ls_ip, LS_IPV4);
          link_specifier_set_un_ipv4_addr(ls_ip, tor_addr_to_ipv4h(&a));
          link_specifier_set_un_ipv4_port(ls_ip, 9001);
          break;
        case AF_INET6:
          link_specifier_set_ls_type(ls_ip, LS_IPV6);
          memcpy(link_specifier_getarray_un_ipv6_addr(ls_ip),
                 tor_addr_to_in6_addr8(&a),
                 link_specifier_getlen_un_ipv6_addr(ls_ip));
          link_specifier_set_un_ipv6_port(ls_ip, 9001);
          break;
        default:
          /* Stop the test, not supposed to have an error.
           * Compare with -1 to show the actual family.
           */
          tt_int_op(family, OP_EQ, -1);
    }
    smartlist_add(ip->link_specifiers, ls_legacy);
    smartlist_add(ip->link_specifiers, ls_ip);
  }

  ret = ed25519_keypair_generate(&auth_kp, 0);
  tt_int_op(ret, ==, 0);
  ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
                                      &auth_kp.pubkey, now,
                                      HS_DESC_CERT_LIFETIME,
                                      CERT_FLAG_INCLUDE_SIGNING_KEY);
  tt_assert(ip->auth_key_cert);

  if (legacy) {
    ip->legacy.key = crypto_pk_new();
    tt_assert(ip->legacy.key);
    ret = crypto_pk_generate_key(ip->legacy.key);
    tt_int_op(ret, ==, 0);
    ssize_t cert_len = tor_make_rsa_ed25519_crosscert(
                                    &signing_kp->pubkey, ip->legacy.key,
                                    now + HS_DESC_CERT_LIFETIME,
                                    &ip->legacy.cert.encoded);
    tt_assert(ip->legacy.cert.encoded);
    tt_u64_op(cert_len, OP_GT, 0);
    ip->legacy.cert.len = cert_len;
  }

  /* Encryption key. */
  {
    int signbit;
    curve25519_keypair_t curve25519_kp;
    ed25519_keypair_t ed25519_kp;
    tor_cert_t *cross_cert;

    ret = curve25519_keypair_generate(&curve25519_kp, 0);
    tt_int_op(ret, ==, 0);
    ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
                                            &curve25519_kp);
    cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
                                 &ed25519_kp.pubkey, time(NULL),
                                 HS_DESC_CERT_LIFETIME,
                                 CERT_FLAG_INCLUDE_SIGNING_KEY);
    tt_assert(cross_cert);
    ip->enc_key_cert = cross_cert;
  }

  intro_point = ip;
 done:
  if (intro_point == NULL)
    tor_free(ip);

  return intro_point;
}
Example #14
0
static void
test_storagedir_read_labeled(void *arg)
{
  (void)arg;
  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  uint8_t *inp = tor_malloc_zero(8192);
  config_line_t *labels = NULL, *labels2 = NULL;
  char *fname = NULL;
  tor_mmap_t *map = NULL;
  uint8_t *as_read = NULL;

  d = storage_dir_new(dirname, 10);
  tt_assert(d);

  tor_snprintf((char*)inp, 8192,
               "Hello world\n"
               "This is a test\n"
               "Yadda yadda.\n");
  size_t bodylen = 8192 - strlen((char*)inp) - 1;
  crypto_rand((char *)inp+strlen((char*)inp)+1, bodylen);

  int r = storage_dir_save_bytes_to_file(d, inp, 8192, 1, &fname);
  tt_int_op(r, OP_EQ, 0);

  /* Try mapping */
  const uint8_t *datap = NULL;
  size_t sz = 0;
  map = storage_dir_map_labeled(d, fname, &labels, &datap, &sz);
  tt_assert(map);
  tt_assert(datap);
  tt_u64_op(sz, OP_EQ, bodylen);
  tt_mem_op(datap, OP_EQ, inp+strlen((char*)inp)+1, bodylen);
  tt_assert(labels);
  tt_str_op(labels->key, OP_EQ, "Hello");
  tt_str_op(labels->value, OP_EQ, "world");
  tt_assert(labels->next);
  tt_str_op(labels->next->key, OP_EQ, "This");
  tt_str_op(labels->next->value, OP_EQ, "is a test");
  tt_assert(labels->next->next);
  tt_str_op(labels->next->next->key, OP_EQ, "Yadda");
  tt_str_op(labels->next->next->value, OP_EQ, "yadda.");
  tt_ptr_op(labels->next->next->next, OP_EQ, NULL);

  /* Try reading this time. */
  sz = 0;
  as_read = storage_dir_read_labeled(d, fname, &labels2, &sz);
  tt_assert(as_read);
  tt_u64_op(sz, OP_EQ, bodylen);
  tt_mem_op(as_read, OP_EQ, inp+strlen((char*)inp)+1, bodylen);
  tt_assert(config_lines_eq(labels, labels2));

 done:
  storage_dir_free(d);
  tor_free(dirname);
  tor_free(inp);
  tor_free(fname);
  config_free_lines(labels);
  config_free_lines(labels2);
  tor_munmap_file(map);
  tor_free(as_read);
}
Example #15
0
static void
test_storagedir_cleaning(void *arg)
{
  (void)arg;

  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  const char str[] =
    "On a mountain halfway between Reno and Rome / "
    "We have a machine in a plexiglass dome / "
    "Which listens and looks into everyone's home."
    " -- Dr. Seuss";
  char *fns[8];
  int r, i;

  memset(fns, 0, sizeof(fns));
  d = storage_dir_new(dirname, 10);
  tt_assert(d);

  for (i = 0; i < 8; ++i) {
    r = storage_dir_save_string_to_file(d, str+i*2, 1, &fns[i]);
    tt_int_op(r, OP_EQ, 0);
  }

  /* Now we're going to make sure all the files have distinct mtimes. */
  time_t now = time(NULL);
  struct utimbuf ub;
  ub.actime = now;
  ub.modtime = now - 1000;
  for (i = 0; i < 8; ++i) {
    char *f = NULL;
    tor_asprintf(&f, "%s/%s", dirname, fns[i]);
    r = utime(f, &ub);
    tor_free(f);
    tt_int_op(r, OP_EQ, 0);
    ub.modtime += 5;
  }

  const uint64_t usage_orig = storage_dir_get_usage(d);
  /* No changes needed if we are already under target. */
  storage_dir_shrink(d, 1024*1024, 0);
  tt_u64_op(usage_orig, OP_EQ, storage_dir_get_usage(d));

  /* Get rid of at least one byte.  This will delete fns[0]. */
  storage_dir_shrink(d, usage_orig - 1, 0);
  tt_u64_op(usage_orig, OP_GT, storage_dir_get_usage(d));
  tt_u64_op(usage_orig - strlen(str), OP_EQ, storage_dir_get_usage(d));

  /* Get rid of at least two files.  This will delete fns[1] and fns[2]. */
  storage_dir_shrink(d, 1024*1024, 2);
  tt_u64_op(usage_orig - strlen(str)*3 + 6, OP_EQ, storage_dir_get_usage(d));

  /* Get rid of everything. */
  storage_dir_remove_all(d);
  tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));

 done:
  tor_free(dirname);
  storage_dir_free(d);
  for (i = 0; i < 8; ++i) {
    tor_free(fns[i]);
  }
}
Example #16
0
/* Test inbound cell. The callstack is:
 *  channel_process_cell()
 *    -> chan->cell_handler()
 *
 * This test is about checking if we can process an inbound cell down to the
 * channel handler. */
static void
test_channel_inbound_cell(void *arg)
{
  channel_t *chan = NULL;
  cell_t *cell = NULL;
  int old_count;

  (void) arg;

  /* The channel will be freed so we need to hijack this so the scheduler
   * doesn't get confused. */
  MOCK(scheduler_release_channel, scheduler_release_channel_mock);

  /* Accept cells to lower layer */
  test_chan_accept_cells = 1;

  chan = new_fake_channel();
  tt_assert(chan);
  /* Start it off in OPENING */
  chan->state = CHANNEL_STATE_OPENING;

  /* Try to register it */
  channel_register(chan);
  tt_int_op(chan->registered, OP_EQ, 1);

  /* Open it */
  channel_change_state_open(chan);
  tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_OPEN);
  tt_int_op(chan->has_been_open, OP_EQ, 1);

  /* Receive a cell now. */
  cell = tor_malloc_zero(sizeof(*cell));
  make_fake_cell(cell);
  old_count = test_chan_fixed_cells_recved;
  channel_process_cell(chan, cell);
  tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count);
  tt_assert(monotime_coarse_is_zero(&chan->timestamp_xfer));
  tt_u64_op(chan->timestamp_active, OP_EQ, 0);
  tt_u64_op(chan->timestamp_recv, OP_EQ, 0);

  /* Setup incoming cell handlers. We don't care about var cell, the channel
   * layers is not handling those. */
  channel_set_cell_handlers(chan, chan_test_cell_handler, NULL);
  tt_ptr_op(chan->cell_handler, OP_EQ, chan_test_cell_handler);
  /* Now process the cell, we should see it. */
  old_count = test_chan_fixed_cells_recved;
  channel_process_cell(chan, cell);
  tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count + 1);
  /* We should have a series of timestamp set. */
  tt_assert(!monotime_coarse_is_zero(&chan->timestamp_xfer));
  tt_u64_op(chan->timestamp_active, OP_NE, 0);
  tt_u64_op(chan->timestamp_recv, OP_NE, 0);
  tt_assert(monotime_coarse_is_zero(&chan->next_padding_time));
  tt_u64_op(chan->n_cells_recved, OP_EQ, 1);
  tt_u64_op(chan->n_bytes_recved, OP_EQ, get_cell_network_size(0));

  /* Close it */
  old_count = test_close_called;
  channel_mark_for_close(chan);
  tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_CLOSING);
  tt_int_op(chan->reason_for_closing, OP_EQ, CHANNEL_CLOSE_REQUESTED);
  tt_int_op(test_close_called, OP_EQ, old_count + 1);

  /* This closes the channe so it calls in the scheduler, make sure of it. */
  old_count = test_releases_count;
  chan_test_finish_close(chan);
  tt_int_op(test_releases_count, OP_EQ, old_count + 1);
  tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_CLOSED);

  /* The channel will be free, lets make sure it is not accessible. */
  uint64_t chan_id = chan->global_identifier;
  tt_ptr_op(channel_find_by_global_id(chan_id), OP_EQ, chan);
  channel_run_cleanup();
  chan = channel_find_by_global_id(chan_id);
  tt_assert(chan == NULL);

 done:
  tor_free(cell);
  UNMOCK(scheduler_release_channel);
}
Example #17
0
/* Test outbound cell. The callstack is:
 *  channel_flush_some_cells()
 *   -> channel_flush_from_first_active_circuit()
 *     -> channel_write_packed_cell()
 *       -> write_packed_cell()
 *         -> chan->write_packed_cell() fct ptr.
 *
 * This test goes from a cell in a circuit up to the channel write handler
 * that should put them on the connection outbuf. */
static void
test_channel_outbound_cell(void *arg)
{
  int old_count;
  channel_t *chan = NULL;
  packed_cell_t *p_cell = NULL, *p_cell2 = NULL;
  origin_circuit_t *circ = NULL;
  cell_queue_t *queue;

  (void) arg;

  /* Set the test time to be mocked, since this test assumes that no
   * time will pass, ewma values will not need to be re-scaled, and so on */
  monotime_enable_test_mocking();
  monotime_set_mock_time_nsec(U64_LITERAL(1000000000) * 12345);

  cmux_ewma_set_options(NULL,NULL);

  /* The channel will be freed so we need to hijack this so the scheduler
   * doesn't get confused. */
  MOCK(scheduler_release_channel, scheduler_release_channel_mock);

  /* Accept cells to lower layer */
  test_chan_accept_cells = 1;

  /* Setup a valid circuit to queue a cell. */
  circ = origin_circuit_new();
  tt_assert(circ);
  /* Circuit needs an origin purpose to be considered origin. */
  TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL;
  TO_CIRCUIT(circ)->n_circ_id = 42;
  /* This is the outbound test so use the next channel queue. */
  queue = &TO_CIRCUIT(circ)->n_chan_cells;
  /* Setup packed cell to queue on the circuit. */
  p_cell = packed_cell_new();
  tt_assert(p_cell);
  p_cell2 = packed_cell_new();
  tt_assert(p_cell2);
  /* Setup a channel to put the circuit on. */
  chan = new_fake_channel();
  tt_assert(chan);
  chan->state = CHANNEL_STATE_OPENING;
  channel_change_state_open(chan);
  /* Outbound channel. */
  channel_mark_outgoing(chan);
  /* Try to register it so we can clean it through the channel cleanup
   * process. */
  channel_register(chan);
  tt_int_op(chan->registered, OP_EQ, 1);
  /* Set EWMA policy so we can pick it when flushing. */
  circuitmux_set_policy(chan->cmux, &ewma_policy);
  tt_ptr_op(circuitmux_get_policy(chan->cmux), OP_EQ, &ewma_policy);

  /* Register circuit to the channel circid map which will attach the circuit
   * to the channel's cmux as well. */
  circuit_set_n_circid_chan(TO_CIRCUIT(circ), 42, chan);
  tt_int_op(channel_num_circuits(chan), OP_EQ, 1);
  /* Test the cmux state. */
  tt_ptr_op(TO_CIRCUIT(circ)->n_mux, OP_EQ, chan->cmux);
  tt_int_op(circuitmux_is_circuit_attached(chan->cmux, TO_CIRCUIT(circ)),
            OP_EQ, 1);

  /* Flush the channel without any cell on it. */
  old_count = test_cells_written;
  ssize_t flushed = channel_flush_some_cells(chan, 1);
  tt_i64_op(flushed, OP_EQ, 0);
  tt_int_op(test_cells_written, OP_EQ, old_count);
  tt_int_op(channel_more_to_flush(chan), OP_EQ, 0);
  tt_int_op(circuitmux_num_active_circuits(chan->cmux), OP_EQ, 0);
  tt_int_op(circuitmux_num_cells(chan->cmux), OP_EQ, 0);
  tt_int_op(circuitmux_is_circuit_active(chan->cmux, TO_CIRCUIT(circ)),
            OP_EQ, 0);
  tt_u64_op(chan->n_cells_xmitted, OP_EQ, 0);
  tt_u64_op(chan->n_bytes_xmitted, OP_EQ, 0);

  /* Queue cell onto the next queue that is the outbound direction. Than
   * update its cmux so the circuit can be picked when flushing cells. */
  cell_queue_append(queue, p_cell);
  p_cell = NULL;
  tt_int_op(queue->n, OP_EQ, 1);
  cell_queue_append(queue, p_cell2);
  p_cell2 = NULL;
  tt_int_op(queue->n, OP_EQ, 2);

  update_circuit_on_cmux(TO_CIRCUIT(circ), CELL_DIRECTION_OUT);
  tt_int_op(circuitmux_num_active_circuits(chan->cmux), OP_EQ, 1);
  tt_int_op(circuitmux_num_cells(chan->cmux), OP_EQ, 2);
  tt_int_op(circuitmux_is_circuit_active(chan->cmux, TO_CIRCUIT(circ)),
            OP_EQ, 1);

  /* From this point on, we have a queued cell on an active circuit attached
   * to the channel's cmux. */

  /* Flush the first cell. This is going to go down the call stack. */
  old_count = test_cells_written;
  flushed = channel_flush_some_cells(chan, 1);
  tt_i64_op(flushed, OP_EQ, 1);
  tt_int_op(test_cells_written, OP_EQ, old_count + 1);
  tt_int_op(circuitmux_num_cells(chan->cmux), OP_EQ, 1);
  tt_int_op(channel_more_to_flush(chan), OP_EQ, 1);
  /* Circuit should remain active because there is a second cell queued. */
  tt_int_op(circuitmux_is_circuit_active(chan->cmux, TO_CIRCUIT(circ)),
            OP_EQ, 1);
  /* Should still be attached. */
  tt_int_op(circuitmux_is_circuit_attached(chan->cmux, TO_CIRCUIT(circ)),
            OP_EQ, 1);
  tt_u64_op(chan->n_cells_xmitted, OP_EQ, 1);
  tt_u64_op(chan->n_bytes_xmitted, OP_EQ, get_cell_network_size(0));

  /* Flush second cell. This is going to go down the call stack. */
  old_count = test_cells_written;
  flushed = channel_flush_some_cells(chan, 1);
  tt_i64_op(flushed, OP_EQ, 1);
  tt_int_op(test_cells_written, OP_EQ, old_count + 1);
  tt_int_op(circuitmux_num_cells(chan->cmux), OP_EQ, 0);
  tt_int_op(channel_more_to_flush(chan), OP_EQ, 0);
  /* No more cells should make the circuit inactive. */
  tt_int_op(circuitmux_is_circuit_active(chan->cmux, TO_CIRCUIT(circ)),
            OP_EQ, 0);
  /* Should still be attached. */
  tt_int_op(circuitmux_is_circuit_attached(chan->cmux, TO_CIRCUIT(circ)),
            OP_EQ, 1);
  tt_u64_op(chan->n_cells_xmitted, OP_EQ, 2);
  tt_u64_op(chan->n_bytes_xmitted, OP_EQ, get_cell_network_size(0) * 2);

 done:
  if (circ) {
    circuit_free_(TO_CIRCUIT(circ));
  }
  tor_free(p_cell);
  channel_free_all();
  UNMOCK(scheduler_release_channel);
  monotime_disable_test_mocking();
}
Example #18
0
static void
test_channel_dumpstats(void *arg)
{
  channel_t *ch = NULL;
  cell_t *cell = NULL;
  packed_cell_t *p_cell = NULL;
  int old_count;

  (void)arg;

  /* Mock these for duration of the test */
  MOCK(scheduler_channel_doesnt_want_writes,
       scheduler_channel_doesnt_want_writes_mock);
  MOCK(scheduler_release_channel,
       scheduler_release_channel_mock);

  /* Set up a new fake channel */
  ch = new_fake_channel();
  tt_assert(ch);

  /* Try to register it */
  channel_register(ch);
  tt_assert(ch->registered);

  /* Set up mock */
  dump_statistics_mock_target = ch;
  dump_statistics_mock_matches = 0;
  MOCK(channel_dump_statistics,
       chan_test_channel_dump_statistics_mock);

  /* Call channel_dumpstats() */
  channel_dumpstats(LOG_DEBUG);

  /* Assert that we hit the mock */
  tt_int_op(dump_statistics_mock_matches, OP_EQ, 1);

  /* Close the channel */
  channel_mark_for_close(ch);
  tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING);
  chan_test_finish_close(ch);
  tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED);

  /* Try again and hit the finished channel */
  channel_dumpstats(LOG_DEBUG);
  tt_int_op(dump_statistics_mock_matches, OP_EQ, 2);

  channel_run_cleanup();
  ch = NULL;

  /* Now we should hit nothing */
  channel_dumpstats(LOG_DEBUG);
  tt_int_op(dump_statistics_mock_matches, OP_EQ, 2);

  /* Unmock */
  UNMOCK(channel_dump_statistics);
  dump_statistics_mock_target = NULL;
  dump_statistics_mock_matches = 0;

  /* Now make another channel */
  ch = new_fake_channel();
  tt_assert(ch);
  channel_register(ch);
  tt_int_op(ch->registered, OP_EQ, 1);
  /* Lie about its age so dumpstats gets coverage for rate calculations */
  ch->timestamp_created = time(NULL) - 30;
  tt_int_op(ch->timestamp_created, OP_GT, 0);
  tt_int_op(time(NULL), OP_GT, ch->timestamp_created);

  /* Put cells through it both ways to make the counters non-zero */
  p_cell = packed_cell_new();
  test_chan_accept_cells = 1;
  old_count = test_cells_written;
  channel_write_packed_cell(ch, p_cell);
  tt_int_op(test_cells_written, OP_EQ, old_count + 1);
  tt_u64_op(ch->n_bytes_xmitted, OP_GT, 0);
  tt_u64_op(ch->n_cells_xmitted, OP_GT, 0);

  /* Receive path */
  channel_set_cell_handlers(ch,
                            chan_test_cell_handler,
                            chan_test_var_cell_handler);
  tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, chan_test_cell_handler);
  tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ,
            chan_test_var_cell_handler);
  cell = tor_malloc_zero(sizeof(*cell));
  old_count = test_chan_fixed_cells_recved;
  channel_process_cell(ch, cell);
  tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count + 1);
  tt_u64_op(ch->n_bytes_recved, OP_GT, 0);
  tt_u64_op(ch->n_cells_recved, OP_GT, 0);

  /* Test channel_dump_statistics */
  ch->describe_transport = chan_test_describe_transport;
  ch->dumpstats = chan_test_dumpstats;
  test_chan_should_be_canonical = 1;
  ch->is_canonical = test_chan_is_canonical;
  old_count = test_dumpstats_calls;
  channel_dump_statistics(ch, LOG_DEBUG);
  tt_int_op(test_dumpstats_calls, OP_EQ, old_count + 1);

  /* Close the channel */
  channel_mark_for_close(ch);
  tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING);
  chan_test_finish_close(ch);
  tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED);
  channel_run_cleanup();
  ch = NULL;

 done:
  free_fake_channel(ch);
  tor_free(cell);

  UNMOCK(scheduler_channel_doesnt_want_writes);
  UNMOCK(scheduler_release_channel);

  return;
}
Example #19
0
static void
test_storagedir_basic(void *arg)
{
  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  uint8_t *junk = NULL, *bytes = NULL;
  const size_t junklen = 1024;
  char *fname1 = NULL, *fname2 = NULL;
  const char hello_str[] = "then what are we but cold, alone ... ?";
  tor_mmap_t *mapping = NULL;
  (void)arg;

  junk = tor_malloc(junklen);
  crypto_rand((void*)junk, junklen);

  d = storage_dir_new(dirname, 10);
  tt_assert(d);
  tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));

  int r;
  r = storage_dir_save_string_to_file(d, hello_str, 1, &fname1);
  tt_int_op(r, OP_EQ, 0);
  tt_ptr_op(fname1, OP_NE, NULL);
  tt_u64_op(strlen(hello_str), OP_EQ, storage_dir_get_usage(d));

  r = storage_dir_save_bytes_to_file(d, junk, junklen, 1, &fname2);
  tt_int_op(r, OP_EQ, 0);
  tt_ptr_op(fname2, OP_NE, NULL);

  tt_str_op(fname1, OP_NE, fname2);

  tt_int_op(2, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(junklen + strlen(hello_str), OP_EQ, storage_dir_get_usage(d));
  tt_assert(smartlist_contains_string(storage_dir_list(d), fname1));
  tt_assert(smartlist_contains_string(storage_dir_list(d), fname2));

  storage_dir_free(d);
  d = storage_dir_new(dirname, 10);
  tt_assert(d);
  tt_int_op(2, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(junklen + strlen(hello_str), OP_EQ, storage_dir_get_usage(d));
  tt_assert(smartlist_contains_string(storage_dir_list(d), fname1));
  tt_assert(smartlist_contains_string(storage_dir_list(d), fname2));

  size_t n;
  bytes = storage_dir_read(d, fname2, 1, &n);
  tt_assert(bytes);
  tt_u64_op(n, OP_EQ, junklen);
  tt_mem_op(bytes, OP_EQ, junk, junklen);

  mapping = storage_dir_map(d, fname1);
  tt_assert(mapping);
  tt_u64_op(mapping->size, OP_EQ, strlen(hello_str));
  tt_mem_op(mapping->data, OP_EQ, hello_str, strlen(hello_str));

 done:
  tor_free(dirname);
  tor_free(junk);
  tor_free(bytes);
  tor_munmap_file(mapping);
  storage_dir_free(d);
  tor_free(fname1);
  tor_free(fname2);
}
Example #20
0
static void
test_relay_close_circuit(void *arg)
{
  channel_t *nchan = NULL, *pchan = NULL;
  or_circuit_t *orcirc = NULL;
  cell_t *cell = NULL;
  int old_count, new_count;

  (void)arg;

  /* Make fake channels to be nchan and pchan for the circuit */
  nchan = new_fake_channel();
  tt_assert(nchan);

  pchan = new_fake_channel();
  tt_assert(pchan);

  /* Make a fake orcirc */
  orcirc = new_fake_orcirc(nchan, pchan);
  tt_assert(orcirc);
  circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc),
                            CELL_DIRECTION_OUT);
  circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc),
                            CELL_DIRECTION_IN);

  /* Make a cell */
  cell = tor_malloc_zero(sizeof(cell_t));
  make_fake_cell(cell);

  MOCK(scheduler_channel_has_waiting_cells,
       scheduler_channel_has_waiting_cells_mock);
  MOCK(assert_circuit_ok,
       assert_circuit_ok_mock);

  /* Append it */
  old_count = get_mock_scheduler_has_waiting_cells_count();
  append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell,
                               CELL_DIRECTION_OUT, 0);
  new_count = get_mock_scheduler_has_waiting_cells_count();
  tt_int_op(new_count, OP_EQ, old_count + 1);

  /* Now try the reverse direction */
  old_count = get_mock_scheduler_has_waiting_cells_count();
  append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell,
                               CELL_DIRECTION_IN, 0);
  new_count = get_mock_scheduler_has_waiting_cells_count();
  tt_int_op(new_count, OP_EQ, old_count + 1);

  /* Ensure our write totals are 0 */
  tt_u64_op(find_largest_max(write_array), OP_EQ, 0);

  /* Mark the circuit for close */
  circuit_mark_for_close(TO_CIRCUIT(orcirc), 0);

  /* Check our write totals. */
  advance_obs(write_array);
  commit_max(write_array);
  /* Check for two cells plus overhead */
  tt_u64_op(find_largest_max(write_array), OP_EQ,
                             2*(get_cell_network_size(nchan->wide_circ_ids)
                                +TLS_PER_CELL_OVERHEAD));

  UNMOCK(scheduler_channel_has_waiting_cells);

  /* Get rid of the fake channels */
  MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  channel_mark_for_close(nchan);
  channel_mark_for_close(pchan);
  UNMOCK(scheduler_release_channel);

  /* Shut down channels */
  channel_free_all();

 done:
  tor_free(cell);
  if (orcirc) {
    circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc));
    circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc));
    cell_queue_clear(&orcirc->base_.n_chan_cells);
    cell_queue_clear(&orcirc->p_chan_cells);
  }
  tor_free(orcirc);
  free_fake_channel(nchan);
  free_fake_channel(pchan);
  UNMOCK(assert_circuit_ok);

  return;
}