test_hs_dos.c (6022B)
1 /* Copyright (c) 2017-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 /** 5 * \file test_hs_cell.c 6 * \brief Test hidden service cell functionality. 7 */ 8 9 #define CIRCUITLIST_PRIVATE 10 #define NETWORKSTATUS_PRIVATE 11 #define HS_DOS_PRIVATE 12 #define HS_INTROPOINT_PRIVATE 13 14 #include "test/test.h" 15 #include "test/test_helpers.h" 16 #include "test/log_test_helpers.h" 17 18 #include "app/config/config.h" 19 #include "lib/time/compat_time.h" 20 21 #include "core/or/circuitlist.h" 22 #include "core/or/circuituse.h" 23 #include "core/or/or_circuit_st.h" 24 25 #include "feature/hs/hs_dos.h" 26 #include "feature/hs/hs_intropoint.h" 27 #include "feature/nodelist/networkstatus.h" 28 29 static void 30 setup_mock_consensus(void) 31 { 32 current_ns_consensus = tor_malloc_zero(sizeof(networkstatus_t)); 33 current_ns_consensus->net_params = smartlist_new(); 34 smartlist_add(current_ns_consensus->net_params, 35 (void *) "HiddenServiceEnableIntroDoSDefense=1"); 36 hs_dos_consensus_has_changed(current_ns_consensus); 37 } 38 39 static void 40 free_mock_consensus(void) 41 { 42 smartlist_free(current_ns_consensus->net_params); 43 tor_free(current_ns_consensus); 44 } 45 46 static void 47 test_can_send_intro2(void *arg) 48 { 49 static const uint64_t BILLION = 1000000000; 50 uint64_t now = 12345; 51 or_circuit_t *or_circ = NULL; 52 53 (void) arg; 54 55 hs_init(); 56 hs_dos_init(); 57 58 get_options_mutable()->ORPort_set = 1; 59 setup_mock_consensus(); 60 monotime_enable_test_mocking(); 61 monotime_coarse_set_mock_time_nsec(now); 62 63 or_circ = or_circuit_new(1, NULL); 64 65 /* Make that circuit a service intro point. */ 66 circuit_change_purpose(TO_CIRCUIT(or_circ), CIRCUIT_PURPOSE_INTRO_POINT); 67 hs_dos_setup_default_intro2_defenses(or_circ); 68 or_circ->introduce2_dos_defense_enabled = 1; 69 70 /* Brand new circuit, we should be able to send INTRODUCE2 cells. */ 71 tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); 72 73 /* Simulate that 10 cells have arrived in 1 second. There should be no 74 * refill since the bucket is already at maximum on the first cell. */ 75 monotime_coarse_set_mock_time_nsec(now += BILLION); 76 for (int i = 0; i < 10; i++) { 77 tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); 78 } 79 tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 80 get_intro2_burst_consensus_param(NULL) - 10); 81 82 /* Fully refill the bucket minus 1 cell. */ 83 monotime_coarse_set_mock_time_nsec(now += BILLION); 84 tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); 85 tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 86 get_intro2_burst_consensus_param(NULL) - 1); 87 88 /* Receive an INTRODUCE2 at each second. We should have the bucket full 89 * since at every second it gets refilled. */ 90 for (int i = 0; i < 10; i++) { 91 monotime_coarse_set_mock_time_nsec(now += BILLION); 92 tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); 93 } 94 /* Last check if we can send the cell decrements the bucket so minus 1. */ 95 tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 96 get_intro2_burst_consensus_param(NULL) - 1); 97 98 /* Manually reset bucket for next test. */ 99 token_bucket_ctr_reset(&or_circ->introduce2_bucket, 100 (uint32_t) monotime_coarse_absolute_sec()); 101 tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 102 get_intro2_burst_consensus_param(NULL)); 103 104 /* Do a full burst in the current second which should empty the bucket and 105 * we shouldn't be allowed to send one more cell after that. We go minus 1 106 * cell else the very last check if we can send the INTRO2 cell returns 107 * false because the bucket goes down to 0. */ 108 for (uint32_t i = 0; i < get_intro2_burst_consensus_param(NULL) - 1; i++) { 109 tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); 110 } 111 tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 1); 112 /* Get the last remaining cell, we shouldn't be allowed to send it. */ 113 tt_int_op(false, OP_EQ, hs_dos_can_send_intro2(or_circ)); 114 tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 0); 115 116 /* Make sure the next 100 cells aren't allowed and bucket stays at 0. */ 117 for (int i = 0; i < 100; i++) { 118 tt_int_op(false, OP_EQ, hs_dos_can_send_intro2(or_circ)); 119 tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 0); 120 } 121 122 /* One second has passed, we should have the rate minus 1 cell added. */ 123 monotime_coarse_set_mock_time_nsec(now += BILLION); 124 tt_int_op(true, OP_EQ, hs_dos_can_send_intro2(or_circ)); 125 tt_uint_op(token_bucket_ctr_get(&or_circ->introduce2_bucket), OP_EQ, 126 get_intro2_rate_consensus_param(NULL) - 1); 127 128 done: 129 circuit_free_(TO_CIRCUIT(or_circ)); 130 131 hs_free_all(); 132 free_mock_consensus(); 133 monotime_disable_test_mocking(); 134 } 135 136 static void 137 test_validate_dos_extension_params(void *arg) 138 { 139 bool ret; 140 141 (void) arg; 142 143 /* Validate the default values. */ 144 ret = cell_dos_extension_parameters_are_valid( 145 get_intro2_rate_consensus_param(NULL), 146 get_intro2_burst_consensus_param(NULL)); 147 tt_assert(ret); 148 149 /* Valid custom rate/burst. */ 150 ret = cell_dos_extension_parameters_are_valid(17, 42); 151 tt_assert(ret); 152 ret = cell_dos_extension_parameters_are_valid(INT32_MAX, INT32_MAX); 153 tt_assert(ret); 154 155 /* Invalid rate. */ 156 ret = cell_dos_extension_parameters_are_valid(UINT64_MAX, 42); 157 tt_assert(!ret); 158 159 /* Invalid burst. */ 160 ret = cell_dos_extension_parameters_are_valid(42, UINT64_MAX); 161 tt_assert(!ret); 162 163 /* Value of 0 is valid (but should disable defenses) */ 164 ret = cell_dos_extension_parameters_are_valid(0, 0); 165 tt_assert(ret); 166 167 /* Can't have burst smaller than rate. */ 168 ret = cell_dos_extension_parameters_are_valid(42, 40); 169 tt_assert(!ret); 170 171 done: 172 return; 173 } 174 175 struct testcase_t hs_dos_tests[] = { 176 { "can_send_intro2", test_can_send_intro2, TT_FORK, 177 NULL, NULL }, 178 { "validate_dos_extension_params", test_validate_dos_extension_params, 179 TT_FORK, NULL, NULL }, 180 181 END_OF_TESTCASES 182 };