diff options
author | Mike Perry <mikeperry-git@torproject.org> | 2017-06-23 16:53:39 -0400 |
---|---|---|
committer | Mike Perry <mikeperry-git@torproject.org> | 2017-06-23 16:53:39 -0400 |
commit | 79e2e4d3cbabff41675aa1f7defb67f4acba398c (patch) | |
tree | 9c1eba60e3b72c7deef375dc37020fe3f22db9a3 /src | |
parent | 784b29a2bfc7b7ce5ef355629528a38c50b81908 (diff) | |
download | tor-79e2e4d3cbabff41675aa1f7defb67f4acba398c.tar.gz tor-79e2e4d3cbabff41675aa1f7defb67f4acba398c.zip |
Ticket #17857: Padding off-switch for single hop connections
This doesn't apply to currently active connections.. yet...
Diffstat (limited to 'src')
-rw-r--r-- | src/or/channel.c | 7 | ||||
-rw-r--r-- | src/or/channelpadding.c | 16 | ||||
-rw-r--r-- | src/test/test_channelpadding.c | 164 |
3 files changed, 166 insertions, 21 deletions
diff --git a/src/or/channel.c b/src/or/channel.c index df6d7d3423..8348ffd649 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -65,6 +65,7 @@ #include "routerlist.h" #include "scheduler.h" #include "compat_time.h" +#include "networkstatus.h" /* Global lists of channels */ @@ -2711,7 +2712,11 @@ channel_do_open_actions(channel_t *chan) /* Disable or reduce padding according to user prefs. */ if (chan->padding_enabled || get_options()->ConnectionPadding == 1) { - if (!get_options()->ConnectionPadding) { + if (!get_options()->ConnectionPadding || + (get_options()->Tor2webMode && + !networkstatus_get_param(NULL, "nf_pad_tor2web", 1, 0, 1)) + || (get_options()->HiddenServiceSingleHopMode && + !networkstatus_get_param(NULL, "nf_pad_single_onion", 1, 0, 1))) { channelpadding_disable_padding_on_channel(chan); } diff --git a/src/or/channelpadding.c b/src/or/channelpadding.c index f5248e8960..9a2fdc4bbe 100644 --- a/src/or/channelpadding.c +++ b/src/or/channelpadding.c @@ -46,6 +46,10 @@ static int consensus_nf_conntimeout_clients; static int consensus_nf_pad_before_usage; /** Should we pad relay-to-relay connections? */ static int consensus_nf_pad_relays; +/** Should we pad tor2web connections? */ +static int consensus_nf_pad_tor2web; +/** Should we pad rosos connections? */ +static int consensus_nf_pad_single_onion; #define TOR_MSEC_PER_SEC 1000 #define TOR_USEC_PER_MSEC 1000 @@ -130,6 +134,12 @@ channelpadding_new_consensus_params(networkstatus_t *ns) consensus_nf_pad_relays = networkstatus_get_param(ns, "nf_pad_relays", 0, 0, 1); + + consensus_nf_pad_tor2web = + networkstatus_get_param(ns, "nf_pad_tor2web", 1, 0, 1); + + consensus_nf_pad_single_onion = + networkstatus_get_param(ns, "nf_pad_single_onion", 1, 0, 1); } /** @@ -707,6 +717,12 @@ channelpadding_decide_to_pad_channel(channel_t *chan) return CHANNELPADDING_WONTPAD; } + if (options->Tor2webMode && !consensus_nf_pad_tor2web) + return CHANNELPADDING_WONTPAD; + + if (options->HiddenServiceSingleHopMode && !consensus_nf_pad_single_onion) + return CHANNELPADDING_WONTPAD; + if (!chan->has_queued_writes(chan)) { int is_client_channel = 0; diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c index 0a70184f86..99f8880a40 100644 --- a/src/test/test_channelpadding.c +++ b/src/test/test_channelpadding.c @@ -26,6 +26,7 @@ void test_channelpadding_timers(void *arg); void test_channelpadding_consensus(void *arg); void test_channelpadding_negotiation(void *arg); void test_channelpadding_decide_to_pad_channel(void *arg); +void test_channelpadding_killonehop(void *arg); void dummy_nop_timer(void); @@ -111,8 +112,6 @@ setup_fake_connection_for_channel(channel_tls_t *chan) conn->base_.conn_array_index = smartlist_len(connection_array); smartlist_add(connection_array, conn); - connection_or_set_canonical(conn, 1); - conn->chan = chan; chan->conn = conn; @@ -127,6 +126,8 @@ setup_fake_connection_for_channel(channel_tls_t *chan) conn->tls = (tor_tls_t *)((void *)(&fake_tortls)); conn->link_proto = MIN_LINK_PROTO_FOR_CHANNEL_PADDING; + + connection_or_set_canonical(conn, 1); } static channel_tls_t * @@ -166,16 +167,30 @@ free_fake_channeltls(channel_tls_t *chan) } static void -setup_mock_network(void) +setup_mock_consensus(void) { - routerstatus_t *relay; - connection_array = smartlist_new(); - current_md_consensus = current_ns_consensus = tor_malloc_zero(sizeof(networkstatus_t)); current_md_consensus->net_params = smartlist_new(); current_md_consensus->routerstatus_list = smartlist_new(); channelpadding_new_consensus_params(current_md_consensus); +} + +static void +free_mock_consensus(void) +{ + SMARTLIST_FOREACH(current_md_consensus->routerstatus_list, void *, r, + tor_free(r)); + smartlist_free(current_md_consensus->routerstatus_list); + smartlist_free(current_ns_consensus->net_params); + tor_free(current_ns_consensus); +} + +static void +setup_mock_network(void) +{ + routerstatus_t *relay; + connection_array = smartlist_new(); relay1_relay2 = (channel_t*)new_fake_channeltls(2); relay1_relay2->write_cell = mock_channel_write_cell_relay1; @@ -202,6 +217,11 @@ setup_mock_network(void) client_relay3 = (channel_t*)new_fake_channeltls(3); client_relay3->write_cell = mock_channel_write_cell_client; channel_timestamp_active(client_relay3); + + channel_do_open_actions(relay1_relay2); + channel_do_open_actions(relay2_relay1); + channel_do_open_actions(relay3_client); + channel_do_open_actions(client_relay3); } static void @@ -212,12 +232,7 @@ free_mock_network(void) free_fake_channeltls((channel_tls_t*)relay3_client); free_fake_channeltls((channel_tls_t*)client_relay3); - SMARTLIST_FOREACH(current_md_consensus->routerstatus_list, void *, r, - tor_free(r)); - smartlist_free(current_md_consensus->routerstatus_list); - smartlist_free(current_ns_consensus->net_params); smartlist_free(connection_array); - tor_free(current_ns_consensus); } static void @@ -345,6 +360,118 @@ test_channelpadding_timers(void *arg) } void +test_channelpadding_killonehop(void *arg) +{ + channelpadding_decision_t decision; + (void)arg; + tor_libevent_postfork(); + + routerstatus_t *relay = tor_malloc_zero(sizeof(routerstatus_t)); + monotime_init(); + timers_initialize(); + + setup_mock_consensus(); + + /* Do we disable padding if tor2webmode or rsos are enabled, and + * the consensus says don't pad? */ + + /* Ensure we can kill tor2web and rsos padding if we want. */ + // First, test that padding works if either is enabled + smartlist_clear(current_md_consensus->net_params); + channelpadding_new_consensus_params(current_md_consensus); + + setup_mock_network(); + tried_to_write_cell = 0; + get_options_mutable()->Tor2webMode = 1; + client_relay3->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); + tt_assert(client_relay3->pending_padding_callback); + tt_int_op(tried_to_write_cell, OP_EQ, 0); + + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED); + + // Wait for the timer + event_base_loop(tor_libevent_get_base(), 0); + tt_int_op(tried_to_write_cell, OP_EQ, 1); + tt_assert(!client_relay3->pending_padding_callback); + + // Then test disabling each via consensus param + smartlist_add(current_md_consensus->net_params, + (void*)"nf_pad_tor2web=0"); + channelpadding_new_consensus_params(current_md_consensus); + + // Test client side (it should stop immediately) + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD); + tt_assert(!client_relay3->pending_padding_callback); + + // Reset connnections.. XXX: remove this requirement via client + // negotiation + free_mock_network(); + setup_mock_network(); + + // Test relay side (it should have gotten the negotiation to disable) + get_options_mutable()->Tor2webMode = 0; + tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ, + CHANNELPADDING_WONTPAD); + tt_assert(!relay3_client->padding_enabled); + + /* Repeat for SOS */ + // First, test that padding works if either is enabled + smartlist_clear(current_md_consensus->net_params); + channelpadding_new_consensus_params(current_md_consensus); + + // Reset connections + free_mock_network(); + setup_mock_network(); + tried_to_write_cell = 0; + get_options_mutable()->HiddenServiceSingleHopMode = 1; + client_relay3->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); + tt_assert(client_relay3->pending_padding_callback); + tt_int_op(tried_to_write_cell, OP_EQ, 0); + + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED); + + // Wait for the timer + event_base_loop(tor_libevent_get_base(), 0); + tt_int_op(tried_to_write_cell, OP_EQ, 1); + tt_assert(!client_relay3->pending_padding_callback); + + // Then test disabling each via consensus param + smartlist_add(current_md_consensus->net_params, + (void*)"nf_pad_single_onion=0"); + channelpadding_new_consensus_params(current_md_consensus); + + // Test client side (it should stop immediately) + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD); + tt_assert(!client_relay3->pending_padding_callback); + + // Reset connnections.. XXX: remove this requirement... + free_mock_network(); + setup_mock_network(); + + // Test relay side (it should have gotten the negotiation to disable) + get_options_mutable()->HiddenServiceSingleHopMode = 0; + tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ, + CHANNELPADDING_WONTPAD); + tt_assert(!relay3_client->padding_enabled); + + done: + free_mock_consensus(); + free_mock_network(); + tor_free(relay); + + timers_shutdown(); + channel_free_all(); +} + +void test_channelpadding_consensus(void *arg) { channelpadding_decision_t decision; @@ -379,11 +506,7 @@ test_channelpadding_consensus(void *arg) chan = (channel_t*)new_fake_channeltls(0); channel_timestamp_active(chan); - current_md_consensus = current_ns_consensus - = tor_malloc_zero(sizeof(networkstatus_t)); - current_md_consensus->net_params = smartlist_new(); - current_md_consensus->routerstatus_list = smartlist_new(); - channelpadding_new_consensus_params(current_md_consensus); + setup_mock_consensus(); get_options_mutable()->ORPort_set = 1; @@ -441,6 +564,7 @@ test_channelpadding_consensus(void *arg) channelpadding_new_consensus_params(current_md_consensus); tried_to_write_cell = 0; + chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; decision = channelpadding_decide_to_pad_channel(chan); tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); tt_assert(chan->pending_padding_callback); @@ -547,12 +671,9 @@ test_channelpadding_consensus(void *arg) tt_i64_op(val, OP_LE, 24*60*60*2); done: + free_mock_consensus(); free_fake_channeltls((channel_tls_t*)chan); smartlist_free(connection_array); - smartlist_free(current_md_consensus->routerstatus_list); - smartlist_free(current_ns_consensus->net_params); - tor_free(relay); - tor_free(current_ns_consensus); timers_shutdown(); channel_free_all(); @@ -579,6 +700,7 @@ test_channelpadding_negotiation(void *arg) */ monotime_init(); timers_initialize(); + setup_mock_consensus(); setup_mock_network(); /* Test case #1: Do the right things ignore negotiation? */ @@ -680,6 +802,7 @@ test_channelpadding_negotiation(void *arg) done: free_mock_network(); + free_mock_consensus(); timers_shutdown(); channel_free_all(); @@ -894,6 +1017,7 @@ struct testcase_t channelpadding_tests[] = { TEST_CHANNELPADDING(channelpadding_decide_to_pad_channel, TT_FORK), TEST_CHANNELPADDING(channelpadding_negotiation, TT_FORK), TEST_CHANNELPADDING(channelpadding_consensus, TT_FORK), + TEST_CHANNELPADDING(channelpadding_killonehop, TT_FORK), TEST_CHANNELPADDING(channelpadding_timers, TT_FORK), END_OF_TESTCASES }; |