diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/include.am | 1 | ||||
-rw-r--r-- | src/test/test.c | 1 | ||||
-rw-r--r-- | src/test/test.h | 1 | ||||
-rw-r--r-- | src/test/test_hs_dos.c | 134 | ||||
-rw-r--r-- | src/test/test_hs_intropoint.c | 48 |
5 files changed, 173 insertions, 12 deletions
diff --git a/src/test/include.am b/src/test/include.am index 7cd1ecae36..1e20f3f53f 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -158,6 +158,7 @@ src_test_test_SOURCES += \ src/test/test_handles.c \ src/test/test_hs_cache.c \ src/test/test_hs_descriptor.c \ + src/test/test_hs_dos.c \ src/test/test_introduce.c \ src/test/test_keypin.c \ src/test/test_link_handshake.c \ diff --git a/src/test/test.c b/src/test/test.c index 266b7454a3..b9a1da06f0 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -877,6 +877,7 @@ struct testgroup_t testgroups[] = { { "hs_config/", hs_config_tests }, { "hs_control/", hs_control_tests }, { "hs_descriptor/", hs_descriptor }, + { "hs_dos/", hs_dos_tests }, { "hs_intropoint/", hs_intropoint_tests }, { "hs_ntor/", hs_ntor_tests }, { "hs_service/", hs_service_tests }, diff --git a/src/test/test.h b/src/test/test.h index 322716a9ab..f5c21bfe88 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -227,6 +227,7 @@ extern struct testcase_t hs_common_tests[]; extern struct testcase_t hs_config_tests[]; extern struct testcase_t hs_control_tests[]; extern struct testcase_t hs_descriptor[]; +extern struct testcase_t hs_dos_tests[]; extern struct testcase_t hs_intropoint_tests[]; extern struct testcase_t hs_ntor_tests[]; extern struct testcase_t hs_service_tests[]; diff --git a/src/test/test_hs_dos.c b/src/test/test_hs_dos.c new file mode 100644 index 0000000000..3dfa057a4a --- /dev/null +++ b/src/test/test_hs_dos.c @@ -0,0 +1,134 @@ +/* Copyright (c) 2017-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_hs_cell.c + * \brief Test hidden service cell functionality. + */ + +#define CIRCUITLIST_PRIVATE +#define NETWORKSTATUS_PRIVATE + +#include "test/test.h" +#include "test/test_helpers.h" +#include "test/log_test_helpers.h" + +#include "app/config/config.h" + +#include "core/or/circuitlist.h" +#include "core/or/circuituse.h" +#include "core/or/or_circuit_st.h" + +#include "feature/hs/hs_dos.h" +#include "feature/nodelist/networkstatus.h" + +static void +setup_mock_consensus(void) +{ + current_ns_consensus = tor_malloc_zero(sizeof(networkstatus_t)); + current_ns_consensus->net_params = smartlist_new(); + smartlist_add(current_ns_consensus->net_params, + (void *) "HiddenServiceEnableIntroDoSDefense=1"); + hs_dos_consensus_has_changed(current_ns_consensus); +} + +static void +free_mock_consensus(void) +{ + smartlist_free(current_ns_consensus->net_params); + tor_free(current_ns_consensus); +} + +static void +test_can_send_intro2(void *arg) +{ + uint32_t now = (uint32_t) approx_time(); + or_circuit_t *or_circ = NULL; + + (void) arg; + + hs_init(); + hs_dos_init(); + + get_options_mutable()->ORPort_set = 1; + setup_mock_consensus(); + + or_circ = or_circuit_new(1, NULL); + + /* Make that circuit a service intro point. */ + circuit_change_purpose(TO_CIRCUIT(or_circ), CIRCUIT_PURPOSE_INTRO_POINT); + /* Initialize the INTRODUCE2 token bucket for the rate limiting. */ + token_bucket_ctr_init(&or_circ->introduce2_bucket, hs_dos_get_intro2_rate(), + hs_dos_get_intro2_burst(), now); + + /* Brand new circuit, we should be able to send INTRODUCE2 cells. */ + tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); + + /* Simulate that 10 cells have arrived in 1 second. There should be no + * refill since the bucket is already at maximum on the first cell. */ + update_approx_time(++now); + for (int i = 0; i < 10; i++) { + tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); + } + tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, + hs_dos_get_intro2_burst() - 10); + + /* Fully refill the bucket minus 1 cell. */ + update_approx_time(++now); + tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); + tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, + hs_dos_get_intro2_burst() - 1); + + /* Receive an INTRODUCE2 at each second. We should have the bucket full + * since at every second it gets refilled. */ + for (int i = 0; i < 10; i++) { + update_approx_time(++now); + tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); + } + /* Last check if we can send the cell decrements the bucket so minus 1. */ + tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, + hs_dos_get_intro2_burst() - 1); + + /* Manually reset bucket for next test. */ + token_bucket_ctr_reset(&or_circ->introduce2_bucket, now); + tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, + hs_dos_get_intro2_burst()); + + /* Do a full burst in the current second which should empty the bucket and + * we shouldn't be allowed to send one more cell after that. We go minus 1 + * cell else the very last check if we can send the INTRO2 cell returns + * false because the bucket goes down to 0. */ + for (uint32_t i = 0; i < hs_dos_get_intro2_burst() - 1; i++) { + tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); + } + tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 1); + /* Get the last remaining cell, we shouldn't be allowed to send it. */ + tt_int_op(false, OP_EQ, hs_dos_can_send_intro2(or_circ)); + tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 0); + + /* Make sure the next 100 cells aren't allowed and bucket stays at 0. */ + for (int i = 0; i < 100; i++) { + tt_int_op(false, OP_EQ, hs_dos_can_send_intro2(or_circ)); + tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 0); + } + + /* One second has passed, we should have the rate minus 1 cell added. */ + update_approx_time(++now); + tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); + tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, + hs_dos_get_intro2_rate() - 1); + + done: + circuit_free_(TO_CIRCUIT(or_circ)); + + hs_free_all(); + free_mock_consensus(); +} + +struct testcase_t hs_dos_tests[] = { + { "can_send_intro2", test_can_send_intro2, TT_FORK, + NULL, NULL }, + + END_OF_TESTCASES +}; + diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c index 0cdb1fef27..7b01809f96 100644 --- a/src/test/test_hs_intropoint.c +++ b/src/test/test_hs_intropoint.c @@ -26,6 +26,7 @@ #include "feature/hs/hs_cell.h" #include "feature/hs/hs_circuitmap.h" #include "feature/hs/hs_common.h" +#include "feature/hs/hs_dos.h" #include "feature/hs/hs_intropoint.h" #include "feature/hs/hs_service.h" @@ -119,6 +120,8 @@ helper_create_intro_circuit(void) or_circuit_t *circ = or_circuit_new(0, NULL); tt_assert(circ); circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_OR); + token_bucket_ctr_init(&circ->introduce2_bucket, 100, 100, + (uint32_t) approx_time()); done: return circ; } @@ -900,42 +903,63 @@ test_received_introduce1_handling(void *arg) UNMOCK(relay_send_command_from_edge_); } +static void * +hs_subsystem_setup_fn(const struct testcase_t *tc) +{ + (void) tc; + + return NULL; +} + +static int +hs_subsystem_cleanup_fn(const struct testcase_t *tc, void *arg) +{ + (void) tc; + (void) arg; + + return 1; +} + +static struct testcase_setup_t test_setup = { + hs_subsystem_setup_fn, hs_subsystem_cleanup_fn +}; + struct testcase_t hs_intropoint_tests[] = { { "intro_point_registration", - test_intro_point_registration, TT_FORK, NULL, NULL }, + test_intro_point_registration, TT_FORK, NULL, &test_setup}, { "receive_establish_intro_wrong_keytype", - test_establish_intro_wrong_keytype, TT_FORK, NULL, NULL }, + test_establish_intro_wrong_keytype, TT_FORK, NULL, &test_setup}, { "receive_establish_intro_wrong_keytype2", - test_establish_intro_wrong_keytype2, TT_FORK, NULL, NULL }, + test_establish_intro_wrong_keytype2, TT_FORK, NULL, &test_setup}, { "receive_establish_intro_wrong_purpose", - test_establish_intro_wrong_purpose, TT_FORK, NULL, NULL }, + test_establish_intro_wrong_purpose, TT_FORK, NULL, &test_setup}, { "receive_establish_intro_wrong_sig", - test_establish_intro_wrong_sig, TT_FORK, NULL, NULL }, + test_establish_intro_wrong_sig, TT_FORK, NULL, &test_setup}, { "receive_establish_intro_wrong_sig_len", - test_establish_intro_wrong_sig_len, TT_FORK, NULL, NULL }, + test_establish_intro_wrong_sig_len, TT_FORK, NULL, &test_setup}, { "receive_establish_intro_wrong_auth_key_len", - test_establish_intro_wrong_auth_key_len, TT_FORK, NULL, NULL }, + test_establish_intro_wrong_auth_key_len, TT_FORK, NULL, &test_setup}, { "receive_establish_intro_wrong_mac", - test_establish_intro_wrong_mac, TT_FORK, NULL, NULL }, + test_establish_intro_wrong_mac, TT_FORK, NULL, &test_setup}, { "introduce1_suitable_circuit", - test_introduce1_suitable_circuit, TT_FORK, NULL, NULL }, + test_introduce1_suitable_circuit, TT_FORK, NULL, &test_setup}, { "introduce1_is_legacy", - test_introduce1_is_legacy, TT_FORK, NULL, NULL }, + test_introduce1_is_legacy, TT_FORK, NULL, &test_setup}, { "introduce1_validation", - test_introduce1_validation, TT_FORK, NULL, NULL }, + test_introduce1_validation, TT_FORK, NULL, &test_setup}, { "received_introduce1_handling", - test_received_introduce1_handling, TT_FORK, NULL, NULL }, + test_received_introduce1_handling, TT_FORK, NULL, &test_setup}, END_OF_TESTCASES }; |