commit 9eba65bd8b688497de139b57ac72e5b8a40bb728
Author: George Kadianakis <desnacked(a)riseup.net>
Date: Fri Jan 29 18:21:30 2021 +0200
test: Add test for exits blocking reentry to the network
Signed-off-by: David Goulet <dgoulet(a)torproject.org>
---
src/feature/nodelist/dirlist.c | 4 +-
src/feature/nodelist/dirlist.h | 2 +-
src/test/test_address_set.c | 87 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index 25f769dd5a..b4abffad67 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -71,8 +71,8 @@ add_trusted_dir_to_nodelist_addr_set(const dir_server_t *dir)
/** Go over the trusted directory server list and add their address(es) to the
* nodelist address set. This is called every time a new consensus is set. */
-void
-dirlist_add_trusted_dir_addresses(void)
+MOCK_IMPL(void,
+dirlist_add_trusted_dir_addresses, (void))
{
if (!trusted_dir_servers) {
return;
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index 9354769bcf..527af35427 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -44,6 +44,6 @@ void dir_server_add(dir_server_t *ent);
void clear_dir_servers(void);
void dirlist_free_all(void);
-void dirlist_add_trusted_dir_addresses(void);
+MOCK_DECL(void, dirlist_add_trusted_dir_addresses, (void));
#endif
diff --git a/src/test/test_address_set.c b/src/test/test_address_set.c
index fb8408b3c3..6d9fab67ab 100644
--- a/src/test/test_address_set.c
+++ b/src/test/test_address_set.c
@@ -4,6 +4,7 @@
#include "core/or/or.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/address_set.h"
+#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
@@ -31,6 +32,12 @@ mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
return dummy_ns;
}
+static void
+mock_dirlist_add_trusted_dir_addresses(void)
+{
+ return;
+}
+
/* Number of address a single node_t can have. Default to the production
* value. This is to control the size of the bloom filter. */
static int addr_per_node = 2;
@@ -169,11 +176,91 @@ test_nodelist(void *arg)
UNMOCK(get_estimated_address_per_node);
}
+/** Test that the no-reentry exit filter works as intended */
+static void
+test_exit_no_reentry(void *arg)
+{
+ routerstatus_t *rs = NULL; microdesc_t *md = NULL; routerinfo_t *ri = NULL;
+ (void) arg;
+
+ MOCK(networkstatus_get_latest_consensus,
+ mock_networkstatus_get_latest_consensus);
+ MOCK(networkstatus_get_latest_consensus_by_flavor,
+ mock_networkstatus_get_latest_consensus_by_flavor);
+ MOCK(get_estimated_address_per_node,
+ mock_get_estimated_address_per_node);
+ MOCK(dirlist_add_trusted_dir_addresses,
+ mock_dirlist_add_trusted_dir_addresses);
+
+ dummy_ns = tor_malloc_zero(sizeof(*dummy_ns));
+ dummy_ns->flavor = FLAV_MICRODESC;
+ dummy_ns->routerstatus_list = smartlist_new();
+
+ tor_addr_t addr_v4, addr_v6, dummy_addr;
+ tor_addr_parse(&addr_v4, "42.42.42.42");
+ tor_addr_parse(&addr_v6, "1:2:3:4::");
+ memset(&dummy_addr, 'A', sizeof(dummy_addr));
+
+ /* This will make the nodelist bloom filter very large
+ * (the_nodelist->node_addrs) so we will fail the contain test rarely. */
+ addr_per_node = 1024;
+
+ /* After this point the nodelist is populated with the directory authorities
+ * address and ports */
+ nodelist_set_consensus(dummy_ns);
+
+ /* The address set is empty. Try it anyway */
+ tt_assert(!nodelist_reentry_probably_contains(&addr_v4, 244));
+ tt_assert(!nodelist_reentry_probably_contains(&addr_v6, 244));
+
+ /* Now let's populate the network */
+ md = tor_malloc_zero(sizeof(*md));
+ ri = tor_malloc_zero(sizeof(*ri));
+ rs = tor_malloc_zero(sizeof(*rs));
+ crypto_rand(rs->identity_digest, sizeof(rs->identity_digest));
+ crypto_rand(md->digest, sizeof(md->digest));
+ memcpy(rs->descriptor_digest, md->digest, DIGEST256_LEN);
+
+ /* Setup the rs, ri and md addresses. */
+ rs->addr = tor_addr_to_ipv4h(&addr_v4);
+ rs->or_port = 444;
+ tor_addr_parse(&rs->ipv6_addr, "1:2:3:4::");
+ rs->ipv6_orport = 666;
+ ri->addr = tor_addr_to_ipv4h(&addr_v4);
+ tor_addr_parse(&ri->ipv6_addr, "1:2:3:4::");
+ tor_addr_parse(&md->ipv6_addr, "1:2:3:4::");
+
+ /* Add the rs to the consensus becoming a node_t. */
+ smartlist_add(dummy_ns->routerstatus_list, rs);
+ nodelist_set_consensus(dummy_ns);
+
+ /* Now that the nodelist is populated let's do some retry attempts */
+
+ /* First let's try an address that is on the no-reentry list, but with a
+ different port */
+ tt_assert(!nodelist_reentry_probably_contains(&addr_v4, 666));
+ tt_assert(!nodelist_reentry_probably_contains(&addr_v6, 444));
+
+ /* OK now let's try with the right address and right port */
+ tt_assert(nodelist_reentry_probably_contains(&addr_v4, 444));
+ tt_assert(nodelist_reentry_probably_contains(&addr_v6, 666));
+
+ done:
+ routerstatus_free(rs); routerinfo_free(ri); microdesc_free(md);
+ smartlist_clear(dummy_ns->routerstatus_list);
+ networkstatus_vote_free(dummy_ns);
+ UNMOCK(networkstatus_get_latest_consensus);
+ UNMOCK(networkstatus_get_latest_consensus_by_flavor);
+ UNMOCK(get_estimated_address_per_node);
+ UNMOCK(dirlist_add_trusted_dir_addresses);
+}
+
struct testcase_t address_set_tests[] = {
{ "contains", test_contains, TT_FORK,
NULL, NULL },
{ "nodelist", test_nodelist, TT_FORK,
NULL, NULL },
+ { "exit_no_reentry", test_exit_no_reentry, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};