mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 13:43:47 +01:00
85edef27eb
Slow system can sometime take more than 10 seconds to reach the test callsite resulting in the unit test failing when using time in the future or in the past. Fixes #19465 Signed-off-by: David Goulet <dgoulet@torproject.org>
1265 lines
40 KiB
C
1265 lines
40 KiB
C
/* Copyright (c) 2010-2016, The Tor Project, Inc. */
|
|
/* See LICENSE for licensing information */
|
|
|
|
#include "orconfig.h"
|
|
#include "or.h"
|
|
|
|
#include "test.h"
|
|
#define RENDCACHE_PRIVATE
|
|
#include "rendcache.h"
|
|
#include "router.h"
|
|
#include "routerlist.h"
|
|
#include "config.h"
|
|
#include <openssl/rsa.h>
|
|
#include "rend_test_helpers.h"
|
|
|
|
#define NS_MODULE rend_cache
|
|
|
|
static const int RECENT_TIME = -10;
|
|
static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + \
|
|
REND_CACHE_MAX_SKEW + 60);
|
|
static const int TIME_IN_THE_FUTURE = REND_CACHE_MAX_SKEW + 60;
|
|
|
|
static rend_data_t *
|
|
mock_rend_data(const char *onion_address)
|
|
{
|
|
rend_data_t *rend_query = tor_malloc_zero(sizeof(rend_data_t));
|
|
|
|
strlcpy(rend_query->onion_address, onion_address,
|
|
sizeof(rend_query->onion_address));
|
|
rend_query->auth_type = REND_NO_AUTH;
|
|
rend_query->hsdirs_fp = smartlist_new();
|
|
smartlist_add(rend_query->hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa",
|
|
DIGEST_LEN));
|
|
|
|
return rend_query;
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_lookup_entry(void *data)
|
|
{
|
|
int ret;
|
|
rend_data_t *mock_rend_query = NULL;
|
|
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
|
|
rend_cache_entry_t *entry = NULL;
|
|
rend_encoded_v2_service_descriptor_t *desc_holder = NULL;
|
|
char *service_id = NULL;
|
|
(void)data;
|
|
|
|
rend_cache_init();
|
|
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
|
|
|
ret = rend_cache_lookup_entry("abababababababab", 0, NULL);
|
|
tt_int_op(ret, OP_EQ, -ENOENT);
|
|
|
|
ret = rend_cache_lookup_entry("invalid query", 2, NULL);
|
|
tt_int_op(ret, OP_EQ, -EINVAL);
|
|
|
|
ret = rend_cache_lookup_entry("abababababababab", 2, NULL);
|
|
tt_int_op(ret, OP_EQ, -ENOENT);
|
|
|
|
ret = rend_cache_lookup_entry("abababababababab", 4224, NULL);
|
|
tt_int_op(ret, OP_EQ, -ENOENT);
|
|
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32,
|
|
mock_rend_query, NULL);
|
|
|
|
ret = rend_cache_lookup_entry(service_id, 2, NULL);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
ret = rend_cache_lookup_entry(service_id, 2, &entry);
|
|
tt_assert(entry);
|
|
tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str));
|
|
tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str);
|
|
|
|
done:
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_cache_free_all();
|
|
rend_data_free(mock_rend_query);
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_store_v2_desc_as_client(void *data)
|
|
{
|
|
int ret;
|
|
rend_data_t *mock_rend_query;
|
|
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
|
|
rend_cache_entry_t *entry = NULL;
|
|
rend_encoded_v2_service_descriptor_t *desc_holder = NULL;
|
|
char *service_id = NULL;
|
|
char client_cookie[REND_DESC_COOKIE_LEN];
|
|
(void)data;
|
|
|
|
rend_cache_init();
|
|
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
|
|
|
// Test success
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
&entry);
|
|
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
tt_assert(entry);
|
|
tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str));
|
|
tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str);
|
|
|
|
// Test various failure modes
|
|
|
|
// TODO: a too long desc_id_base32 argument crashes the function
|
|
/* ret = rend_cache_store_v2_desc_as_client( */
|
|
/* desc_holder->desc_str, */
|
|
/* "3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG", */
|
|
/* &mock_rend_query, NULL); */
|
|
/* tt_int_op(ret, OP_EQ, -1); */
|
|
|
|
// Test bad base32 failure
|
|
// This causes an assertion failure if we're running with assertions.
|
|
// But when building without asserts, we can test it.
|
|
#ifdef DISABLE_ASSERTS_IN_UNIT_TESTS
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
"!xqunszqnaolrrfmtzgaki7mxelgvkj", mock_rend_query, NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
#endif
|
|
|
|
// Test invalid descriptor
|
|
ret = rend_cache_store_v2_desc_as_client("invalid descriptor",
|
|
"3xqunszqnaolrrfmtzgaki7mxelgvkje", mock_rend_query, NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
|
|
// TODO: it doesn't seem to be possible to test invalid service ID condition.
|
|
// that means it is likely not possible to have that condition without
|
|
// earlier conditions failing first (such as signature checking of the desc)
|
|
|
|
rend_cache_free_all();
|
|
|
|
// Test mismatch between service ID and onion address
|
|
rend_cache_init();
|
|
strncpy(mock_rend_query->onion_address, "abc", REND_SERVICE_ID_LEN_BASE32+1);
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32,
|
|
mock_rend_query, NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
rend_cache_free_all();
|
|
rend_data_free(mock_rend_query);
|
|
|
|
// Test incorrect descriptor ID
|
|
rend_cache_init();
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
desc_id_base32[0]++;
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
desc_id_base32[0]--;
|
|
rend_cache_free_all();
|
|
|
|
// Test too old descriptor
|
|
rend_cache_init();
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_data_free(mock_rend_query);
|
|
|
|
generate_desc(TIME_IN_THE_PAST, &desc_holder, &service_id, 3);
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32,
|
|
mock_rend_query, NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
rend_cache_free_all();
|
|
|
|
// Test too new descriptor (in the future)
|
|
rend_cache_init();
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_data_free(mock_rend_query);
|
|
|
|
generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3);
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
rend_cache_free_all();
|
|
|
|
// Test when a descriptor is already in the cache
|
|
rend_cache_init();
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_data_free(mock_rend_query);
|
|
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
|
|
rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32,
|
|
mock_rend_query, NULL);
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
NULL);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
&entry);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
tt_assert(entry);
|
|
rend_cache_free_all();
|
|
|
|
// Test unsuccessful decrypting of introduction points
|
|
rend_cache_init();
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_data_free(mock_rend_query);
|
|
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
mock_rend_query->auth_type = REND_BASIC_AUTH;
|
|
client_cookie[0] = 'A';
|
|
memcpy(mock_rend_query->descriptor_cookie, client_cookie,
|
|
REND_DESC_COOKIE_LEN);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
NULL);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
rend_cache_free_all();
|
|
|
|
// Test successful run when we have REND_BASIC_AUTH but not cookie
|
|
rend_cache_init();
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_data_free(mock_rend_query);
|
|
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
mock_rend_query->auth_type = REND_BASIC_AUTH;
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
NULL);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
rend_cache_free_all();
|
|
|
|
// Test when we have no introduction points
|
|
rend_cache_init();
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_data_free(mock_rend_query);
|
|
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, 0);
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
rend_cache_free_all();
|
|
|
|
// Test when we have too many intro points
|
|
rend_cache_init();
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_data_free(mock_rend_query);
|
|
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, MAX_INTRO_POINTS+1);
|
|
mock_rend_query = mock_rend_data(service_id);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
|
desc_id_base32, mock_rend_query,
|
|
NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
|
|
done:
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_cache_free_all();
|
|
rend_data_free(mock_rend_query);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
#define NS_SUBMODULE lookup_v2_desc_as_dir
|
|
NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
|
|
|
|
static routerinfo_t *mock_routerinfo;
|
|
|
|
static const routerinfo_t *
|
|
NS(router_get_my_routerinfo)(void)
|
|
{
|
|
if (!mock_routerinfo) {
|
|
mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
|
|
}
|
|
|
|
return mock_routerinfo;
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_lookup_v2_desc_as_dir(void *data)
|
|
{
|
|
int ret;
|
|
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
|
|
rend_encoded_v2_service_descriptor_t *desc_holder = NULL;
|
|
char *service_id = NULL;
|
|
const char *ret_desc = NULL;
|
|
|
|
(void)data;
|
|
|
|
NS_MOCK(router_get_my_routerinfo);
|
|
|
|
rend_cache_init();
|
|
|
|
// Test invalid base32
|
|
ret = rend_cache_lookup_v2_desc_as_dir("!bababababababab", NULL);
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
|
|
// Test non-existent descriptor but well formed
|
|
ret = rend_cache_lookup_v2_desc_as_dir("3xqunszqnaolrrfmtzgaki7mxelgvkje",
|
|
NULL);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
// Test existing descriptor
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
|
rend_cache_store_v2_desc_as_dir(desc_holder->desc_str);
|
|
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
|
DIGEST_LEN);
|
|
ret = rend_cache_lookup_v2_desc_as_dir(desc_id_base32, &ret_desc);
|
|
tt_int_op(ret, OP_EQ, 1);
|
|
tt_assert(ret_desc);
|
|
|
|
done:
|
|
NS_UNMOCK(router_get_my_routerinfo);
|
|
tor_free(mock_routerinfo);
|
|
rend_cache_free_all();
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
}
|
|
|
|
#undef NS_SUBMODULE
|
|
|
|
#define NS_SUBMODULE store_v2_desc_as_dir
|
|
NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
|
|
|
|
static const routerinfo_t *
|
|
NS(router_get_my_routerinfo)(void)
|
|
{
|
|
return mock_routerinfo;
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_store_v2_desc_as_dir(void *data)
|
|
{
|
|
(void)data;
|
|
int ret;
|
|
rend_encoded_v2_service_descriptor_t *desc_holder = NULL;
|
|
char *service_id = NULL;
|
|
|
|
NS_MOCK(router_get_my_routerinfo);
|
|
|
|
rend_cache_init();
|
|
|
|
// Test when we can't parse the descriptor
|
|
mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
|
|
ret = rend_cache_store_v2_desc_as_dir("unparseable");
|
|
tt_int_op(ret, OP_EQ, -1);
|
|
|
|
// Test when we have an old descriptor
|
|
generate_desc(TIME_IN_THE_PAST, &desc_holder, &service_id, 3);
|
|
ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
|
|
// Test when we have a descriptor in the future
|
|
generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3);
|
|
ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
|
|
// Test when two descriptors
|
|
generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3);
|
|
ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
|
|
// Test when asking for hidden service statistics HiddenServiceStatistics
|
|
rend_cache_purge();
|
|
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
|
get_options_mutable()->HiddenServiceStatistics = 1;
|
|
ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
done:
|
|
NS_UNMOCK(router_get_my_routerinfo);
|
|
rend_encoded_v2_service_descriptor_free(desc_holder);
|
|
tor_free(service_id);
|
|
rend_cache_free_all();
|
|
tor_free(mock_routerinfo);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_store_v2_desc_as_dir_with_different_content(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_one = NULL;
|
|
rend_encoded_v2_service_descriptor_t *desc_holder_two = NULL;
|
|
|
|
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_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));
|
|
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, 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_one);
|
|
rend_encoded_v2_service_descriptor_free(desc_holder_two);
|
|
}
|
|
|
|
#undef NS_SUBMODULE
|
|
|
|
static void
|
|
test_rend_cache_init(void *data)
|
|
{
|
|
(void)data;
|
|
|
|
tt_assert_msg(!rend_cache, "rend_cache should be NULL when starting");
|
|
tt_assert_msg(!rend_cache_v2_dir, "rend_cache_v2_dir should be NULL "
|
|
"when starting");
|
|
tt_assert_msg(!rend_cache_failure, "rend_cache_failure should be NULL when "
|
|
"starting");
|
|
|
|
rend_cache_init();
|
|
|
|
tt_assert_msg(rend_cache, "rend_cache should not be NULL after initing");
|
|
tt_assert_msg(rend_cache_v2_dir, "rend_cache_v2_dir should not be NULL "
|
|
"after initing");
|
|
tt_assert_msg(rend_cache_failure, "rend_cache_failure should not be NULL "
|
|
"after initing");
|
|
|
|
tt_int_op(strmap_size(rend_cache), OP_EQ, 0);
|
|
tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0);
|
|
tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0);
|
|
|
|
done:
|
|
rend_cache_free_all();
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_decrement_allocation(void *data)
|
|
{
|
|
(void)data;
|
|
|
|
// Test when the cache has enough allocations
|
|
rend_cache_total_allocation = 10;
|
|
rend_cache_decrement_allocation(3);
|
|
tt_int_op(rend_cache_total_allocation, OP_EQ, 7);
|
|
|
|
// Test when there are not enough allocations
|
|
rend_cache_total_allocation = 1;
|
|
rend_cache_decrement_allocation(2);
|
|
tt_int_op(rend_cache_total_allocation, OP_EQ, 0);
|
|
|
|
// And again
|
|
rend_cache_decrement_allocation(2);
|
|
tt_int_op(rend_cache_total_allocation, OP_EQ, 0);
|
|
|
|
done:
|
|
(void)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;
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_failure_intro_entry_new(void *data)
|
|
{
|
|
time_t now;
|
|
rend_cache_failure_intro_t *entry;
|
|
rend_intro_point_failure_t failure;
|
|
|
|
(void)data;
|
|
|
|
failure = INTRO_POINT_FAILURE_TIMEOUT;
|
|
now = time(NULL);
|
|
entry = rend_cache_failure_intro_entry_new(failure);
|
|
|
|
tt_int_op(entry->failure_type, OP_EQ, INTRO_POINT_FAILURE_TIMEOUT);
|
|
tt_int_op(entry->created_ts, OP_GE, now-5);
|
|
tt_int_op(entry->created_ts, OP_LE, now+5);
|
|
|
|
done:
|
|
tor_free(entry);
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_clean(void *data)
|
|
{
|
|
rend_cache_entry_t *one, *two;
|
|
rend_service_descriptor_t *desc_one, *desc_two;
|
|
strmap_iter_t *iter = NULL;
|
|
const char *key;
|
|
void *val;
|
|
|
|
(void)data;
|
|
|
|
rend_cache_init();
|
|
|
|
// Test with empty rendcache
|
|
rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT);
|
|
tt_int_op(strmap_size(rend_cache), OP_EQ, 0);
|
|
|
|
// Test with two old entries
|
|
one = tor_malloc_zero(sizeof(rend_cache_entry_t));
|
|
two = tor_malloc_zero(sizeof(rend_cache_entry_t));
|
|
desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t));
|
|
desc_two = tor_malloc_zero(sizeof(rend_service_descriptor_t));
|
|
one->parsed = desc_one;
|
|
two->parsed = desc_two;
|
|
|
|
desc_one->timestamp = time(NULL) + TIME_IN_THE_PAST;
|
|
desc_two->timestamp = (time(NULL) + TIME_IN_THE_PAST) - 10;
|
|
desc_one->pk = pk_generate(0);
|
|
desc_two->pk = pk_generate(1);
|
|
|
|
strmap_set_lc(rend_cache, "foo1", one);
|
|
strmap_set_lc(rend_cache, "foo2", two);
|
|
|
|
rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT);
|
|
tt_int_op(strmap_size(rend_cache), OP_EQ, 0);
|
|
|
|
// Test with one old entry and one newer entry
|
|
one = tor_malloc_zero(sizeof(rend_cache_entry_t));
|
|
two = tor_malloc_zero(sizeof(rend_cache_entry_t));
|
|
desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t));
|
|
desc_two = tor_malloc_zero(sizeof(rend_service_descriptor_t));
|
|
one->parsed = desc_one;
|
|
two->parsed = desc_two;
|
|
|
|
desc_one->timestamp = (time(NULL) + TIME_IN_THE_PAST) - 10;
|
|
desc_two->timestamp = time(NULL) - 100;
|
|
desc_one->pk = pk_generate(0);
|
|
desc_two->pk = pk_generate(1);
|
|
|
|
strmap_set_lc(rend_cache, "foo1", one);
|
|
strmap_set_lc(rend_cache, "foo2", two);
|
|
|
|
rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT);
|
|
tt_int_op(strmap_size(rend_cache), OP_EQ, 1);
|
|
|
|
iter = strmap_iter_init(rend_cache);
|
|
strmap_iter_get(iter, &key, &val);
|
|
tt_str_op(key, OP_EQ, "foo2");
|
|
|
|
done:
|
|
rend_cache_free_all();
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_failure_entry_new(void *data)
|
|
{
|
|
rend_cache_failure_t *failure;
|
|
|
|
(void)data;
|
|
|
|
failure = rend_cache_failure_entry_new();
|
|
tt_assert(failure);
|
|
tt_int_op(digestmap_size(failure->intro_failures), OP_EQ, 0);
|
|
|
|
done:
|
|
rend_cache_failure_entry_free(failure);
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_failure_entry_free(void *data)
|
|
{
|
|
(void)data;
|
|
|
|
// Test that it can deal with a NULL argument
|
|
rend_cache_failure_entry_free(NULL);
|
|
|
|
/* done: */
|
|
/* (void)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();
|
|
}
|
|
|
|
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; */
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_free_all(void *data)
|
|
{
|
|
rend_cache_failure_t *failure;
|
|
rend_cache_entry_t *one;
|
|
rend_service_descriptor_t *desc_one;
|
|
|
|
(void)data;
|
|
|
|
rend_cache_init();
|
|
|
|
failure = rend_cache_failure_entry_new();
|
|
strmap_set_lc(rend_cache_failure, "foo1", failure);
|
|
|
|
one = tor_malloc_zero(sizeof(rend_cache_entry_t));
|
|
desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t));
|
|
one->parsed = desc_one;
|
|
desc_one->timestamp = time(NULL) + TIME_IN_THE_PAST;
|
|
desc_one->pk = pk_generate(0);
|
|
strmap_set_lc(rend_cache, "foo1", one);
|
|
|
|
rend_cache_free_all();
|
|
|
|
tt_assert(!rend_cache);
|
|
tt_assert(!rend_cache_v2_dir);
|
|
tt_assert(!rend_cache_failure);
|
|
tt_assert(!rend_cache_total_allocation);
|
|
|
|
done:
|
|
rend_cache_free_all();
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_entry_free(void *data)
|
|
{
|
|
(void)data;
|
|
rend_cache_entry_t *e;
|
|
|
|
// Handles NULL correctly
|
|
rend_cache_entry_free(NULL);
|
|
|
|
// Handles NULL descriptor correctly
|
|
e = tor_malloc_zero(sizeof(rend_cache_entry_t));
|
|
rend_cache_entry_free(e);
|
|
|
|
// Handles non-NULL descriptor correctly
|
|
e = tor_malloc_zero(sizeof(rend_cache_entry_t));
|
|
e->desc = (char *)malloc(10);
|
|
rend_cache_entry_free(e);
|
|
|
|
/* done: */
|
|
/* (void)0; */
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_purge(void *data)
|
|
{
|
|
(void)data;
|
|
|
|
// Deals with a NULL rend_cache
|
|
rend_cache_purge();
|
|
tt_assert(rend_cache);
|
|
tt_assert(strmap_size(rend_cache) == 0);
|
|
|
|
// Deals with existing rend_cache
|
|
rend_cache_free_all();
|
|
rend_cache_init();
|
|
tt_assert(rend_cache);
|
|
tt_assert(strmap_size(rend_cache) == 0);
|
|
|
|
rend_cache_purge();
|
|
tt_assert(rend_cache);
|
|
tt_assert(strmap_size(rend_cache) == 0);
|
|
|
|
done:
|
|
rend_cache_free_all();
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_failure_intro_add(void *data)
|
|
{
|
|
(void)data;
|
|
rend_cache_failure_t *fail_entry;
|
|
rend_cache_failure_intro_t *entry;
|
|
const char identity[DIGEST_LEN] = "foo1";
|
|
|
|
rend_cache_init();
|
|
|
|
// Adds non-existing entry
|
|
cache_failure_intro_add((const uint8_t *) identity, "foo2",
|
|
INTRO_POINT_FAILURE_TIMEOUT);
|
|
fail_entry = strmap_get_lc(rend_cache_failure, "foo2");
|
|
tt_assert(fail_entry);
|
|
tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1);
|
|
entry = digestmap_get(fail_entry->intro_failures, identity);
|
|
tt_assert(entry);
|
|
|
|
// Adds existing entry
|
|
cache_failure_intro_add((const uint8_t *) identity, "foo2",
|
|
INTRO_POINT_FAILURE_TIMEOUT);
|
|
fail_entry = strmap_get_lc(rend_cache_failure, "foo2");
|
|
tt_assert(fail_entry);
|
|
tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1);
|
|
entry = digestmap_get(fail_entry->intro_failures, identity);
|
|
tt_assert(entry);
|
|
|
|
done:
|
|
rend_cache_free_all();
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_intro_failure_note(void *data)
|
|
{
|
|
(void)data;
|
|
rend_cache_failure_t *fail_entry;
|
|
rend_cache_failure_intro_t *entry;
|
|
const char key[DIGEST_LEN] = "foo1";
|
|
|
|
rend_cache_init();
|
|
|
|
// Test not found
|
|
rend_cache_intro_failure_note(INTRO_POINT_FAILURE_TIMEOUT,
|
|
(const uint8_t *) key, "foo2");
|
|
fail_entry = strmap_get_lc(rend_cache_failure, "foo2");
|
|
tt_assert(fail_entry);
|
|
tt_int_op(digestmap_size(fail_entry->intro_failures), OP_EQ, 1);
|
|
entry = digestmap_get(fail_entry->intro_failures, key);
|
|
tt_assert(entry);
|
|
tt_int_op(entry->failure_type, OP_EQ, INTRO_POINT_FAILURE_TIMEOUT);
|
|
|
|
// Test found
|
|
rend_cache_intro_failure_note(INTRO_POINT_FAILURE_UNREACHABLE,
|
|
(const uint8_t *) key, "foo2");
|
|
tt_int_op(entry->failure_type, OP_EQ, INTRO_POINT_FAILURE_UNREACHABLE);
|
|
|
|
done:
|
|
rend_cache_free_all();
|
|
}
|
|
|
|
#define NS_SUBMODULE clean_v2_descs_as_dir
|
|
|
|
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();
|
|
}
|
|
|
|
#undef NS_SUBMODULE
|
|
|
|
static void
|
|
test_rend_cache_entry_allocation(void *data)
|
|
{
|
|
(void)data;
|
|
|
|
size_t ret;
|
|
rend_cache_entry_t *e = NULL;
|
|
|
|
// Handles a null argument
|
|
ret = rend_cache_entry_allocation(NULL);
|
|
tt_int_op(ret, OP_EQ, 0);
|
|
|
|
// Handles a non-null argument
|
|
e = tor_malloc_zero(sizeof(rend_cache_entry_t));
|
|
ret = rend_cache_entry_allocation(e);
|
|
tt_int_op(ret, OP_GT, sizeof(rend_cache_entry_t));
|
|
|
|
done:
|
|
tor_free(e);
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_failure_intro_entry_free(void *data)
|
|
{
|
|
(void)data;
|
|
rend_cache_failure_intro_t *entry;
|
|
|
|
// Handles a null argument
|
|
rend_cache_failure_intro_entry_free(NULL);
|
|
|
|
// Handles a non-null argument
|
|
entry = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT);
|
|
rend_cache_failure_intro_entry_free(entry);
|
|
}
|
|
|
|
static void
|
|
test_rend_cache_failure_purge(void *data)
|
|
{
|
|
(void)data;
|
|
|
|
// Handles a null failure cache
|
|
strmap_free(rend_cache_failure, rend_cache_failure_entry_free_);
|
|
rend_cache_failure = NULL;
|
|
|
|
rend_cache_failure_purge();
|
|
|
|
tt_ptr_op(rend_cache_failure, OP_NE, NULL);
|
|
tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0);
|
|
|
|
done:
|
|
rend_cache_free_all();
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
struct testcase_t rend_cache_tests[] = {
|
|
{ "init", test_rend_cache_init, 0, NULL, NULL },
|
|
{ "decrement_allocation", test_rend_cache_decrement_allocation, 0,
|
|
NULL, NULL },
|
|
{ "increment_allocation", test_rend_cache_increment_allocation, 0,
|
|
NULL, NULL },
|
|
{ "clean", test_rend_cache_clean, TT_FORK, NULL, NULL },
|
|
{ "clean_v2_descs_as_dir", test_rend_cache_clean_v2_descs_as_dir, 0,
|
|
NULL, NULL },
|
|
{ "entry_allocation", test_rend_cache_entry_allocation, 0, NULL, NULL },
|
|
{ "entry_free", test_rend_cache_entry_free, 0, NULL, NULL },
|
|
{ "failure_intro_entry_free", test_rend_cache_failure_intro_entry_free, 0,
|
|
NULL, NULL },
|
|
{ "free_all", test_rend_cache_free_all, 0, NULL, NULL },
|
|
{ "purge", test_rend_cache_purge, 0, NULL, NULL },
|
|
{ "failure_clean", test_rend_cache_failure_clean, 0, NULL, NULL },
|
|
{ "failure_entry_new", test_rend_cache_failure_entry_new, 0, NULL, NULL },
|
|
{ "failure_entry_free", test_rend_cache_failure_entry_free, 0, NULL, NULL },
|
|
{ "failure_intro_add", test_rend_cache_failure_intro_add, 0, NULL, NULL },
|
|
{ "failure_intro_entry_new", test_rend_cache_failure_intro_entry_new, 0,
|
|
NULL, NULL },
|
|
{ "failure_intro_lookup", test_rend_cache_failure_intro_lookup, 0,
|
|
NULL, NULL },
|
|
{ "failure_purge", test_rend_cache_failure_purge, 0, NULL, NULL },
|
|
{ "failure_remove", test_rend_cache_failure_remove, 0, NULL, NULL },
|
|
{ "intro_failure_note", test_rend_cache_intro_failure_note, 0, NULL, NULL },
|
|
{ "lookup", test_rend_cache_lookup_entry, 0, NULL, NULL },
|
|
{ "lookup_v2_desc_as_dir", test_rend_cache_lookup_v2_desc_as_dir, 0,
|
|
NULL, NULL },
|
|
{ "store_v2_desc_as_client", test_rend_cache_store_v2_desc_as_client, 0,
|
|
NULL, NULL },
|
|
{ "store_v2_desc_as_client_with_different_time",
|
|
test_rend_cache_store_v2_desc_as_client_with_different_time, 0,
|
|
NULL, NULL },
|
|
{ "store_v2_desc_as_dir", test_rend_cache_store_v2_desc_as_dir, 0,
|
|
NULL, NULL },
|
|
{ "store_v2_desc_as_dir_with_different_time",
|
|
test_rend_cache_store_v2_desc_as_dir_with_different_time, 0, NULL, NULL },
|
|
{ "store_v2_desc_as_dir_with_different_content",
|
|
test_rend_cache_store_v2_desc_as_dir_with_different_content, 0,
|
|
NULL, NULL },
|
|
{ "validate_intro_point_failure",
|
|
test_rend_cache_validate_intro_point_failure, 0, NULL, NULL },
|
|
END_OF_TESTCASES
|
|
};
|
|
|