diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/hs_test_helpers.c | 3 | ||||
-rw-r--r-- | src/test/include.am | 4 | ||||
-rw-r--r-- | src/test/test.c | 2 | ||||
-rw-r--r-- | src/test/test_addr.c | 4 | ||||
-rw-r--r-- | src/test/test_circuitpadding.c | 650 | ||||
-rw-r--r-- | src/test/test_circuitstats.c | 16 | ||||
-rw-r--r-- | src/test/test_crypto.c | 4 | ||||
-rw-r--r-- | src/test/test_crypto_slow.c | 2 | ||||
-rw-r--r-- | src/test/test_extorport.c | 4 | ||||
-rw-r--r-- | src/test/test_hs.c | 2 | ||||
-rw-r--r-- | src/test/test_hs_cache.c | 2 | ||||
-rw-r--r-- | src/test/test_hs_client.c | 37 | ||||
-rw-r--r-- | src/test/test_hs_descriptor.c | 6 | ||||
-rw-r--r-- | src/test/test_hs_service.c | 28 | ||||
-rw-r--r-- | src/test/test_link_handshake.c | 4 | ||||
-rw-r--r-- | src/test/test_options.c | 1 | ||||
-rw-r--r-- | src/test/test_policy.c | 235 | ||||
-rw-r--r-- | src/test/test_relaycrypt.c | 10 | ||||
-rw-r--r-- | src/test/test_routerkeys.c | 4 | ||||
-rw-r--r-- | src/test/test_shared_random.c | 4 | ||||
-rw-r--r-- | src/test/test_util.c | 14 | ||||
-rw-r--r-- | src/test/test_util_format.c | 2 |
22 files changed, 908 insertions, 130 deletions
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c index c57bdc730b..0a21fe576b 100644 --- a/src/test/hs_test_helpers.c +++ b/src/test/hs_test_helpers.c @@ -162,11 +162,8 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip, /* Add four intro points. */ smartlist_add(desc->encrypted_data.intro_points, hs_helper_build_intro_point(signing_kp, now, "1.2.3.4", 0)); -/* IPv6-only introduction points are not supported yet, see #23588 */ -#if 0 smartlist_add(desc->encrypted_data.intro_points, hs_helper_build_intro_point(signing_kp, now, "[2600::1]", 0)); -#endif smartlist_add(desc->encrypted_data.intro_points, hs_helper_build_intro_point(signing_kp, now, "3.2.1.4", 1)); smartlist_add(desc->encrypted_data.intro_points, diff --git a/src/test/include.am b/src/test/include.am index 899e0de7d9..824089bc47 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -46,10 +46,8 @@ TESTS += src/test/test src/test/test-slow src/test/test-memwipe \ TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-v2-min hs-v3-min \ single-onion-v23 # only run if we can ping6 ::1 (localhost) -# IPv6-only v3 single onion services don't work yet, so we don't test the -# single-onion-v23-ipv6-md flavor TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-v23-ipv6-md \ - single-onion-ipv6-md + single-onion-v23-ipv6-md # only run if we can find a stable (or simply another) version of tor TEST_CHUTNEY_FLAVORS_MIXED = mixed+hs-v2 diff --git a/src/test/test.c b/src/test/test.c index b19bf3bd88..cac98dd839 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -284,7 +284,7 @@ test_fast_handshake(void *arg) /* First, test an entire handshake. */ memset(client_handshake, 0, sizeof(client_handshake)); tt_int_op(0, OP_EQ, fast_onionskin_create(&state, client_handshake)); - tt_assert(! tor_mem_is_zero((char*)client_handshake, + tt_assert(! fast_mem_is_zero((char*)client_handshake, sizeof(client_handshake))); tt_int_op(0, OP_EQ, diff --git a/src/test/test_addr.c b/src/test/test_addr.c index 3a1a7b6997..05d8bf6c7b 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -240,7 +240,7 @@ test_addr_ip6_helpers(void *arg) tt_int_op(0,OP_EQ, tor_addr_lookup("9000::5", AF_UNSPEC, &t1)); tt_int_op(AF_INET6,OP_EQ, tor_addr_family(&t1)); tt_int_op(0x90,OP_EQ, tor_addr_to_in6_addr8(&t1)[0]); - tt_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14)); + tt_assert(fast_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14)); tt_int_op(0x05,OP_EQ, tor_addr_to_in6_addr8(&t1)[15]); /* === Test pton: valid af_inet6 */ @@ -697,7 +697,7 @@ test_addr_ip6_helpers(void *arg) &t1,&mask,&port1,&port2); tt_int_op(r,OP_EQ,AF_INET6); tt_int_op(tor_addr_family(&t1),OP_EQ,AF_INET6); - tt_assert(tor_mem_is_zero((const char*)tor_addr_to_in6_addr32(&t1), 16)); + tt_assert(fast_mem_is_zero((const char*)tor_addr_to_in6_addr32(&t1), 16)); tt_int_op(mask,OP_EQ,0); tt_int_op(port1,OP_EQ,1); tt_int_op(port2,OP_EQ,65535); diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c index 3289c866cf..bd6697922e 100644 --- a/src/test/test_circuitpadding.c +++ b/src/test/test_circuitpadding.c @@ -2,6 +2,7 @@ #define TOR_TIMERS_PRIVATE #define CIRCUITPADDING_PRIVATE #define NETWORKSTATUS_PRIVATE +#define CRYPT_PATH_PRIVATE #include "core/or/or.h" #include "test.h" @@ -9,6 +10,7 @@ #include "core/or/connection_or.h" #include "core/or/channel.h" #include "core/or/channeltls.h" +#include "core/or/crypt_path.h" #include <event.h> #include "lib/evloop/compat_libevent.h" #include "lib/time/compat_time.h" @@ -39,6 +41,7 @@ TOR_NSEC_PER_USEC*TOR_USEC_PER_SEC) extern smartlist_t *connection_array; +void circuit_expire_old_circuits_clientside(void); circid_t get_unique_circ_id_by_chan(channel_t *chan); void helper_create_basic_machine(void); @@ -53,6 +56,7 @@ void test_circuitpadding_conditions(void *arg); void test_circuitpadding_serialize(void *arg); void test_circuitpadding_rtt(void *arg); void test_circuitpadding_tokens(void *arg); +void test_circuitpadding_state_length(void *arg); static void simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay, @@ -143,12 +147,12 @@ new_fake_orcirc(channel_t *nchan, channel_t *pchan) circuit_set_n_circid_chan(circ, circ->n_circ_id, nchan); memset(&tmp_cpath, 0, sizeof(tmp_cpath)); - if (circuit_init_cpath_crypto(&tmp_cpath, whatevs_key, + if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key, sizeof(whatevs_key), 0, 0)<0) { log_warn(LD_BUG,"Circuit initialization failed"); return NULL; } - orcirc->crypto = tmp_cpath.crypto; + orcirc->crypto = tmp_cpath.pvt_crypto; return orcirc; } @@ -327,12 +331,12 @@ test_circuitpadding_rtt(void *arg) relay_side->padding_info[0] = circpad_circuit_machineinfo_new(client_side,0); /* Test 1: Test measuring RTT */ - circpad_cell_event_nonpadding_received((circuit_t*)relay_side); + circpad_cell_event_nonpadding_received(relay_side); tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_NE, 0); timers_advance_and_run(20); - circpad_cell_event_nonpadding_sent((circuit_t*)relay_side); + circpad_cell_event_nonpadding_sent(relay_side); tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_EQ, 0); tt_int_op(relay_side->padding_info[0]->rtt_estimate_usec, OP_GE, 19000); @@ -343,12 +347,12 @@ test_circuitpadding_rtt(void *arg) circpad_machine_current_state( relay_side->padding_info[0])->histogram_edges[0]); - circpad_cell_event_nonpadding_received((circuit_t*)relay_side); - circpad_cell_event_nonpadding_received((circuit_t*)relay_side); + circpad_cell_event_nonpadding_received(relay_side); + circpad_cell_event_nonpadding_received(relay_side); tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_NE, 0); timers_advance_and_run(20); - circpad_cell_event_nonpadding_sent((circuit_t*)relay_side); - circpad_cell_event_nonpadding_sent((circuit_t*)relay_side); + circpad_cell_event_nonpadding_sent(relay_side); + circpad_cell_event_nonpadding_sent(relay_side); tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_EQ, 0); tt_int_op(relay_side->padding_info[0]->rtt_estimate_usec, OP_GE, 20000); @@ -363,9 +367,9 @@ test_circuitpadding_rtt(void *arg) tt_int_op(relay_side->padding_info[0]->stop_rtt_update, OP_EQ, 1); rtt_estimate = relay_side->padding_info[0]->rtt_estimate_usec; - circpad_cell_event_nonpadding_received((circuit_t*)relay_side); + circpad_cell_event_nonpadding_received(relay_side); timers_advance_and_run(4); - circpad_cell_event_nonpadding_sent((circuit_t*)relay_side); + circpad_cell_event_nonpadding_sent(relay_side); tt_int_op(relay_side->padding_info[0]->rtt_estimate_usec, OP_EQ, rtt_estimate); @@ -378,11 +382,11 @@ test_circuitpadding_rtt(void *arg) relay_side->padding_info[0])->histogram_edges[0]); /* Test 3: Make sure client side machine properly ignores RTT */ - circpad_cell_event_nonpadding_received((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); tt_u64_op(client_side->padding_info[0]->last_received_time_usec, OP_EQ, 0); timers_advance_and_run(20); - circpad_cell_event_nonpadding_sent((circuit_t*)client_side); + circpad_cell_event_nonpadding_sent(client_side); tt_u64_op(client_side->padding_info[0]->last_received_time_usec, OP_EQ, 0); tt_int_op(client_side->padding_info[0]->rtt_estimate_usec, OP_EQ, 0); @@ -413,6 +417,7 @@ helper_create_basic_machine(void) circ_client_machine.states[CIRCPAD_STATE_START]. next_state[CIRCPAD_EVENT_NONPADDING_RECV] = CIRCPAD_STATE_BURST; + circ_client_machine.states[CIRCPAD_STATE_START].use_rtt_estimate = 1; circ_client_machine.states[CIRCPAD_STATE_BURST]. next_state[CIRCPAD_EVENT_PADDING_RECV] = CIRCPAD_STATE_BURST; @@ -524,7 +529,7 @@ test_circuitpadding_token_removal_higher(void *arg) MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock); /* Setup test environment (time etc.) */ - client_side = (circuit_t *)origin_circuit_new(); + client_side = TO_CIRCUIT(origin_circuit_new()); client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; monotime_enable_test_mocking(); @@ -535,7 +540,7 @@ test_circuitpadding_token_removal_higher(void *arg) circpad_circuit_machineinfo_new(client_side, 0); /* move the machine to the right state */ - circpad_cell_event_nonpadding_received((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); tt_int_op(client_side->padding_info[0]->current_state, OP_EQ, CIRCPAD_STATE_BURST); @@ -584,12 +589,12 @@ test_circuitpadding_token_removal_higher(void *arg) tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 2); mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 1); mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); /* Test that we cleaned out this bin. Don't do this in the case of the last bin since the tokens will get refilled */ @@ -608,7 +613,7 @@ test_circuitpadding_token_removal_higher(void *arg) CIRCPAD_STATE_BURST); circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[0] = 100; mi->padding_scheduled_at_usec = current_time; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[0], OP_EQ, 1); done: @@ -629,7 +634,7 @@ test_circuitpadding_token_removal_lower(void *arg) MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock); /* Setup test environment (time etc.) */ - client_side = (circuit_t *)origin_circuit_new(); + client_side = TO_CIRCUIT(origin_circuit_new()); client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; monotime_enable_test_mocking(); @@ -640,7 +645,7 @@ test_circuitpadding_token_removal_lower(void *arg) circpad_circuit_machineinfo_new(client_side, 0); /* move the machine to the right state */ - circpad_cell_event_nonpadding_received((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); tt_int_op(client_side->padding_info[0]->current_state, OP_EQ, CIRCPAD_STATE_BURST); @@ -681,12 +686,12 @@ test_circuitpadding_token_removal_lower(void *arg) tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 2); mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 1); mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); /* Test that we cleaned out this bin. Don't do this in the case of the last bin since the tokens will get refilled */ @@ -706,7 +711,7 @@ test_circuitpadding_token_removal_lower(void *arg) circ_client_machine.states[CIRCPAD_STATE_BURST]. histogram_edges[BIG_HISTOGRAM_LEN-2] = 100; mi->padding_scheduled_at_usec = current_time - 29202; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[BIG_HISTOGRAM_LEN-2], OP_EQ, 1); done: @@ -727,7 +732,7 @@ test_circuitpadding_closest_token_removal(void *arg) MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock); /* Setup test environment (time etc.) */ - client_side = (circuit_t *)origin_circuit_new(); + client_side = TO_CIRCUIT(origin_circuit_new()); client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; monotime_enable_test_mocking(); @@ -738,7 +743,7 @@ test_circuitpadding_closest_token_removal(void *arg) circpad_circuit_machineinfo_new(client_side, 0); /* move the machine to the right state */ - circpad_cell_event_nonpadding_received((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); tt_int_op(client_side->padding_info[0]->current_state, OP_EQ, CIRCPAD_STATE_BURST); @@ -778,12 +783,12 @@ test_circuitpadding_closest_token_removal(void *arg) tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 2); mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 1); mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); /* Test that we cleaned out this bin. Don't do this in the case of the last bin since the tokens will get refilled */ @@ -805,14 +810,14 @@ test_circuitpadding_closest_token_removal(void *arg) circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[2] = 120; mi->padding_scheduled_at_usec = current_time - 102; mi->histogram[0] = 0; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[1], OP_EQ, 1); /* Test above the highest bin, for coverage */ tt_int_op(client_side->padding_info[0]->current_state, OP_EQ, CIRCPAD_STATE_BURST); mi->padding_scheduled_at_usec = current_time - 29202; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[BIG_HISTOGRAM_LEN-2], OP_EQ, 1); done: @@ -833,7 +838,7 @@ test_circuitpadding_closest_token_removal_usec(void *arg) MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock); /* Setup test environment (time etc.) */ - client_side = (circuit_t *)origin_circuit_new(); + client_side = TO_CIRCUIT(origin_circuit_new()); client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; monotime_enable_test_mocking(); @@ -844,7 +849,7 @@ test_circuitpadding_closest_token_removal_usec(void *arg) circpad_circuit_machineinfo_new(client_side, 0); /* move the machine to the right state */ - circpad_cell_event_nonpadding_received((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); tt_int_op(client_side->padding_info[0]->current_state, OP_EQ, CIRCPAD_STATE_BURST); @@ -887,12 +892,12 @@ test_circuitpadding_closest_token_removal_usec(void *arg) tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 2); mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 1); mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); /* Test that we cleaned out this bin. Don't do this in the case of the last bin since the tokens will get refilled */ @@ -914,7 +919,7 @@ test_circuitpadding_closest_token_removal_usec(void *arg) circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[2] = 120; mi->padding_scheduled_at_usec = current_time - 102; mi->histogram[0] = 0; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[1], OP_EQ, 1); /* Test above the highest bin, for coverage */ @@ -923,7 +928,7 @@ test_circuitpadding_closest_token_removal_usec(void *arg) circ_client_machine.states[CIRCPAD_STATE_BURST]. histogram_edges[BIG_HISTOGRAM_LEN-2] = 100; mi->padding_scheduled_at_usec = current_time - 29202; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[BIG_HISTOGRAM_LEN-2], OP_EQ, 1); done: @@ -944,7 +949,7 @@ test_circuitpadding_token_removal_exact(void *arg) MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock); /* Setup test environment (time etc.) */ - client_side = (circuit_t *)origin_circuit_new(); + client_side = TO_CIRCUIT(origin_circuit_new()); client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; monotime_enable_test_mocking(); @@ -955,7 +960,7 @@ test_circuitpadding_token_removal_exact(void *arg) circpad_circuit_machineinfo_new(client_side, 0); /* move the machine to the right state */ - circpad_cell_event_nonpadding_received((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); tt_int_op(client_side->padding_info[0]->current_state, OP_EQ, CIRCPAD_STATE_BURST); @@ -969,16 +974,16 @@ test_circuitpadding_token_removal_exact(void *arg) /* Ensure that we will clear out bin #4 with this usec */ mi->padding_scheduled_at_usec = current_time - 57; tt_int_op(mi->histogram[4], OP_EQ, 2); - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); mi->padding_scheduled_at_usec = current_time - 57; tt_int_op(mi->histogram[4], OP_EQ, 1); - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); tt_int_op(mi->histogram[4], OP_EQ, 0); /* Ensure that we will not remove any other tokens even tho we try to, since * this is what the exact strategy dictates */ mi->padding_scheduled_at_usec = current_time - 57; - circpad_machine_remove_token(mi); + circpad_cell_event_nonpadding_sent(client_side); for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) { if (i != 4) { tt_int_op(mi->histogram[i], OP_EQ, 2); @@ -1044,8 +1049,8 @@ test_circuitpadding_tokens(void *arg) mi = client_side->padding_info[0]; // Pretend a non-padding cell was sent - circpad_cell_event_nonpadding_received((circuit_t*)client_side); - circpad_cell_event_nonpadding_sent((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); + circpad_cell_event_nonpadding_sent(client_side); /* We have to save the infinity bin because one inf delay * could have been chosen when we transition to burst */ circpad_hist_token_t inf_bin = mi->histogram[4]; @@ -1154,11 +1159,11 @@ test_circuitpadding_tokens(void *arg) /* Drain the infinity bin and cause a refill */ while (inf_bin != 0) { tt_int_op(mi->histogram[4], OP_EQ, inf_bin); - circpad_cell_event_nonpadding_received((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); inf_bin--; } - circpad_cell_event_nonpadding_sent((circuit_t*)client_side); + circpad_cell_event_nonpadding_sent(client_side); // We should have refilled here. tt_int_op(mi->histogram[4], OP_EQ, 2); @@ -1282,10 +1287,10 @@ test_circuitpadding_wronghop(void *arg) * padding that gets sent by scheduled timers. */ MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock); - client_side = (circuit_t *)origin_circuit_new(); + client_side = TO_CIRCUIT(origin_circuit_new()); dummy_channel.cmux = circuitmux_alloc(); - relay_side = (circuit_t *)new_fake_orcirc(&dummy_channel, - &dummy_channel); + relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, + &dummy_channel)); orig_client = TO_ORIGIN_CIRCUIT(client_side); relay_side->purpose = CIRCUIT_PURPOSE_OR; @@ -1403,9 +1408,9 @@ test_circuitpadding_wronghop(void *arg) free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); free_fake_orcirc(relay_side); - client_side = (circuit_t *)origin_circuit_new(); - relay_side = (circuit_t *)new_fake_orcirc(&dummy_channel, - &dummy_channel); + client_side = TO_CIRCUIT(origin_circuit_new()); + relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, + &dummy_channel)); relay_side->purpose = CIRCUIT_PURPOSE_OR; client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; @@ -1599,10 +1604,10 @@ simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay, tor_addr_t addr; // Pretend a non-padding cell was sent - circpad_cell_event_nonpadding_sent((circuit_t*)client); + circpad_cell_event_nonpadding_sent(client); // Receive extend cell at middle - circpad_cell_event_nonpadding_received((circuit_t*)mid_relay); + circpad_cell_event_nonpadding_received(mid_relay); // Advance time a tiny bit so we can calculate an RTT curr_mocked_time += 10 * TOR_NSEC_PER_MSEC; @@ -1610,14 +1615,14 @@ simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay, monotime_set_mock_time_nsec(curr_mocked_time); // Receive extended cell at middle - circpad_cell_event_nonpadding_sent((circuit_t*)mid_relay); + circpad_cell_event_nonpadding_sent(mid_relay); // Receive extended cell at first hop - circpad_cell_event_nonpadding_received((circuit_t*)client); + circpad_cell_event_nonpadding_received(client); // Add a hop to cpath crypt_path_t *hop = tor_malloc_zero(sizeof(crypt_path_t)); - onion_append_to_cpath(&TO_ORIGIN_CIRCUIT(client)->cpath, hop); + cpath_extend_linked_list(&TO_ORIGIN_CIRCUIT(client)->cpath, hop); hop->magic = CRYPT_PATH_MAGIC; hop->state = CPATH_STATE_OPEN; @@ -1631,7 +1636,7 @@ simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay, digest, NULL, NULL, NULL, &addr, padding); - circuit_init_cpath_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0); + cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0); hop->package_window = circuit_initial_package_window(); hop->deliver_window = CIRCWINDOW_START; @@ -1641,6 +1646,55 @@ simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay, } static circpad_machine_spec_t * +helper_create_length_machine(void) +{ + circpad_machine_spec_t *ret = + tor_malloc_zero(sizeof(circpad_machine_spec_t)); + + /* Start, burst */ + circpad_machine_states_init(ret, 2); + + ret->states[CIRCPAD_STATE_START]. + next_state[CIRCPAD_EVENT_PADDING_SENT] = CIRCPAD_STATE_BURST; + + ret->states[CIRCPAD_STATE_BURST]. + next_state[CIRCPAD_EVENT_PADDING_SENT] = CIRCPAD_STATE_BURST; + + ret->states[CIRCPAD_STATE_BURST]. + next_state[CIRCPAD_EVENT_LENGTH_COUNT] = CIRCPAD_STATE_END; + + ret->states[CIRCPAD_STATE_BURST]. + next_state[CIRCPAD_EVENT_BINS_EMPTY] = CIRCPAD_STATE_END; + + /* No token removal.. end via state_length only */ + ret->states[CIRCPAD_STATE_BURST].token_removal = + CIRCPAD_TOKEN_REMOVAL_NONE; + + /* Let's have this one end after 12 packets */ + ret->states[CIRCPAD_STATE_BURST].length_dist.type = CIRCPAD_DIST_UNIFORM; + ret->states[CIRCPAD_STATE_BURST].length_dist.param1 = 12; + ret->states[CIRCPAD_STATE_BURST].length_dist.param2 = 13; + ret->states[CIRCPAD_STATE_BURST].max_length = 12; + + ret->states[CIRCPAD_STATE_BURST].histogram_len = 4; + + ret->states[CIRCPAD_STATE_BURST].histogram_edges[0] = 0; + ret->states[CIRCPAD_STATE_BURST].histogram_edges[1] = 1; + ret->states[CIRCPAD_STATE_BURST].histogram_edges[2] = 1000000; + ret->states[CIRCPAD_STATE_BURST].histogram_edges[3] = 10000000; + + ret->states[CIRCPAD_STATE_BURST].histogram[0] = 0; + ret->states[CIRCPAD_STATE_BURST].histogram[1] = 0; + ret->states[CIRCPAD_STATE_BURST].histogram[2] = 6; + + ret->states[CIRCPAD_STATE_BURST].histogram_total_tokens = 6; + ret->states[CIRCPAD_STATE_BURST].use_rtt_estimate = 0; + ret->states[CIRCPAD_STATE_BURST].length_includes_nonpadding = 0; + + return ret; +} + +static circpad_machine_spec_t * helper_create_conditional_machine(void) { circpad_machine_spec_t *ret = @@ -1683,8 +1737,11 @@ static void helper_create_conditional_machines(void) { circpad_machine_spec_t *add = helper_create_conditional_machine(); - origin_padding_machines = smartlist_new(); - relay_padding_machines = smartlist_new(); + + if (!origin_padding_machines) + origin_padding_machines = smartlist_new(); + if (!relay_padding_machines) + relay_padding_machines = smartlist_new(); add->machine_num = 2; add->is_origin_side = 1; @@ -1733,6 +1790,135 @@ helper_create_conditional_machines(void) } void +test_circuitpadding_state_length(void *arg) +{ + /** + * Test plan: + * * Explicitly test that with no token removal enabled, we hit + * the state length limit due to either padding, or non-padding. + * * Repeat test with an arbitrary token removal strategy, and + * verify that if we run out of tokens due to padding before we + * hit the state length, we still go to state end (all our + * token removal tests only test nonpadding token removal). + */ + int64_t actual_mocked_monotime_start; + (void)arg; + MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock); + MOCK(circpad_send_command_to_hop, circpad_send_command_to_hop_mock); + + nodes_init(); + dummy_channel.cmux = circuitmux_alloc(); + relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, + &dummy_channel)); + client_side = TO_CIRCUIT(origin_circuit_new()); + relay_side->purpose = CIRCUIT_PURPOSE_OR; + client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; + + monotime_init(); + monotime_enable_test_mocking(); + actual_mocked_monotime_start = MONOTIME_MOCK_START; + monotime_set_mock_time_nsec(actual_mocked_monotime_start); + monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start); + curr_mocked_time = actual_mocked_monotime_start; + + /* This is needed so that we are not considered to be dormant */ + note_user_activity(20); + + timers_initialize(); + circpad_machine_spec_t *client_machine = + helper_create_length_machine(); + + MOCK(circuit_package_relay_cell, + circuit_package_relay_cell_mock); + MOCK(node_get_by_id, + node_get_by_id_mock); + + client_side->padding_machine[0] = client_machine; + client_side->padding_info[0] = + circpad_circuit_machineinfo_new(client_side, 0); + circpad_machine_runtime_t *mi = client_side->padding_info[0]; + + circpad_cell_event_padding_sent(client_side); + tt_int_op(mi->state_length, OP_EQ, 12); + tt_ptr_op(mi->histogram, OP_EQ, NULL); + + /* Verify that non-padding does not change our state length */ + circpad_cell_event_nonpadding_sent(client_side); + tt_int_op(mi->state_length, OP_EQ, 12); + + /* verify that sending padding changes our state length */ + for (uint64_t i = mi->state_length-1; i > 0; i--) { + circpad_send_padding_cell_for_callback(mi); + tt_int_op(mi->state_length, OP_EQ, i); + } + circpad_send_padding_cell_for_callback(mi); + + tt_int_op(mi->state_length, OP_EQ, -1); + tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END); + + /* Restart machine */ + mi->current_state = CIRCPAD_STATE_START; + + /* Now, count nonpadding as part of the state length */ + client_machine->states[CIRCPAD_STATE_BURST].length_includes_nonpadding = 1; + + circpad_cell_event_padding_sent(client_side); + tt_int_op(mi->state_length, OP_EQ, 12); + + /* Verify that non-padding does change our state length now */ + for (uint64_t i = mi->state_length-1; i > 0; i--) { + circpad_cell_event_nonpadding_sent(client_side); + tt_int_op(mi->state_length, OP_EQ, i); + } + + circpad_cell_event_nonpadding_sent(client_side); + tt_int_op(mi->state_length, OP_EQ, -1); + tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END); + + /* Now, just test token removal when we send padding */ + client_machine->states[CIRCPAD_STATE_BURST].token_removal = + CIRCPAD_TOKEN_REMOVAL_EXACT; + + /* Restart machine */ + mi->current_state = CIRCPAD_STATE_START; + circpad_cell_event_padding_sent(client_side); + tt_int_op(mi->state_length, OP_EQ, 12); + tt_ptr_op(mi->histogram, OP_NE, NULL); + tt_int_op(mi->chosen_bin, OP_EQ, 2); + + /* verify that sending padding changes our state length and + * our histogram now */ + for (uint32_t i = mi->histogram[2]-1; i > 0; i--) { + circpad_send_padding_cell_for_callback(mi); + tt_int_op(mi->chosen_bin, OP_EQ, 2); + tt_int_op(mi->histogram[2], OP_EQ, i); + } + + tt_int_op(mi->state_length, OP_EQ, 7); + tt_int_op(mi->histogram[2], OP_EQ, 1); + + circpad_send_padding_cell_for_callback(mi); + tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END); + + done: + tor_free(client_machine->states); + tor_free(client_machine); + + free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); + free_fake_orcirc(relay_side); + + circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); + circuitmux_free(dummy_channel.cmux); + timers_shutdown(); + monotime_disable_test_mocking(); + UNMOCK(circuit_package_relay_cell); + UNMOCK(circuitmux_attach_circuit); + UNMOCK(node_get_by_id); + + return; +} + +void test_circuitpadding_conditions(void *arg) { /** @@ -1756,9 +1942,9 @@ test_circuitpadding_conditions(void *arg) nodes_init(); dummy_channel.cmux = circuitmux_alloc(); - relay_side = (circuit_t *)new_fake_orcirc(&dummy_channel, - &dummy_channel); - client_side = (circuit_t *)origin_circuit_new(); + relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, + &dummy_channel)); + client_side = TO_CIRCUIT(origin_circuit_new()); relay_side->purpose = CIRCUIT_PURPOSE_OR; client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; @@ -2212,7 +2398,7 @@ test_circuitpadding_sample_distribution(void *arg) } /* send a non-padding cell to move to the next machine state */ - circpad_cell_event_nonpadding_received((circuit_t*)client_side); + circpad_cell_event_nonpadding_received(client_side); } done: @@ -2324,12 +2510,12 @@ test_circuitpadding_global_rate_limiting(void *arg) curr_mocked_time = actual_mocked_monotime_start; timers_initialize(); - client_side = (circuit_t *)origin_circuit_new(); + client_side = TO_CIRCUIT(origin_circuit_new()); client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; dummy_channel.cmux = circuitmux_alloc(); /* Setup machine and circuits */ - relay_side = (circuit_t *)new_fake_orcirc(&dummy_channel, &dummy_channel); + relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel)); relay_side->purpose = CIRCUIT_PURPOSE_OR; helper_create_basic_machine(); relay_side->padding_machine[0] = &circ_client_machine; @@ -2396,11 +2582,347 @@ test_circuitpadding_global_rate_limiting(void *arg) smartlist_free(vote1.net_params); } +/* Test reduced and disabled padding */ +static void +test_circuitpadding_reduce_disable(void *arg) +{ + (void) arg; + int64_t actual_mocked_monotime_start; + + MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock); + + nodes_init(); + dummy_channel.cmux = circuitmux_alloc(); + relay_side = (circuit_t *)new_fake_orcirc(&dummy_channel, + &dummy_channel); + client_side = (circuit_t *)origin_circuit_new(); + relay_side->purpose = CIRCUIT_PURPOSE_OR; + client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; + + circpad_machines_init(); + helper_create_conditional_machines(); + + monotime_init(); + monotime_enable_test_mocking(); + actual_mocked_monotime_start = MONOTIME_MOCK_START; + monotime_set_mock_time_nsec(actual_mocked_monotime_start); + monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start); + curr_mocked_time = actual_mocked_monotime_start; + timers_initialize(); + + /* This is needed so that we are not considered to be dormant */ + note_user_activity(20); + + MOCK(circuit_package_relay_cell, + circuit_package_relay_cell_mock); + MOCK(node_get_by_id, + node_get_by_id_mock); + + /* Simulate extend. This should result in the original machine getting + * added, since the circuit is not built */ + simulate_single_hop_extend(client_side, relay_side, 1); + simulate_single_hop_extend(client_side, relay_side, 1); + + /* Verify that machine #2 is added */ + tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2); + tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2); + + /* Deliver a padding cell to the client, to trigger burst state */ + circpad_cell_event_padding_sent(client_side); + + /* This should have trigger length shutdown condition on client.. */ + tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL); + tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL); + + /* Verify machine is gone from both sides */ + tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL); + tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL); + + /* Now test the reduced padding machine by setting up the consensus */ + networkstatus_t vote1; + vote1.net_params = smartlist_new(); + smartlist_split_string(vote1.net_params, + "circpad_padding_reduced=1", NULL, 0, 0); + + /* Register reduced padding machine with the padding subsystem */ + circpad_new_consensus_params(&vote1); + + simulate_single_hop_extend(client_side, relay_side, 1); + + /* Verify that machine #0 is added */ + tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 0); + tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 0); + + tt_int_op( + circpad_machine_reached_padding_limit(client_side->padding_info[0]), + OP_EQ, 0); + tt_int_op( + circpad_machine_reached_padding_limit(relay_side->padding_info[0]), + OP_EQ, 0); + + /* Test that machines get torn down when padding is disabled */ + SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp)); + smartlist_free(vote1.net_params); + vote1.net_params = smartlist_new(); + smartlist_split_string(vote1.net_params, + "circpad_padding_disabled=1", NULL, 0, 0); + + /* Register reduced padding machine with the padding subsystem */ + circpad_new_consensus_params(&vote1); + + tt_int_op( + circpad_machine_schedule_padding(client_side->padding_info[0]), + OP_EQ, CIRCPAD_STATE_UNCHANGED); + tt_int_op( + circpad_machine_schedule_padding(relay_side->padding_info[0]), + OP_EQ, CIRCPAD_STATE_UNCHANGED); + + /* Signal that circuit is built: this event causes us to re-evaluate + * machine conditions (which don't apply because padding is disabled). */ + circpad_machine_event_circ_built(TO_ORIGIN_CIRCUIT(client_side)); + + tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL); + tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL); + tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL); + tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL); + + SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp)); + smartlist_free(vote1.net_params); + vote1.net_params = NULL; + circpad_new_consensus_params(&vote1); + + get_options_mutable()->ReducedCircuitPadding = 1; + + simulate_single_hop_extend(client_side, relay_side, 1); + + /* Verify that machine #0 is added */ + tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 0); + tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 0); + + tt_int_op( + circpad_machine_reached_padding_limit(client_side->padding_info[0]), + OP_EQ, 0); + tt_int_op( + circpad_machine_reached_padding_limit(relay_side->padding_info[0]), + OP_EQ, 0); + + get_options_mutable()->CircuitPadding = 0; + + tt_int_op( + circpad_machine_schedule_padding(client_side->padding_info[0]), + OP_EQ, CIRCPAD_STATE_UNCHANGED); + tt_int_op( + circpad_machine_schedule_padding(relay_side->padding_info[0]), + OP_EQ, CIRCPAD_STATE_UNCHANGED); + + /* Signal that circuit is built: this event causes us to re-evaluate + * machine conditions (which don't apply because padding is disabled). */ + + circpad_machine_event_circ_built(TO_ORIGIN_CIRCUIT(client_side)); + + tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL); + tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL); + tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL); + tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL); + + done: + free_fake_orcirc(relay_side); + circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); + circuitmux_free(dummy_channel.cmux); +} + +/** Just a basic machine whose whole purpose is to reach the END state */ +static void +helper_create_ender_machine(void) +{ + /* Start, burst */ + circpad_machine_states_init(&circ_client_machine, 2); + + circ_client_machine.states[CIRCPAD_STATE_START]. + next_state[CIRCPAD_EVENT_NONPADDING_RECV] = CIRCPAD_STATE_END; + + circ_client_machine.conditions.state_mask = CIRCPAD_STATE_ALL; + circ_client_machine.conditions.purpose_mask = CIRCPAD_PURPOSE_ALL; +} + +static time_t mocked_timeofday; +/** Set timeval to a mock date and time. This is necessary + * to make tor_gettimeofday() mockable. */ +static void +mock_tor_gettimeofday(struct timeval *timeval) +{ + timeval->tv_sec = mocked_timeofday; + timeval->tv_usec = 0; +} + +/** Test manual managing of circuit lifetimes by the circuitpadding + * subsystem. In particular this test goes through all the cases of the + * circpad_marked_circuit_for_padding() function, via + * circuit_mark_for_close() as well as + * circuit_expire_old_circuits_clientside(). */ +static void +test_circuitpadding_manage_circuit_lifetime(void *arg) +{ + circpad_machine_runtime_t *mi; + + (void) arg; + + client_side = (circuit_t *)origin_circuit_new(); + client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; + monotime_enable_test_mocking(); + MOCK(tor_gettimeofday, mock_tor_gettimeofday); + mocked_timeofday = 23; + + helper_create_ender_machine(); + + /* Enable manual circuit lifetime manage for this test */ + circ_client_machine.manage_circ_lifetime = 1; + + /* Test setup */ + client_side->padding_machine[0] = &circ_client_machine; + client_side->padding_info[0] = + circpad_circuit_machineinfo_new(client_side, 0); + mi = client_side->padding_info[0]; + + tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_START); + + /* Check that the circuit is not marked for close */ + tt_int_op(client_side->marked_for_close, OP_EQ, 0); + tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_GENERAL); + + /* Mark this circuit for close due to a remote reason */ + circuit_mark_for_close(client_side, + END_CIRC_REASON_FLAG_REMOTE|END_CIRC_REASON_NONE); + tt_ptr_op(client_side->padding_info[0], OP_NE, NULL); + tt_int_op(client_side->marked_for_close, OP_NE, 0); + tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_GENERAL); + client_side->marked_for_close = 0; + + /* Mark this circuit for close due to a protocol issue */ + circuit_mark_for_close(client_side, END_CIRC_REASON_TORPROTOCOL); + tt_int_op(client_side->marked_for_close, OP_NE, 0); + tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_GENERAL); + client_side->marked_for_close = 0; + + /* Mark a measurement circuit for close */ + client_side->purpose = CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT; + circuit_mark_for_close(client_side, END_CIRC_REASON_NONE); + tt_int_op(client_side->marked_for_close, OP_NE, 0); + tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT); + client_side->marked_for_close = 0; + + /* Mark a general circuit for close */ + client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; + circuit_mark_for_close(client_side, END_CIRC_REASON_NONE); + + /* Check that this circuit is still not marked for close since we are + * managing the lifetime manually, but the circuit was tagged as such by the + * circpadding subsystem */ + tt_int_op(client_side->marked_for_close, OP_EQ, 0); + tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_CIRCUIT_PADDING); + + /* We just tested case (1) from the comments of + * circpad_circuit_should_be_marked_for_close() */ + + /* Transition the machine to the END state but did not delete its machine */ + tt_ptr_op(client_side->padding_info[0], OP_NE, NULL); + circpad_cell_event_nonpadding_received(client_side); + tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END); + + /* We just tested case (3) from the comments of + * circpad_circuit_should_be_marked_for_close(). + * Now let's go for case (2). */ + + /* Reset the close mark */ + client_side->marked_for_close = 0; + + /* Mark this circuit for close */ + circuit_mark_for_close(client_side, 0); + + /* See that the circ got closed since we are already in END state */ + tt_int_op(client_side->marked_for_close, OP_NE, 0); + + /* We just tested case (2). Now let's see that case (4) is unreachable as + that comment claims */ + + /* First, reset all close marks and tags */ + client_side->marked_for_close = 0; + client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL; + + /* Now re-create the ender machine so that we can transition to END again */ + /* Free up some stuff first */ + circpad_circuit_free_all_machineinfos(client_side); + tor_free(circ_client_machine.states); + helper_create_ender_machine(); + + client_side->padding_machine[0] = &circ_client_machine; + client_side->padding_info[0] = + circpad_circuit_machineinfo_new(client_side, 0); + mi = client_side->padding_info[0]; + + /* Check we are in START. */ + tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_START); + + /* Test that we don't expire this circuit yet */ + client_side->timestamp_dirty = 0; + client_side->state = CIRCUIT_STATE_OPEN; + tor_gettimeofday(&client_side->timestamp_began); + TO_ORIGIN_CIRCUIT(client_side)->circuit_idle_timeout = 23; + mocked_timeofday += 24; + circuit_expire_old_circuits_clientside(); + circuit_expire_old_circuits_clientside(); + circuit_expire_old_circuits_clientside(); + tt_int_op(client_side->timestamp_dirty, OP_NE, 0); + tt_int_op(client_side->marked_for_close, OP_EQ, 0); + tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_CIRCUIT_PADDING); + + /* Runaway circpad test: if the machine does not transition to end, + * test that after CIRCPAD_DELAY_MAX_SECS, we get marked anyway */ + mocked_timeofday = client_side->timestamp_dirty + + get_options()->MaxCircuitDirtiness + 2; + client_side->padding_info[0]->last_cell_time_sec = + approx_time()-(CIRCPAD_DELAY_MAX_SECS+10); + circuit_expire_old_circuits_clientside(); + tt_int_op(client_side->marked_for_close, OP_NE, 0); + + /* Test back to normal: if we had activity, we won't close */ + client_side->padding_info[0]->last_cell_time_sec = approx_time(); + client_side->marked_for_close = 0; + circuit_expire_old_circuits_clientside(); + tt_int_op(client_side->marked_for_close, OP_EQ, 0); + + /* Transition to END, but before we're past the dirty timer */ + mocked_timeofday = client_side->timestamp_dirty; + circpad_cell_event_nonpadding_received(client_side); + tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END); + + /* Verify that the circuit was not closed. */ + tt_int_op(client_side->marked_for_close, OP_EQ, 0); + + /* Now that we are in END state, we can be closed by expiry, but via + * the timestamp_dirty path, not the idle path. So first test not dirty + * enough. */ + mocked_timeofday = client_side->timestamp_dirty; + circuit_expire_old_circuits_clientside(); + tt_int_op(client_side->marked_for_close, OP_EQ, 0); + mocked_timeofday = client_side->timestamp_dirty + + get_options()->MaxCircuitDirtiness + 2; + circuit_expire_old_circuits_clientside(); + tt_int_op(client_side->marked_for_close, OP_NE, 0); + + done: + free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); + tor_free(circ_client_machine.states); + monotime_disable_test_mocking(); + UNMOCK(tor_gettimeofday); +} + #define TEST_CIRCUITPADDING(name, flags) \ { #name, test_##name, (flags), NULL, NULL } struct testcase_t circuitpadding_tests[] = { TEST_CIRCUITPADDING(circuitpadding_tokens, TT_FORK), + TEST_CIRCUITPADDING(circuitpadding_state_length, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_negotiation, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_wronghop, TT_FORK), /** Disabled unstable test until #29298 is implemented (see #29122) */ @@ -2410,10 +2932,12 @@ struct testcase_t circuitpadding_tests[] = { TEST_CIRCUITPADDING(circuitpadding_sample_distribution, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_machine_rate_limiting, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_global_rate_limiting, TT_FORK), + TEST_CIRCUITPADDING(circuitpadding_reduce_disable, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_token_removal_lower, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_token_removal_higher, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_closest_token_removal, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_closest_token_removal_usec, TT_FORK), TEST_CIRCUITPADDING(circuitpadding_token_removal_exact, TT_FORK), + TEST_CIRCUITPADDING(circuitpadding_manage_circuit_lifetime, TT_FORK), END_OF_TESTCASES }; diff --git a/src/test/test_circuitstats.c b/src/test/test_circuitstats.c index 1cbcb14f2b..2a09622f09 100644 --- a/src/test/test_circuitstats.c +++ b/src/test/test_circuitstats.c @@ -28,7 +28,7 @@ origin_circuit_t *subtest_fourhop_circuit(struct timeval, int); origin_circuit_t *add_opened_threehop(void); origin_circuit_t *build_unopened_fourhop(struct timeval); -int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice); +int cpath_append_hop(crypt_path_t **head_ptr, extend_info_t *choice); static int marked_for_close; /* Mock function because we are not trying to test the close circuit that does @@ -57,9 +57,9 @@ add_opened_threehop(void) or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); or_circ->build_state->desired_path_len = DEFAULT_ROUTE_LEN; - onion_append_hop(&or_circ->cpath, &fakehop); - onion_append_hop(&or_circ->cpath, &fakehop); - onion_append_hop(&or_circ->cpath, &fakehop); + cpath_append_hop(&or_circ->cpath, &fakehop); + cpath_append_hop(&or_circ->cpath, &fakehop); + cpath_append_hop(&or_circ->cpath, &fakehop); or_circ->has_opened = 1; TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN; @@ -82,10 +82,10 @@ build_unopened_fourhop(struct timeval circ_start_time) or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); or_circ->build_state->desired_path_len = 4; - onion_append_hop(&or_circ->cpath, fakehop); - onion_append_hop(&or_circ->cpath, fakehop); - onion_append_hop(&or_circ->cpath, fakehop); - onion_append_hop(&or_circ->cpath, fakehop); + cpath_append_hop(&or_circ->cpath, fakehop); + cpath_append_hop(&or_circ->cpath, fakehop); + cpath_append_hop(&or_circ->cpath, fakehop); + cpath_append_hop(&or_circ->cpath, fakehop); tor_free(fakehop); diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 08dfb6bcdd..872da3d2c5 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -389,7 +389,7 @@ test_crypto_aes128(void *arg) "\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff"); crypto_cipher_crypt_inplace(env1, data2, 64); - tt_assert(tor_mem_is_zero(data2, 64)); + tt_assert(fast_mem_is_zero(data2, 64)); done: tor_free(mem_op_hex_tmp); @@ -2134,7 +2134,7 @@ test_crypto_curve25519_persist(void *arg) tt_u64_op((uint64_t)st.st_size, OP_EQ, 32+CURVE25519_PUBKEY_LEN+CURVE25519_SECKEY_LEN); tt_assert(fast_memeq(content, "== c25519v1: testing ==", taglen)); - tt_assert(tor_mem_is_zero(content+taglen, 32-taglen)); + tt_assert(fast_mem_is_zero(content+taglen, 32-taglen)); cp = content + 32; tt_mem_op(keypair.seckey.secret_key,OP_EQ, cp, diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c index e24aee8930..3b20dfa587 100644 --- a/src/test/test_crypto_slow.c +++ b/src/test/test_crypto_slow.c @@ -109,7 +109,7 @@ run_s2k_tests(const unsigned flags, const unsigned type, secret_to_key_derivekey(buf3, sizeof(buf3), buf, speclen, pw1, strlen(pw1))); tt_mem_op(buf2, OP_EQ, buf3, sizeof(buf3)); - tt_assert(!tor_mem_is_zero((char*)buf2+keylen, sizeof(buf2)-keylen)); + tt_assert(!fast_mem_is_zero((char*)buf2+keylen, sizeof(buf2)-keylen)); done: ; diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c index cfdd11d161..38aca90266 100644 --- a/src/test/test_extorport.c +++ b/src/test/test_extorport.c @@ -177,7 +177,7 @@ test_ext_or_init_auth(void *arg) /* Shouldn't be initialized already, or our tests will be a bit * meaningless */ ext_or_auth_cookie = tor_malloc_zero(32); - tt_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32)); + tt_assert(fast_mem_is_zero((char*)ext_or_auth_cookie, 32)); /* Now make sure we use a temporary file */ fn = get_fname("ext_cookie_file"); @@ -202,7 +202,7 @@ test_ext_or_init_auth(void *arg) tt_mem_op(cp,OP_EQ, "! Extended ORPort Auth Cookie !\x0a", 32); tt_mem_op(cp+32,OP_EQ, ext_or_auth_cookie, 32); memcpy(cookie0, ext_or_auth_cookie, 32); - tt_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32)); + tt_assert(!fast_mem_is_zero((char*)ext_or_auth_cookie, 32)); /* Operation should be idempotent. */ tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1)); diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 5d3327c777..2b69aae547 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -448,7 +448,7 @@ test_hs_rend_data(void *arg) tt_int_op(client_v2->auth_type, OP_EQ, REND_BASIC_AUTH); tt_int_op(strlen(client_v2->onion_address), OP_EQ, 0); tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id)); - tt_int_op(tor_mem_is_zero(client_v2->descriptor_cookie, + tt_int_op(fast_mem_is_zero(client_v2->descriptor_cookie, sizeof(client_v2->descriptor_cookie)), OP_EQ, 1); tt_assert(client->hsdirs_fp); tt_int_op(smartlist_len(client->hsdirs_fp), OP_EQ, 0); diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c index 2187c2be39..d71f8b6b18 100644 --- a/src/test/test_hs_cache.c +++ b/src/test/test_hs_cache.c @@ -486,7 +486,7 @@ test_client_cache(void *arg) NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); memcpy(wanted_subcredential, published_desc->subcredential, DIGEST256_LEN); - tt_assert(!tor_mem_is_zero((char*)wanted_subcredential, DIGEST256_LEN)); + tt_assert(!fast_mem_is_zero((char*)wanted_subcredential, DIGEST256_LEN)); } /* Test handle_response_fetch_hsdesc_v3() */ diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c index 8362b6cbda..0d25a98bb3 100644 --- a/src/test/test_hs_client.c +++ b/src/test/test_hs_client.c @@ -14,6 +14,7 @@ #define CIRCUITBUILD_PRIVATE #define CIRCUITLIST_PRIVATE #define CONNECTION_PRIVATE +#define CRYPT_PATH_PRIVATE #include "test/test.h" #include "test/test_helpers.h" @@ -44,6 +45,7 @@ #include "core/or/cpath_build_state_st.h" #include "core/or/crypt_path_st.h" +#include "core/or/crypt_path.h" #include "feature/dircommon/dir_connection_st.h" #include "core/or/entry_connection_st.h" #include "core/or/extend_info_st.h" @@ -241,12 +243,14 @@ test_e2e_rend_circuit_setup_legacy(void *arg) tt_int_op(retval, OP_EQ, 1); /* Check the digest algo */ - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest), + tt_int_op( + crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest), OP_EQ, DIGEST_SHA1); - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest), + tt_int_op( + crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest), OP_EQ, DIGEST_SHA1); - tt_assert(or_circ->cpath->crypto.f_crypto); - tt_assert(or_circ->cpath->crypto.b_crypto); + tt_assert(or_circ->cpath->pvt_crypto.f_crypto); + tt_assert(or_circ->cpath->pvt_crypto.b_crypto); /* Ensure that circ purpose was changed */ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED); @@ -311,12 +315,14 @@ test_e2e_rend_circuit_setup(void *arg) tt_int_op(retval, OP_EQ, 1); /* Check that the crypt path has prop224 algorithm parameters */ - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest), + tt_int_op( + crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest), OP_EQ, DIGEST_SHA3_256); - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest), + tt_int_op( + crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest), OP_EQ, DIGEST_SHA3_256); - tt_assert(or_circ->cpath->crypto.f_crypto); - tt_assert(or_circ->cpath->crypto.b_crypto); + tt_assert(or_circ->cpath->pvt_crypto.f_crypto); + tt_assert(or_circ->cpath->pvt_crypto.b_crypto); /* Ensure that circ purpose was changed */ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED); @@ -395,7 +401,7 @@ test_client_pick_intro(void *arg) tt_assert(fetched_desc); tt_mem_op(fetched_desc->subcredential, OP_EQ, desc->subcredential, DIGEST256_LEN); - tt_assert(!tor_mem_is_zero((char*)fetched_desc->subcredential, + tt_assert(!fast_mem_is_zero((char*)fetched_desc->subcredential, DIGEST256_LEN)); tor_free(encoded); } @@ -433,7 +439,7 @@ test_client_pick_intro(void *arg) for (int i = 0; i < 64; ++i) { extend_info_t *ip = client_get_random_intro(&service_kp.pubkey); tor_assert(ip); - tt_assert(!tor_mem_is_zero((char*)ip->identity_digest, DIGEST_LEN)); + tt_assert(!fast_mem_is_zero((char*)ip->identity_digest, DIGEST_LEN)); tt_mem_op(ip->identity_digest, OP_EQ, chosen_intro_ei->identity_digest, DIGEST_LEN); extend_info_free(ip); @@ -479,6 +485,17 @@ test_client_pick_intro(void *arg) SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points, hs_desc_intro_point_t *, ip) { extend_info_t *intro_ei = desc_intro_point_to_extend_info(ip); + /* desc_intro_point_to_extend_info() doesn't return IPv6 intro points + * yet, because we can't extend to them. See #24404, #24451, and #24181. + */ + if (intro_ei == NULL) { + /* Pretend we're making a direct connection, and that we can use IPv6 + */ + get_options_mutable()->ClientUseIPv6 = 1; + intro_ei = hs_get_extend_info_from_lspecs(ip->link_specifiers, + &ip->onion_key, 1); + tt_assert(tor_addr_family(&intro_ei->addr) == AF_INET6); + } tt_assert(intro_ei); if (intro_ei) { const char *ptr; diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c index 5a3fd46dbe..6fe5573c0f 100644 --- a/src/test/test_hs_descriptor.c +++ b/src/test/test_hs_descriptor.c @@ -126,7 +126,7 @@ test_descriptor_padding(void *arg) tt_assert(padded_plaintext); tor_free(plaintext); /* Make sure our padding has been zeroed. */ - tt_int_op(tor_mem_is_zero((char *) padded_plaintext + plaintext_len, + tt_int_op(fast_mem_is_zero((char *) padded_plaintext + plaintext_len, padded_len - plaintext_len), OP_EQ, 1); tor_free(padded_plaintext); /* Never never have a padded length smaller than the plaintext. */ @@ -143,7 +143,7 @@ test_descriptor_padding(void *arg) tt_assert(padded_plaintext); tor_free(plaintext); /* Make sure our padding has been zeroed. */ - tt_int_op(tor_mem_is_zero((char *) padded_plaintext + plaintext_len, + tt_int_op(fast_mem_is_zero((char *) padded_plaintext + plaintext_len, padded_len - plaintext_len), OP_EQ, 1); tor_free(padded_plaintext); /* Never never have a padded length smaller than the plaintext. */ @@ -160,7 +160,7 @@ test_descriptor_padding(void *arg) tt_assert(padded_plaintext); tor_free(plaintext); /* Make sure our padding has been zeroed. */ - tt_int_op(tor_mem_is_zero((char *) padded_plaintext + plaintext_len, + tt_int_op(fast_mem_is_zero((char *) padded_plaintext + plaintext_len, padded_len - plaintext_len), OP_EQ, 1); tor_free(padded_plaintext); /* Never never have a padded length smaller than the plaintext. */ diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c index 57132e6197..c4a8583696 100644 --- a/src/test/test_hs_service.c +++ b/src/test/test_hs_service.c @@ -21,6 +21,7 @@ #define STATEFILE_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define HS_CLIENT_PRIVATE +#define CRYPT_PATH_PRIVATE #include "test/test.h" #include "test/test_helpers.h" @@ -60,6 +61,7 @@ #include "core/or/cpath_build_state_st.h" #include "core/or/crypt_path_st.h" +#include "core/or/crypt_path.h" #include "feature/nodelist/networkstatus_st.h" #include "feature/nodelist/node_st.h" #include "core/or/origin_circuit_st.h" @@ -193,12 +195,14 @@ test_e2e_rend_circuit_setup(void *arg) tt_int_op(retval, OP_EQ, 1); /* Check the digest algo */ - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.f_digest), + tt_int_op( + crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest), OP_EQ, DIGEST_SHA3_256); - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->crypto.b_digest), + tt_int_op( + crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest), OP_EQ, DIGEST_SHA3_256); - tt_assert(or_circ->cpath->crypto.f_crypto); - tt_assert(or_circ->cpath->crypto.b_crypto); + tt_assert(or_circ->cpath->pvt_crypto.f_crypto); + tt_assert(or_circ->cpath->pvt_crypto.b_crypto); /* Ensure that circ purpose was changed */ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED); @@ -393,11 +397,11 @@ test_load_keys(void *arg) tt_assert(s); /* Ok we have the service object. Validate few things. */ - tt_assert(!tor_mem_is_zero(s->onion_address, sizeof(s->onion_address))); + tt_assert(!fast_mem_is_zero(s->onion_address, sizeof(s->onion_address))); tt_int_op(hs_address_is_valid(s->onion_address), OP_EQ, 1); - tt_assert(!tor_mem_is_zero((char *) s->keys.identity_sk.seckey, + tt_assert(!fast_mem_is_zero((char *) s->keys.identity_sk.seckey, ED25519_SECKEY_LEN)); - tt_assert(!tor_mem_is_zero((char *) s->keys.identity_pk.pubkey, + tt_assert(!fast_mem_is_zero((char *) s->keys.identity_pk.pubkey, ED25519_PUBKEY_LEN)); /* Check onion address from identity key. */ hs_build_address(&s->keys.identity_pk, s->config.version, addr); @@ -677,7 +681,7 @@ test_service_intro_point(void *arg) ip = helper_create_service_ip(); tt_assert(ip); /* Make sure the authentication keypair is not zeroes. */ - tt_int_op(tor_mem_is_zero((const char *) &ip->auth_key_kp, + tt_int_op(fast_mem_is_zero((const char *) &ip->auth_key_kp, sizeof(ed25519_keypair_t)), OP_EQ, 0); /* The introduce2_max MUST be in that range. */ tt_u64_op(ip->introduce2_max, OP_GE, @@ -1562,9 +1566,9 @@ test_build_update_descriptors(void *arg) tt_int_op(smartlist_len(ip_cur->base.link_specifiers), OP_EQ, 3); /* Make sure we have a valid encryption keypair generated when we pick an * intro point in the update process. */ - tt_assert(!tor_mem_is_zero((char *) ip_cur->enc_key_kp.seckey.secret_key, + tt_assert(!fast_mem_is_zero((char *) ip_cur->enc_key_kp.seckey.secret_key, CURVE25519_SECKEY_LEN)); - tt_assert(!tor_mem_is_zero((char *) ip_cur->enc_key_kp.pubkey.public_key, + tt_assert(!fast_mem_is_zero((char *) ip_cur->enc_key_kp.pubkey.public_key, CURVE25519_PUBKEY_LEN)); tt_u64_op(ip_cur->time_to_expire, OP_GE, now + INTRO_POINT_LIFETIME_MIN_SECONDS); @@ -1884,9 +1888,9 @@ test_rendezvous1_parsing(void *arg) } /* Send out the RENDEZVOUS1 and make sure that our mock func worked */ - tt_assert(tor_mem_is_zero(rend1_payload, 32)); + tt_assert(fast_mem_is_zero(rend1_payload, 32)); hs_circ_service_rp_has_opened(service, service_circ); - tt_assert(!tor_mem_is_zero(rend1_payload, 32)); + tt_assert(!fast_mem_is_zero(rend1_payload, 32)); tt_int_op(rend1_payload_len, OP_EQ, HS_LEGACY_RENDEZVOUS_CELL_SIZE); /******************************/ diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c index 34f59f26cd..4e4c86aa0a 100644 --- a/src/test/test_link_handshake.c +++ b/src/test/test_link_handshake.c @@ -263,7 +263,7 @@ test_link_handshake_certs_ok(void *arg) tt_assert(c1->handshake_state->authenticated_rsa); tt_assert(! c1->handshake_state->authenticated_ed25519); } - tt_assert(! tor_mem_is_zero( + tt_assert(! fast_mem_is_zero( (char*)c1->handshake_state->authenticated_rsa_peer_id, 20)); chan2 = tor_malloc_zero(sizeof(*chan2)); @@ -290,7 +290,7 @@ test_link_handshake_certs_ok(void *arg) tt_ptr_op(c2->handshake_state->certs->ed_id_sign, OP_EQ, NULL); } tt_assert(c2->handshake_state->certs->id_cert); - tt_assert(tor_mem_is_zero( + tt_assert(fast_mem_is_zero( (char*)c2->handshake_state->authenticated_rsa_peer_id, 20)); /* no authentication has happened yet, since we haen't gotten an AUTH cell. */ diff --git a/src/test/test_options.c b/src/test/test_options.c index f12e6b6763..396be6b18d 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -430,6 +430,7 @@ get_options_test_data(const char *conf) // Being kinda lame and just fixing the immedate breakage for now.. result->opt->ConnectionPadding = -1; // default must be "auto" result->opt->DormantClientTimeout = 1800; // must be over 600. + result->opt->CircuitPadding = 1; // default must be "1" rv = config_get_lines(conf, &cl, 1); tt_int_op(rv, OP_EQ, 0); diff --git a/src/test/test_policy.c b/src/test/test_policy.c index 46d4a1b94a..e58bb3d174 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -6,13 +6,18 @@ #include "core/or/or.h" #include "app/config/config.h" +#include "core/or/circuitbuild.h" #include "core/or/policies.h" #include "feature/dirparse/policy_parse.h" +#include "feature/hs/hs_common.h" +#include "feature/hs/hs_descriptor.h" #include "feature/relay/router.h" #include "lib/encoding/confline.h" #include "test/test.h" +#include "test/log_test_helpers.h" #include "core/or/addr_policy_st.h" +#include "core/or/extend_info_st.h" #include "core/or/port_cfg_st.h" #include "feature/nodelist/node_st.h" #include "feature/nodelist/routerinfo_st.h" @@ -2024,6 +2029,101 @@ test_policies_fascist_firewall_allows_address(void *arg) expect_ap); \ STMT_END +/* Check that fascist_firewall_choose_address_ls() returns the expected + * results. */ +#define CHECK_CHOSEN_ADDR_NULL_LS() \ + STMT_BEGIN \ + tor_addr_port_t chosen_ls_ap; \ + tor_addr_make_null(&chosen_ls_ap.addr, AF_UNSPEC); \ + chosen_ls_ap.port = 0; \ + setup_full_capture_of_logs(LOG_WARN); \ + fascist_firewall_choose_address_ls(NULL, 1, &chosen_ls_ap); \ + expect_single_log_msg("Unknown or missing link specifiers"); \ + teardown_capture_of_logs(); \ + STMT_END + +#define CHECK_CHOSEN_ADDR_LS(fake_ls, pref_only, expect_rv, expect_ap) \ + STMT_BEGIN \ + tor_addr_port_t chosen_ls_ap; \ + tor_addr_make_null(&chosen_ls_ap.addr, AF_UNSPEC); \ + chosen_ls_ap.port = 0; \ + setup_full_capture_of_logs(LOG_WARN); \ + fascist_firewall_choose_address_ls(fake_ls, pref_only, &chosen_ls_ap); \ + if (smartlist_len(fake_ls) == 0) { \ + expect_single_log_msg("Link specifiers are empty"); \ + } else { \ + expect_no_log_entry(); \ + tt_assert(tor_addr_eq(&(expect_ap).addr, &chosen_ls_ap.addr)); \ + tt_int_op((expect_ap).port, OP_EQ, chosen_ls_ap.port); \ + } \ + teardown_capture_of_logs(); \ + STMT_END + +#define CHECK_LS_LEGACY_ONLY(fake_ls) \ + STMT_BEGIN \ + tor_addr_port_t chosen_ls_ap; \ + tor_addr_make_null(&chosen_ls_ap.addr, AF_UNSPEC); \ + chosen_ls_ap.port = 0; \ + setup_full_capture_of_logs(LOG_WARN); \ + fascist_firewall_choose_address_ls(fake_ls, 0, &chosen_ls_ap); \ + expect_single_log_msg("None of our link specifiers have IPv4 or IPv6"); \ + teardown_capture_of_logs(); \ + STMT_END + +#define CHECK_HS_EXTEND_INFO_ADDR_LS(fake_ls, direct_conn, expect_ap) \ + STMT_BEGIN \ + curve25519_secret_key_t seckey; \ + curve25519_secret_key_generate(&seckey, 0); \ + curve25519_public_key_t pubkey; \ + curve25519_public_key_generate(&pubkey, &seckey); \ + setup_full_capture_of_logs(LOG_WARN); \ + extend_info_t *ei = hs_get_extend_info_from_lspecs(fake_ls, &pubkey, \ + direct_conn); \ + if (fake_ls == NULL) { \ + tt_ptr_op(ei, OP_EQ, NULL); \ + expect_single_log_msg("Specified link specifiers is null"); \ + } else { \ + expect_no_log_entry(); \ + tt_assert(tor_addr_eq(&(expect_ap).addr, &ei->addr)); \ + tt_int_op((expect_ap).port, OP_EQ, ei->port); \ + extend_info_free(ei); \ + } \ + teardown_capture_of_logs(); \ + STMT_END + +#define CHECK_HS_EXTEND_INFO_ADDR_LS_NULL_KEY(fake_ls) \ + STMT_BEGIN \ + setup_full_capture_of_logs(LOG_WARN); \ + extend_info_t *ei = hs_get_extend_info_from_lspecs(fake_ls, NULL, 0); \ + tt_ptr_op(ei, OP_EQ, NULL); \ + expect_single_log_msg("Specified onion key is null"); \ + teardown_capture_of_logs(); \ + STMT_END + +#define CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_NULL(fake_ls, direct_conn) \ + STMT_BEGIN \ + curve25519_secret_key_t seckey; \ + curve25519_secret_key_generate(&seckey, 0); \ + curve25519_public_key_t pubkey; \ + curve25519_public_key_generate(&pubkey, &seckey); \ + extend_info_t *ei = hs_get_extend_info_from_lspecs(fake_ls, &pubkey, \ + direct_conn); \ + tt_ptr_op(ei, OP_EQ, NULL); \ + STMT_END + +#define CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_MSG(fake_ls, msg_level, msg) \ + STMT_BEGIN \ + curve25519_secret_key_t seckey; \ + curve25519_secret_key_generate(&seckey, 0); \ + curve25519_public_key_t pubkey; \ + curve25519_public_key_generate(&pubkey, &seckey); \ + setup_full_capture_of_logs(msg_level); \ + extend_info_t *ei = hs_get_extend_info_from_lspecs(fake_ls, &pubkey, 0); \ + tt_ptr_op(ei, OP_EQ, NULL); \ + expect_single_log_msg(msg); \ + teardown_capture_of_logs(); \ + STMT_END + /** Mock the preferred address function to return zero (prefer IPv4). */ static int mock_fascist_firewall_rand_prefer_ipv6_addr_use_ipv4(void) @@ -2472,6 +2572,141 @@ test_policies_fascist_firewall_choose_address(void *arg) UNMOCK(fascist_firewall_rand_prefer_ipv6_addr); + /* Test firewall_choose_address_ls(). To do this, we make a fake link + * specifier. */ + smartlist_t *lspecs = smartlist_new(), + *lspecs_blank = smartlist_new(), + *lspecs_v4 = smartlist_new(), + *lspecs_v6 = smartlist_new(), + *lspecs_no_legacy = smartlist_new(), + *lspecs_legacy_only = smartlist_new(); + link_specifier_t *fake_ls; + + /* IPv4 link specifier */ + fake_ls = link_specifier_new(); + link_specifier_set_ls_type(fake_ls, LS_IPV4); + link_specifier_set_un_ipv4_addr(fake_ls, + tor_addr_to_ipv4h(&ipv4_or_ap.addr)); + link_specifier_set_un_ipv4_port(fake_ls, ipv4_or_ap.port); + link_specifier_set_ls_len(fake_ls, sizeof(ipv4_or_ap.addr.addr.in_addr) + + sizeof(ipv4_or_ap.port)); + smartlist_add(lspecs, fake_ls); + smartlist_add(lspecs_v4, fake_ls); + smartlist_add(lspecs_no_legacy, fake_ls); + + /* IPv6 link specifier */ + fake_ls = link_specifier_new(); + link_specifier_set_ls_type(fake_ls, LS_IPV6); + size_t addr_len = link_specifier_getlen_un_ipv6_addr(fake_ls); + const uint8_t *in6_addr = tor_addr_to_in6_addr8(&ipv6_or_ap.addr); + uint8_t *ipv6_array = link_specifier_getarray_un_ipv6_addr(fake_ls); + memcpy(ipv6_array, in6_addr, addr_len); + link_specifier_set_un_ipv6_port(fake_ls, ipv6_or_ap.port); + link_specifier_set_ls_len(fake_ls, addr_len + sizeof(ipv6_or_ap.port)); + smartlist_add(lspecs, fake_ls); + smartlist_add(lspecs_v6, fake_ls); + + /* Legacy ID link specifier */ + fake_ls = link_specifier_new(); + link_specifier_set_ls_type(fake_ls, LS_LEGACY_ID); + uint8_t *legacy_id = link_specifier_getarray_un_legacy_id(fake_ls); + memset(legacy_id, 'A', sizeof(*legacy_id)); + link_specifier_set_ls_len(fake_ls, + link_specifier_getlen_un_legacy_id(fake_ls)); + smartlist_add(lspecs, fake_ls); + smartlist_add(lspecs_legacy_only, fake_ls); + smartlist_add(lspecs_v4, fake_ls); + smartlist_add(lspecs_v6, fake_ls); + + /* Check with bogus requests. */ + tor_addr_port_t null_ap; \ + tor_addr_make_null(&null_ap.addr, AF_UNSPEC); \ + null_ap.port = 0; \ + + /* Check for a null link state. */ + CHECK_CHOSEN_ADDR_NULL_LS(); + CHECK_HS_EXTEND_INFO_ADDR_LS(NULL, 1, null_ap); + + /* Check for a blank link state. */ + CHECK_CHOSEN_ADDR_LS(lspecs_blank, 0, 0, null_ap); + CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_NULL(lspecs_blank, 0); + + /* Check for a link state with only a Legacy ID. */ + CHECK_LS_LEGACY_ONLY(lspecs_legacy_only); + CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_NULL(lspecs_legacy_only, 0); + smartlist_free(lspecs_legacy_only); + + /* Check with a null onion_key. */ + CHECK_HS_EXTEND_INFO_ADDR_LS_NULL_KEY(lspecs_blank); + smartlist_free(lspecs_blank); + + /* Check with a null onion_key. */ + CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_MSG(lspecs_no_legacy, LOG_WARN, + "Missing Legacy ID in link state"); + smartlist_free(lspecs_no_legacy); + + /* Enable both IPv4 and IPv6. */ + memset(&mock_options, 0, sizeof(or_options_t)); + mock_options.ClientUseIPv4 = 1; + mock_options.ClientUseIPv6 = 1; + + /* Prefer IPv4, enable both IPv4 and IPv6. */ + mock_options.ClientPreferIPv6ORPort = 0; + + CHECK_CHOSEN_ADDR_LS(lspecs, 0, 1, ipv4_or_ap); + CHECK_CHOSEN_ADDR_LS(lspecs, 1, 1, ipv4_or_ap); + + CHECK_HS_EXTEND_INFO_ADDR_LS(lspecs, 1, ipv4_or_ap); + CHECK_HS_EXTEND_INFO_ADDR_LS(lspecs, 0, ipv4_or_ap); + + /* Prefer IPv6, enable both IPv4 and IPv6. */ + mock_options.ClientPreferIPv6ORPort = 1; + + CHECK_CHOSEN_ADDR_LS(lspecs, 0, 1, ipv6_or_ap); + CHECK_CHOSEN_ADDR_LS(lspecs, 1, 1, ipv6_or_ap); + + CHECK_HS_EXTEND_INFO_ADDR_LS(lspecs, 1, ipv6_or_ap); + CHECK_HS_EXTEND_INFO_ADDR_LS(lspecs, 0, ipv4_or_ap); + + /* IPv4-only. */ + memset(&mock_options, 0, sizeof(or_options_t)); + mock_options.ClientUseIPv4 = 1; + mock_options.ClientUseIPv6 = 0; + + CHECK_CHOSEN_ADDR_LS(lspecs, 0, 1, ipv4_or_ap); + CHECK_CHOSEN_ADDR_LS(lspecs, 1, 1, ipv4_or_ap); + + CHECK_CHOSEN_ADDR_LS(lspecs_v6, 0, 0, null_ap); + + CHECK_HS_EXTEND_INFO_ADDR_LS(lspecs, 1, ipv4_or_ap); + CHECK_HS_EXTEND_INFO_ADDR_LS(lspecs, 0, ipv4_or_ap); + + CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_NULL(lspecs_v6, 0); + CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_NULL(lspecs_v6, 1); + + /* IPv6-only. */ + memset(&mock_options, 0, sizeof(or_options_t)); + mock_options.ClientUseIPv4 = 0; + mock_options.ClientUseIPv6 = 1; + + CHECK_CHOSEN_ADDR_LS(lspecs, 0, 1, ipv6_or_ap); + CHECK_CHOSEN_ADDR_LS(lspecs, 1, 1, ipv6_or_ap); + + CHECK_CHOSEN_ADDR_LS(lspecs_v4, 0, 0, null_ap); + + CHECK_HS_EXTEND_INFO_ADDR_LS(lspecs, 1, ipv6_or_ap); + CHECK_HS_EXTEND_INFO_ADDR_LS(lspecs, 0, ipv4_or_ap); + + CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_NULL(lspecs_v4, 1); + CHECK_HS_EXTEND_INFO_ADDR_LS_EXPECT_NULL(lspecs_v6, 0); + + smartlist_free(lspecs_v4); + smartlist_free(lspecs_v6); + + SMARTLIST_FOREACH(lspecs, link_specifier_t *, lspec, \ + link_specifier_free(lspec)); \ + smartlist_free(lspecs); + done: UNMOCK(get_options); } diff --git a/src/test/test_relaycrypt.c b/src/test/test_relaycrypt.c index fe6889e521..4bbf07c3ec 100644 --- a/src/test/test_relaycrypt.c +++ b/src/test/test_relaycrypt.c @@ -3,6 +3,8 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#define CRYPT_PATH_PRIVATE + #include "core/or/or.h" #include "core/or/circuitbuild.h" #define CIRCUITLIST_PRIVATE @@ -10,7 +12,7 @@ #include "lib/crypt_ops/crypto_rand.h" #include "core/or/relay.h" #include "core/crypto/relay_crypto.h" - +#include "core/or/crypt_path.h" #include "core/or/cell_st.h" #include "core/or/or_circuit_st.h" #include "core/or/origin_circuit_st.h" @@ -49,10 +51,10 @@ testing_circuitset_setup(const struct testcase_t *testcase) cs->origin_circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL; for (i=0; i<3; ++i) { crypt_path_t *hop = tor_malloc_zero(sizeof(*hop)); - relay_crypto_init(&hop->crypto, KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]), - 0, 0); + relay_crypto_init(&hop->pvt_crypto, KEY_MATERIAL[i], + sizeof(KEY_MATERIAL[i]), 0, 0); hop->state = CPATH_STATE_OPEN; - onion_append_to_cpath(&cs->origin_circ->cpath, hop); + cpath_extend_linked_list(&cs->origin_circ->cpath, hop); tt_ptr_op(hop, OP_EQ, cs->origin_circ->cpath->prev); } diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c index 102d9334a1..0c6b533698 100644 --- a/src/test/test_routerkeys.c +++ b/src/test/test_routerkeys.c @@ -399,7 +399,7 @@ test_routerkeys_ed_key_init_split(void *arg) tt_assert(kp2 != NULL); tt_assert(cert == NULL); tt_mem_op(&kp1->pubkey, OP_EQ, &kp2->pubkey, sizeof(kp2->pubkey)); - tt_assert(tor_mem_is_zero((char*)kp2->seckey.seckey, + tt_assert(fast_mem_is_zero((char*)kp2->seckey.seckey, sizeof(kp2->seckey.seckey))); ed25519_keypair_free(kp2); kp2 = NULL; @@ -409,7 +409,7 @@ test_routerkeys_ed_key_init_split(void *arg) tt_assert(kp2 != NULL); tt_assert(cert == NULL); tt_mem_op(&kp1->pubkey, OP_EQ, &kp2->pubkey, sizeof(kp2->pubkey)); - tt_assert(tor_mem_is_zero((char*)kp2->seckey.seckey, + tt_assert(fast_mem_is_zero((char*)kp2->seckey.seckey, sizeof(kp2->seckey.seckey))); ed25519_keypair_free(kp2); kp2 = NULL; diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c index 480799383b..9fb88b9bee 100644 --- a/src/test/test_shared_random.c +++ b/src/test/test_shared_random.c @@ -449,12 +449,12 @@ test_sr_commit(void *arg) /* We should have a reveal value. */ tt_assert(commit_has_reveal_value(our_commit)); /* We should have a random value. */ - tt_assert(!tor_mem_is_zero((char *) our_commit->random_number, + tt_assert(!fast_mem_is_zero((char *) our_commit->random_number, sizeof(our_commit->random_number))); /* Commit and reveal timestamp should be the same. */ tt_u64_op(our_commit->commit_ts, OP_EQ, our_commit->reveal_ts); /* We should have a hashed reveal. */ - tt_assert(!tor_mem_is_zero(our_commit->hashed_reveal, + tt_assert(!fast_mem_is_zero(our_commit->hashed_reveal, sizeof(our_commit->hashed_reveal))); /* Do we have a valid encoded commit and reveal. Note the following only * tests if the generated values are correct. Their could be a bug in diff --git a/src/test/test_util.c b/src/test/test_util.c index 88eda847a2..79df2825be 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -2087,14 +2087,14 @@ test_util_strmisc(void *arg) /* Test mem_is_zero */ memset(buf,0,128); buf[128] = 'x'; - tt_assert(tor_mem_is_zero(buf, 10)); - tt_assert(tor_mem_is_zero(buf, 20)); - tt_assert(tor_mem_is_zero(buf, 128)); - tt_assert(!tor_mem_is_zero(buf, 129)); + tt_assert(fast_mem_is_zero(buf, 10)); + tt_assert(fast_mem_is_zero(buf, 20)); + tt_assert(fast_mem_is_zero(buf, 128)); + tt_assert(!fast_mem_is_zero(buf, 129)); buf[60] = (char)255; - tt_assert(!tor_mem_is_zero(buf, 128)); + tt_assert(!fast_mem_is_zero(buf, 128)); buf[0] = (char)1; - tt_assert(!tor_mem_is_zero(buf, 10)); + tt_assert(!fast_mem_is_zero(buf, 10)); /* Test 'escaped' */ tt_ptr_op(escaped(NULL), OP_EQ, NULL); @@ -3789,7 +3789,7 @@ test_util_memarea(void *arg) tt_int_op(((uintptr_t)p3) % sizeof(void*),OP_EQ, 0); tt_assert(!memarea_owns_ptr(area, p3+8192)); tt_assert(!memarea_owns_ptr(area, p3+30)); - tt_assert(tor_mem_is_zero(p2, 52)); + tt_assert(fast_mem_is_zero(p2, 52)); /* Make sure we don't overalign. */ p1 = memarea_alloc(area, 1); p2 = memarea_alloc(area, 1); diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c index c8945a707c..2859da66b2 100644 --- a/src/test/test_util_format.c +++ b/src/test/test_util_format.c @@ -367,7 +367,7 @@ test_util_format_base32_decode(void *arg) ret = base32_decode(dst, real_dstlen, "#abcde", 6); tt_int_op(ret, OP_EQ, -1); /* Make sure the destination buffer has been zeroed even on error. */ - tt_int_op(tor_mem_is_zero(dst, real_dstlen), OP_EQ, 1); + tt_int_op(fast_mem_is_zero(dst, real_dstlen), OP_EQ, 1); } done: |