]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Add unit test for selecting guards with exit restrictions
authorCecylia Bocovich <cohosh@torproject.org>
Tue, 24 Sep 2024 20:32:41 +0000 (16:32 -0400)
committerDavid Goulet <dgoulet@torproject.org>
Wed, 22 Jan 2025 14:01:51 +0000 (09:01 -0500)
This test checks to see whether guard selection for circuits honor exit
family restrictions.

src/test/test_entrynodes.c

index 7184e49c8c03186e553e734fde91eb2bd55acaa7..9b816e1d3f599a432a0d3aa1b7bcebc470416d8d 100644 (file)
@@ -24,6 +24,7 @@
 #include "feature/dirclient/dirclient.h"
 #include "feature/client/entrynodes.h"
 #include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/nodefamily.h"
 #include "feature/nodelist/networkstatus.h"
 #include "core/or/policies.h"
 #include "feature/nodelist/routerlist.h"
@@ -2324,6 +2325,75 @@ test_entry_guard_select_for_circuit_highlevel_primary_retry(void *arg)
   circuit_guard_state_free(guard2);
 }
 
+static void
+test_entry_guard_select_for_circuit_exit_family_restriction(void *arg)
+{
+  (void) arg;
+  entry_guard_restriction_t *rst = NULL;
+  entry_guard_restriction_t *rst2 = NULL;
+  guard_selection_t *gs = guard_selection_new("default", GS_TYPE_NORMAL);
+  int retval;
+  unsigned state = 9999;
+
+  /* Create our circuit */
+  circuit_t *circ = dummy_origin_circuit_new(30);
+  origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
+  oc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+
+  /* First pick the exit and pin it on the build_state */
+  retval = onion_pick_cpath_exit(oc, NULL, 0);
+  tt_int_op(retval, OP_EQ, 0);
+
+  /* Then pick a guard */
+  entry_guards_update_primary(gs);
+  entry_guard_t *g = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC,
+                                                    NULL, &state);
+
+  tt_assert(g);
+  tt_assert(g->is_primary);
+  tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION);
+  tt_i64_op(g->last_tried_to_connect, OP_EQ, approx_time());
+
+  /* Add the guard and the exit to each others' families */
+  get_options_mutable()->EnforceDistinctSubnets = 0;
+  const char* exit_id =
+      (const char*)build_state_get_exit_rsa_id(oc->build_state);
+  const node_t *exit = node_get_by_id(exit_id);
+  const node_t *guard = node_get_by_id(g->identity);
+  exit->md->family = nodefamily_parse((const char*)g->nickname,
+          node_get_rsa_id_digest(exit),0);
+  guard->md->family =
+      nodefamily_parse((const char*)exit->rs->nickname,
+              node_get_rsa_id_digest(guard),0);
+  tt_assert(nodefamily_contains_nickname(exit->md->family,
+              (const char*)g->nickname));
+
+  /* We should get a different guard, after adding the exit restriction */
+  rst = guard_create_exit_restriction((const uint8_t*)exit_id);
+  entry_guard_t *g2 =
+      select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst, &state);
+  tt_assert(g2);
+  tt_assert(g2->is_primary);
+  tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION);
+  tt_i64_op(g2->last_tried_to_connect, OP_EQ, approx_time());
+  tt_ptr_op(g2, OP_NE, g);
+
+  /* Now check that conflux circuits satisfy the exit family restriction */
+  rst2 = guard_create_conflux_restriction(oc, (const uint8_t*)exit_id);
+  g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst2, &state);
+  tt_assert(g2);
+  tt_assert(g2->is_primary);
+  tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION);
+  tt_i64_op(g2->last_tried_to_connect, OP_EQ, approx_time());
+  tt_ptr_op(g2, OP_NE, g);
+
+ done:
+  circuit_free_(circ);
+  guard_selection_free(gs);
+  entry_guard_restriction_free(rst);
+  entry_guard_restriction_free(rst2);
+}
+
 static void
 test_entry_guard_select_and_cancel(void *arg)
 {
@@ -3201,6 +3271,7 @@ struct testcase_t entrynodes_tests[] = {
   BFN_TEST(select_for_circuit_highlevel_primary),
   BFN_TEST(select_for_circuit_highlevel_confirm_other),
   BFN_TEST(select_for_circuit_highlevel_primary_retry),
+  BFN_TEST(select_for_circuit_exit_family_restriction),
   BFN_TEST(select_and_cancel),
   BFN_TEST(drop_guards),
   BFN_TEST(outdated_dirserver_exclusion),