aboutsummaryrefslogtreecommitdiff
path: root/src/test/test_hs_common.c
diff options
context:
space:
mode:
authorGeorge Kadianakis <desnacked@riseup.net>2017-08-19 16:26:46 +0300
committerGeorge Kadianakis <desnacked@riseup.net>2017-08-19 16:28:48 +0300
commit7823c98a38556237a86c7235d411d7d2237cc2d6 (patch)
tree175f51c662f55ce9579fd1af186151b515e15429 /src/test/test_hs_common.c
parent26c85fcc863678c06cc79ec1a58bd6c504d3321a (diff)
downloadtor-7823c98a38556237a86c7235d411d7d2237cc2d6.tar.gz
tor-7823c98a38556237a86c7235d411d7d2237cc2d6.zip
prop224: Improve descriptor reupload logic.
We want to reupload our descriptor if its set of responsible HSDirs changed to minimize reachability issues. This patch adds a callback everytime we get new dirinfo which checks if the hash ring changed and reuploads descriptor if needed.
Diffstat (limited to 'src/test/test_hs_common.c')
-rw-r--r--src/test/test_hs_common.c163
1 files changed, 162 insertions, 1 deletions
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index db37663075..c60deb2ab9 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -18,7 +18,9 @@
#include "hs_service.h"
#include "config.h"
#include "networkstatus.h"
+#include "directory.h"
#include "nodelist.h"
+#include "statefile.h"
/** Test the validation of HS v3 addresses */
static void
@@ -486,6 +488,163 @@ test_responsible_hsdirs(void *arg)
networkstatus_vote_free(mock_ns);
}
+static void
+mock_directory_initiate_request(directory_request_t *req)
+{
+ (void)req;
+ return;
+}
+
+static int
+mock_hs_desc_encode_descriptor(const hs_descriptor_t *desc,
+ const ed25519_keypair_t *signing_kp,
+ char **encoded_out)
+{
+ (void)desc;
+ (void)signing_kp;
+
+ tor_asprintf(encoded_out, "lulu");
+ return 0;
+}
+
+static or_state_t dummy_state;
+
+/* Mock function to get fake or state (used for rev counters) */
+static or_state_t *
+get_or_state_replacement(void)
+{
+ return &dummy_state;
+}
+
+static int
+mock_router_have_minimum_dir_info(void)
+{
+ return 1;
+}
+
+/** Test that we correctly detect when the HSDir hash ring changes so that we
+ * reupload our descriptor. */
+static void
+test_desc_reupload_logic(void *arg)
+{
+ networkstatus_t *ns = NULL;
+
+ (void) arg;
+
+ hs_init();
+
+ MOCK(router_have_minimum_dir_info,
+ mock_router_have_minimum_dir_info);
+ MOCK(get_or_state,
+ get_or_state_replacement);
+ MOCK(networkstatus_get_latest_consensus,
+ mock_networkstatus_get_latest_consensus);
+ MOCK(directory_initiate_request,
+ mock_directory_initiate_request);
+ MOCK(hs_desc_encode_descriptor,
+ mock_hs_desc_encode_descriptor);
+
+ ns = networkstatus_get_latest_consensus();
+
+ /** Test logic:
+ * 1) Upload descriptor to HSDirs
+ * CHECK that previous_hsdirs list was populated.
+ * 2) Then call router_dir_info_changed() without an HSDir set change.
+ * CHECK that no reuplod occurs.
+ * 3) Now change the HSDir set, and call dir_info_changed() again.
+ * CHECK that reupload occurs.
+ * 4) Finally call service_desc_schedule_upload().
+ * CHECK that previous_hsdirs list was cleared.
+ **/
+
+ /* Let's start by building our descriptor and service */
+ hs_service_descriptor_t *desc = service_descriptor_new();
+ hs_service_t *service = NULL;
+ char onion_addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
+ ed25519_public_key_t pubkey;
+ memset(&pubkey, '\x42', sizeof(pubkey));
+ hs_build_address(&pubkey, HS_VERSION_THREE, onion_addr);
+ service = tor_malloc_zero(sizeof(hs_service_t));
+ memcpy(service->onion_address, onion_addr, sizeof(service->onion_address));
+ ed25519_secret_key_generate(&service->keys.identity_sk, 0);
+ ed25519_public_key_generate(&service->keys.identity_pk,
+ &service->keys.identity_sk);
+ service->desc_current = desc;
+ /* Also add service to service map */
+ hs_service_ht *service_map = get_hs_service_map();
+ tt_assert(service_map);
+ tt_int_op(hs_service_get_num_services(), OP_EQ, 0);
+ register_service(service_map, service);
+ tt_int_op(hs_service_get_num_services(), OP_EQ, 1);
+
+ /* Now let's create our hash ring: */
+ { /* First HSDir */
+ uint8_t identity[DIGEST_LEN];
+ uint8_t curr_hsdir_index[DIGEST256_LEN];
+ char nickname[] = "let_me";
+ memset(identity, 1, sizeof(identity));
+ memset(curr_hsdir_index, 1, sizeof(curr_hsdir_index));
+
+ helper_add_hsdir_to_networkstatus(ns, identity,
+ curr_hsdir_index, nickname, 1);
+ }
+
+ { /* Second HSDir */
+ uint8_t identity[DIGEST_LEN];
+ uint8_t curr_hsdir_index[DIGEST256_LEN];
+ char nickname[] = "show_you";
+ memset(identity, 2, sizeof(identity));
+ memset(curr_hsdir_index, 2, sizeof(curr_hsdir_index));
+
+ helper_add_hsdir_to_networkstatus(ns, identity,
+ curr_hsdir_index, nickname, 1);
+ }
+
+ /* Now let's upload our desc to all hsdirs */
+ upload_descriptor_to_all(service, desc, 0);
+ /* Check that previous hsdirs were populated */
+ tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 2);
+
+ /* Poison next upload time so that we can see if it was changed by
+ * router_dir_info_changed(). No changes in hash ring so far, so the upload
+ * time should stay as is. */
+ desc->next_upload_time = 42;
+ router_dir_info_changed();
+ tt_int_op(desc->next_upload_time, OP_EQ, 42);
+
+ /* Now change the HSDir hash ring by adding another node */
+
+ { /* Third HSDir */
+ uint8_t identity[DIGEST_LEN];
+ uint8_t curr_hsdir_index[DIGEST256_LEN];
+ char nickname[] = "how_to_dance";
+ memset(identity, 3, sizeof(identity));
+ memset(curr_hsdir_index, 3, sizeof(curr_hsdir_index));
+
+ helper_add_hsdir_to_networkstatus(ns, identity,
+ curr_hsdir_index, nickname, 1);
+ }
+
+ /* Now call router_dir_info_changed() again and see that it detected the hash
+ ring change and updated the upload time */
+ time_t now = approx_time();
+ tt_assert(now);
+ router_dir_info_changed();
+ tt_int_op(desc->next_upload_time, OP_EQ, now);
+
+ /* Now pretend that the descriptor changed, and order a reupload to all
+ HSDirs. Make sure that the set of previous HSDirs was cleared. */
+ service_desc_schedule_upload(desc, now, 1);
+ tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 0);
+
+ /* Now reupload again: see that the prev hsdir set got populated again. */
+ upload_descriptor_to_all(service, desc, 0);
+ tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 3);
+
+ done:
+ hs_free_all();
+}
+
/** Test disaster SRV computation and caching */
static void
test_disaster_srv(void *arg)
@@ -550,7 +709,9 @@ struct testcase_t hs_common_tests[] = {
NULL, NULL },
{ "desc_overlap_period_testnet", test_desc_overlap_period_testnet, TT_FORK,
NULL, NULL },
- { "desc_responsible_hsdirs", test_responsible_hsdirs, TT_FORK,
+ { "responsible_hsdirs", test_responsible_hsdirs, TT_FORK,
+ NULL, NULL },
+ { "desc_reupload_logic", test_desc_reupload_logic, TT_FORK,
NULL, NULL },
{ "disaster_srv", test_disaster_srv, TT_FORK, NULL, NULL },