diff options
Diffstat (limited to 'src/test')
69 files changed, 2502 insertions, 284 deletions
diff --git a/src/test/fuzz/fuzz_consensus.c b/src/test/fuzz/fuzz_consensus.c index 5a04683a11..1a4195b418 100644 --- a/src/test/fuzz/fuzz_consensus.c +++ b/src/test/fuzz/fuzz_consensus.c @@ -1,8 +1,10 @@ /* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE +#define SIGCOMMON_PRIVATE #include "core/or/or.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/ns_parse.h" +#include "feature/dirparse/sigcommon.h" +#include "feature/dirparse/unparseable.h" #include "feature/nodelist/networkstatus.h" #include "lib/crypt_ops/crypto_ed25519.h" #include "feature/nodelist/networkstatus_st.h" diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c index 5a56f4081a..3420113717 100644 --- a/src/test/fuzz/fuzz_descriptor.c +++ b/src/test/fuzz/fuzz_descriptor.c @@ -1,10 +1,13 @@ /* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE +#define SIGCOMMON_PRIVATE #include "core/or/or.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/routerparse.h" +#include "feature/dirparse/sigcommon.h" +#include "feature/dirparse/unparseable.h" #include "feature/nodelist/routerlist.h" -#include "feature/relay/routerkeys.h" +#include "feature/nodelist/torcert.h" +#include "feature/keymgt/loadkey.h" #include "test/fuzz/fuzzing.h" static int @@ -76,4 +79,3 @@ fuzz_main(const uint8_t *data, size_t sz) } return 0; } - diff --git a/src/test/fuzz/fuzz_extrainfo.c b/src/test/fuzz/fuzz_extrainfo.c index 6c88f80122..da0fe80838 100644 --- a/src/test/fuzz/fuzz_extrainfo.c +++ b/src/test/fuzz/fuzz_extrainfo.c @@ -1,8 +1,10 @@ /* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE +#define SIGCOMMON_PRIVATE #include "core/or/or.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/routerparse.h" +#include "feature/dirparse/sigcommon.h" +#include "feature/dirparse/unparseable.h" #include "feature/nodelist/routerlist.h" #include "feature/relay/routerkeys.h" #include "test/fuzz/fuzzing.h" diff --git a/src/test/fuzz/fuzz_hsdescv2.c b/src/test/fuzz/fuzz_hsdescv2.c index fd5da41635..667b58b3aa 100644 --- a/src/test/fuzz/fuzz_hsdescv2.c +++ b/src/test/fuzz/fuzz_hsdescv2.c @@ -1,9 +1,9 @@ /* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE #include "core/or/or.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/unparseable.h" #include "feature/rend/rendcommon.h" +#include "feature/rend/rendparse.h" #include "lib/crypt_ops/crypto_ed25519.h" #include "test/fuzz/fuzzing.h" diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c index b332973b39..d5ddcc2e27 100644 --- a/src/test/fuzz/fuzz_hsdescv3.c +++ b/src/test/fuzz/fuzz_hsdescv3.c @@ -1,14 +1,13 @@ /* Copyright (c) 2017-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE #define HS_DESCRIPTOR_PRIVATE #include "core/or/or.h" #include "trunnel/ed25519_cert.h" /* Trunnel interface. */ #include "lib/crypt_ops/crypto_ed25519.h" #include "feature/hs/hs_descriptor.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/unparseable.h" #include "test/fuzz/fuzzing.h" diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c index 2fbb275614..06483282bc 100644 --- a/src/test/fuzz/fuzz_http.c +++ b/src/test/fuzz/fuzz_http.c @@ -4,14 +4,14 @@ #include "orconfig.h" #define BUFFERS_PRIVATE -#define DIRECTORY_PRIVATE +#define DIRCACHE_PRIVATE #include "core/or/or.h" #include "lib/err/backtrace.h" #include "lib/container/buffers.h" #include "app/config/config.h" #include "core/mainloop/connection.h" -#include "feature/dircache/directory.h" +#include "feature/dircache/dircache.h" #include "lib/log/log.h" #include "feature/dircommon/dir_connection_st.h" @@ -132,4 +132,3 @@ fuzz_main(const uint8_t *stdin_buf, size_t data_size) return 0; } - diff --git a/src/test/fuzz/fuzz_iptsv2.c b/src/test/fuzz/fuzz_iptsv2.c index a3082f4d0e..265677eebe 100644 --- a/src/test/fuzz/fuzz_iptsv2.c +++ b/src/test/fuzz/fuzz_iptsv2.c @@ -1,9 +1,10 @@ /* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE + #include "core/or/or.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/unparseable.h" #include "feature/rend/rendcommon.h" +#include "feature/rend/rendparse.h" #include "lib/crypt_ops/crypto_ed25519.h" #include "feature/rend/rend_service_descriptor_st.h" diff --git a/src/test/fuzz/fuzz_microdesc.c b/src/test/fuzz/fuzz_microdesc.c index fa9676372d..ab54cf2a34 100644 --- a/src/test/fuzz/fuzz_microdesc.c +++ b/src/test/fuzz/fuzz_microdesc.c @@ -1,8 +1,9 @@ /* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE + #include "core/or/or.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/microdesc_parse.h" +#include "feature/dirparse/unparseable.h" #include "feature/nodelist/microdesc.h" #include "lib/crypt_ops/crypto_ed25519.h" diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c index 5665ffeaca..3c6d205a3f 100644 --- a/src/test/fuzz/fuzz_vrs.c +++ b/src/test/fuzz/fuzz_vrs.c @@ -1,9 +1,10 @@ /* Copyright (c) 2016-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define ROUTERPARSE_PRIVATE +#define NS_PARSE_PRIVATE #define NETWORKSTATUS_PRIVATE #include "core/or/or.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/ns_parse.h" +#include "feature/dirparse/unparseable.h" #include "lib/memarea/memarea.h" #include "feature/nodelist/microdesc.h" #include "feature/nodelist/networkstatus.h" diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c index 4e13ba43a7..dcec1b9d48 100644 --- a/src/test/hs_test_helpers.c +++ b/src/test/hs_test_helpers.c @@ -241,11 +241,11 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, hs_desc_authorized_client_t *client1 = smartlist_get(desc1->superencrypted_data.clients, i), *client2 = smartlist_get(desc2->superencrypted_data.clients, i); - tor_memeq(client1->client_id, client2->client_id, + tt_mem_op(client1->client_id, OP_EQ, client2->client_id, sizeof(client1->client_id)); - tor_memeq(client1->iv, client2->iv, + tt_mem_op(client1->iv, OP_EQ, client2->iv, sizeof(client1->iv)); - tor_memeq(client1->encrypted_cookie, client2->encrypted_cookie, + tt_mem_op(client1->encrypted_cookie, OP_EQ, client2->encrypted_cookie, sizeof(client1->encrypted_cookie)); } } diff --git a/src/test/include.am b/src/test/include.am index c54605383c..e5eae56e25 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -12,8 +12,7 @@ TESTS_ENVIRONMENT = \ export EXTRA_CARGO_OPTIONS="$(EXTRA_CARGO_OPTIONS)"; \ export CARGO_ONLINE="$(CARGO_ONLINE)"; \ export CCLD="$(CCLD)"; \ - chmod +x "$(abs_top_builddir)/link_rust.sh"; \ - export RUSTFLAGS="-C linker=$(abs_top_builddir)/link_rust.sh"; + export RUSTFLAGS="-C linker=`echo '$(CC)' | cut -d' ' -f 1` $(RUST_LINKER_OPTIONS)"; TESTSCRIPTS = \ src/test/fuzz_static_testcases.sh \ @@ -33,6 +32,7 @@ endif if USEPYTHON TESTSCRIPTS += src/test/test_ntor.sh src/test/test_hs_ntor.sh src/test/test_bt.sh +TESTSCRIPTS += src/test/test_rebind.sh endif TESTS += src/test/test src/test/test-slow src/test/test-memwipe \ @@ -181,6 +181,7 @@ src_test_test_SOURCES += \ src/test/test_x509.c \ src/test/test_helpers.c \ src/test/test_dns.c \ + src/test/test_parsecommon.c \ src/test/testing_common.c \ src/test/testing_rsakeys.c \ src/ext/tinytest.c @@ -353,6 +354,8 @@ EXTRA_DIST += \ src/test/hs_indexes.py \ src/test/fuzz_static_testcases.sh \ src/test/slownacl_curve25519.py \ + src/test/test_rebind.sh \ + src/test/test_rebind.py \ src/test/zero_length_keys.sh \ src/test/rust_supp.txt \ src/test/test_keygen.sh \ diff --git a/src/test/test.c b/src/test/test.c index dc8e3bede3..17b736d305 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -11,7 +11,6 @@ #include "orconfig.h" #include "lib/crypt_ops/crypto_dh.h" #include "lib/crypt_ops/crypto_rand.h" - #include "app/config/or_state_st.h" #include <stdio.h> @@ -33,7 +32,7 @@ #define ROUTER_PRIVATE #define CIRCUITSTATS_PRIVATE #define CIRCUITLIST_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define STATEFILE_PRIVATE #include "core/or/or.h" @@ -46,16 +45,16 @@ #include "core/or/connection_edge.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendcache.h" +#include "feature/rend/rendparse.h" #include "test/test.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "lib/memarea/memarea.h" -#include "core/crypto/onion.h" +#include "core/or/onion.h" #include "core/crypto/onion_ntor.h" #include "core/crypto/onion_fast.h" #include "core/crypto/onion_tap.h" #include "core/or/policies.h" #include "feature/stats/rephist.h" -#include "feature/nodelist/routerparse.h" #include "app/config/statefile.h" #include "lib/crypt_ops/crypto_curve25519.h" @@ -64,6 +63,7 @@ #include "feature/rend/rend_encoded_v2_service_descriptor_st.h" #include "feature/rend/rend_intro_point_st.h" #include "feature/rend/rend_service_descriptor_st.h" +#include "feature/relay/onion_queue.h" /** Run unit tests for the onion handshake code. */ static void @@ -847,8 +847,8 @@ struct testgroup_t testgroups[] = { { "circuitbuild/", circuitbuild_tests }, { "circuitlist/", circuitlist_tests }, { "circuitmux/", circuitmux_tests }, - { "circuituse/", circuituse_tests }, { "circuitstats/", circuitstats_tests }, + { "circuituse/", circuituse_tests }, { "compat/libevent/", compat_libevent_tests }, { "config/", config_tests }, { "connection/", connection_tests }, @@ -865,34 +865,36 @@ struct testgroup_t testgroups[] = { #endif { "crypto/pem/", pem_tests }, { "dir/", dir_tests }, - { "dir_handle_get/", dir_handle_get_tests }, { "dir/md/", microdesc_tests }, { "dir/voting-schedule/", voting_schedule_tests }, + { "dir_handle_get/", dir_handle_get_tests }, + { "dns/", dns_tests }, { "dos/", dos_tests }, { "entryconn/", entryconn_tests }, { "entrynodes/", entrynodes_tests }, - { "guardfraction/", guardfraction_tests }, { "extorport/", extorport_tests }, { "geoip/", geoip_tests }, - { "legacy_hs/", hs_tests }, + { "guardfraction/", guardfraction_tests }, { "hs_cache/", hs_cache }, { "hs_cell/", hs_cell_tests }, + { "hs_client/", hs_client_tests }, { "hs_common/", hs_common_tests }, { "hs_config/", hs_config_tests }, { "hs_control/", hs_control_tests }, { "hs_descriptor/", hs_descriptor }, + { "hs_intropoint/", hs_intropoint_tests }, { "hs_ntor/", hs_ntor_tests }, { "hs_service/", hs_service_tests }, - { "hs_client/", hs_client_tests }, - { "hs_intropoint/", hs_intropoint_tests }, { "introduce/", introduce_tests }, { "keypin/", keypin_tests }, + { "legacy_hs/", hs_tests }, { "link-handshake/", link_handshake_tests }, { "mainloop/", mainloop_tests }, { "nodelist/", nodelist_tests }, { "oom/", oom_tests }, { "oos/", oos_tests }, { "options/", options_tests }, + { "parsecommon/", parsecommon_tests }, { "periodic-event/" , periodic_event_tests }, { "policy/" , policy_tests }, { "procmon/", procmon_tests }, @@ -910,8 +912,8 @@ struct testgroup_t testgroups[] = { { "routerlist/", routerlist_tests }, { "routerset/" , routerset_tests }, { "scheduler/", scheduler_tests }, - { "socks/", socks_tests }, { "shared-random/", sr_tests }, + { "socks/", socks_tests }, { "status/" , status_tests }, { "storagedir/", storagedir_tests }, { "tortls/", tortls_tests }, @@ -921,10 +923,9 @@ struct testgroup_t testgroups[] = { { "tortls/x509/", x509_tests }, { "util/", util_tests }, { "util/format/", util_format_tests }, + { "util/handle/", handle_tests }, { "util/logging/", logging_tests }, { "util/process/", util_process_tests }, { "util/thread/", thread_tests }, - { "util/handle/", handle_tests }, - { "dns/", dns_tests }, END_OF_GROUPS }; diff --git a/src/test/test.h b/src/test/test.h index a46fedf3e0..092356f0fb 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -177,11 +177,11 @@ extern const struct testcase_setup_t ed25519_test_setup; extern struct testcase_t accounting_tests[]; extern struct testcase_t addr_tests[]; -extern struct testcase_t address_tests[]; extern struct testcase_t address_set_tests[]; +extern struct testcase_t address_tests[]; extern struct testcase_t bridges_tests[]; -extern struct testcase_t bwmgt_tests[]; extern struct testcase_t buffer_tests[]; +extern struct testcase_t bwmgt_tests[]; extern struct testcase_t cell_format_tests[]; extern struct testcase_t cell_queue_tests[]; extern struct testcase_t channel_tests[]; @@ -191,8 +191,8 @@ extern struct testcase_t checkdir_tests[]; extern struct testcase_t circuitbuild_tests[]; extern struct testcase_t circuitlist_tests[]; extern struct testcase_t circuitmux_tests[]; -extern struct testcase_t circuituse_tests[]; extern struct testcase_t circuitstats_tests[]; +extern struct testcase_t circuituse_tests[]; extern struct testcase_t compat_libevent_tests[]; extern struct testcase_t config_tests[]; extern struct testcase_t connection_tests[]; @@ -200,30 +200,32 @@ extern struct testcase_t conscache_tests[]; extern struct testcase_t consdiff_tests[]; extern struct testcase_t consdiffmgr_tests[]; extern struct testcase_t container_tests[]; -extern struct testcase_t controller_tests[]; extern struct testcase_t controller_event_tests[]; -extern struct testcase_t crypto_tests[]; +extern struct testcase_t controller_tests[]; extern struct testcase_t crypto_ope_tests[]; extern struct testcase_t crypto_openssl_tests[]; -extern struct testcase_t dir_tests[]; +extern struct testcase_t crypto_tests[]; extern struct testcase_t dir_handle_get_tests[]; +extern struct testcase_t dir_tests[]; +extern struct testcase_t dns_tests[]; extern struct testcase_t dos_tests[]; extern struct testcase_t entryconn_tests[]; extern struct testcase_t entrynodes_tests[]; -extern struct testcase_t guardfraction_tests[]; extern struct testcase_t extorport_tests[]; extern struct testcase_t geoip_tests[]; -extern struct testcase_t hs_tests[]; +extern struct testcase_t guardfraction_tests[]; +extern struct testcase_t handle_tests[]; extern struct testcase_t hs_cache[]; extern struct testcase_t hs_cell_tests[]; +extern struct testcase_t hs_client_tests[]; 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_intropoint_tests[]; extern struct testcase_t hs_ntor_tests[]; extern struct testcase_t hs_service_tests[]; -extern struct testcase_t hs_client_tests[]; -extern struct testcase_t hs_intropoint_tests[]; +extern struct testcase_t hs_tests[]; extern struct testcase_t introduce_tests[]; extern struct testcase_t keypin_tests[]; extern struct testcase_t link_handshake_tests[]; @@ -234,6 +236,7 @@ extern struct testcase_t nodelist_tests[]; extern struct testcase_t oom_tests[]; extern struct testcase_t oos_tests[]; extern struct testcase_t options_tests[]; +extern struct testcase_t parsecommon_tests[]; extern struct testcase_t pem_tests[]; extern struct testcase_t periodic_event_tests[]; extern struct testcase_t policy_tests[]; @@ -252,19 +255,17 @@ extern struct testcase_t routerkeys_tests[]; extern struct testcase_t routerlist_tests[]; extern struct testcase_t routerset_tests[]; extern struct testcase_t scheduler_tests[]; -extern struct testcase_t storagedir_tests[]; extern struct testcase_t socks_tests[]; +extern struct testcase_t sr_tests[]; extern struct testcase_t status_tests[]; +extern struct testcase_t storagedir_tests[]; extern struct testcase_t thread_tests[]; -extern struct testcase_t tortls_tests[]; extern struct testcase_t tortls_openssl_tests[]; -extern struct testcase_t util_tests[]; +extern struct testcase_t tortls_tests[]; extern struct testcase_t util_format_tests[]; extern struct testcase_t util_process_tests[]; +extern struct testcase_t util_tests[]; extern struct testcase_t voting_schedule_tests[]; -extern struct testcase_t dns_tests[]; -extern struct testcase_t handle_tests[]; -extern struct testcase_t sr_tests[]; extern struct testcase_t x509_tests[]; extern struct testcase_t slow_crypto_tests[]; diff --git a/src/test/test_addr.c b/src/test/test_addr.c index a9004048a5..1d97db52a6 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -723,7 +723,7 @@ test_addr_ip6_helpers(void *arg) ; } -/** Test tor_addr_port_parse(). */ +/** Test tor_addr_parse() and tor_addr_port_parse(). */ static void test_addr_parse(void *arg) { @@ -734,6 +734,60 @@ test_addr_parse(void *arg) /* Correct call. */ (void)arg; + r= tor_addr_parse(&addr, "192.0.2.1"); + tt_int_op(r,OP_EQ, AF_INET); + tor_addr_to_str(buf, &addr, sizeof(buf), 0); + tt_str_op(buf,OP_EQ, "192.0.2.1"); + + r= tor_addr_parse(&addr, "11:22::33:44"); + tt_int_op(r,OP_EQ, AF_INET6); + tor_addr_to_str(buf, &addr, sizeof(buf), 0); + tt_str_op(buf,OP_EQ, "11:22::33:44"); + + r= tor_addr_parse(&addr, "[11:22::33:44]"); + tt_int_op(r,OP_EQ, AF_INET6); + tor_addr_to_str(buf, &addr, sizeof(buf), 0); + tt_str_op(buf,OP_EQ, "11:22::33:44"); + + r= tor_addr_parse(&addr, "11:22:33:44:55:66:1.2.3.4"); + tt_int_op(r,OP_EQ, AF_INET6); + tor_addr_to_str(buf, &addr, sizeof(buf), 0); + tt_str_op(buf,OP_EQ, "11:22:33:44:55:66:102:304"); + + r= tor_addr_parse(&addr, "11:22::33:44:1.2.3.4"); + tt_int_op(r,OP_EQ, AF_INET6); + tor_addr_to_str(buf, &addr, sizeof(buf), 0); + tt_str_op(buf,OP_EQ, "11:22::33:44:102:304"); + + /* Empty string. */ + r= tor_addr_parse(&addr, ""); + tt_int_op(r,OP_EQ, -1); + + /* Square brackets around IPv4 address. */ + r= tor_addr_parse(&addr, "[192.0.2.1]"); + tt_int_op(r,OP_EQ, -1); + + /* Only left square bracket. */ + r= tor_addr_parse(&addr, "[11:22::33:44"); + tt_int_op(r,OP_EQ, -1); + + /* Only right square bracket. */ + r= tor_addr_parse(&addr, "11:22::33:44]"); + tt_int_op(r,OP_EQ, -1); + + /* Leading colon. */ + r= tor_addr_parse(&addr, ":11:22::33:44"); + tt_int_op(r,OP_EQ, -1); + + /* Trailing colon. */ + r= tor_addr_parse(&addr, "11:22::33:44:"); + tt_int_op(r,OP_EQ, -1); + + /* Too many hex words in IPv4-mapped IPv6 address. */ + r= tor_addr_parse(&addr, "11:22:33:44:55:66:77:88:1.2.3.4"); + tt_int_op(r,OP_EQ, -1); + + /* Correct call. */ r= tor_addr_port_parse(LOG_DEBUG, "192.0.2.1:1234", &addr, &port, -1); diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c index 07d6b88ed9..1cad5445f4 100644 --- a/src/test/test_bridges.c +++ b/src/test/test_bridges.c @@ -16,6 +16,10 @@ #include "feature/client/bridges.h" #include "app/config/config.h" #include "feature/client/transports.h" +#include "feature/nodelist/node_st.h" +#include "feature/nodelist/routerinfo_st.h" +#include "feature/nodelist/routerstatus_st.h" +#include "feature/nodelist/microdesc_st.h" /* Test suite stuff */ #include "test/test.h" @@ -75,6 +79,7 @@ helper_add_bridges_to_bridgelist(void *arg) char *bridge5 = tor_strdup("apple 4.4.4.4:4444 " "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA " "foo=abcdefghijklmnopqrstuvwxyz"); + char *bridge6 = tor_strdup("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:6666"); mark_bridge_list(); @@ -93,6 +98,7 @@ helper_add_bridges_to_bridgelist(void *arg) ADD_BRIDGE(bridge3); ADD_BRIDGE(bridge4); ADD_BRIDGE(bridge5); + ADD_BRIDGE(bridge6); #undef ADD_BRIDGES sweep_bridge_list(); @@ -585,6 +591,92 @@ test_bridges_get_transport_by_bridge_addrport(void *arg) sweep_bridge_list(); } +static void +test_bridges_node_is_a_configured_bridge(void *arg) +{ + routerinfo_t ri_ipv4 = { .addr = 0x06060606, .or_port = 6666 }; + routerstatus_t rs_ipv4 = { .addr = 0x06060606, .or_port = 6666 }; + + routerinfo_t ri_ipv6 = { .ipv6_orport = 6666 }; + tor_addr_parse(&(ri_ipv6.ipv6_addr), + "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + + routerstatus_t rs_ipv6 = { .ipv6_orport = 6666 }; + tor_addr_parse(&(rs_ipv6.ipv6_addr), + "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + + microdesc_t md_ipv6 = { .ipv6_orport = 6666 }; + tor_addr_parse(&(md_ipv6.ipv6_addr), + "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + + helper_add_bridges_to_bridgelist(arg); + + node_t node_with_digest; + memset(&node_with_digest, 0, sizeof(node_with_digest)); + + const char fingerprint[HEX_DIGEST_LEN] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + const char fingerprint2[HEX_DIGEST_LEN] = + "ffffffffffffffffffffffffffffffffffffffff"; + + base16_decode(node_with_digest.identity, DIGEST_LEN, + fingerprint, HEX_DIGEST_LEN); + + node_t node_ri_ipv4 = { .ri = &ri_ipv4 }; + base16_decode(node_ri_ipv4.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_ri_ipv4)); + + /* This will still match bridge0, since bridge0 has no digest set. */ + memset(node_ri_ipv4.identity, 0x3f, DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_ri_ipv4)); + + /* It won't match bridge1, though, since bridge1 has a digest, and this + isn't it! */ + node_ri_ipv4.ri->addr = 0x06060607; + node_ri_ipv4.ri->or_port = 6667; + tt_assert(! node_is_a_configured_bridge(&node_ri_ipv4)); + /* If we set the fingerprint right, though, it will match. */ + base16_decode(node_ri_ipv4.identity, DIGEST_LEN, + "A10C4F666D27364036B562823E5830BC448E046A", HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_ri_ipv4)); + + node_t node_rs_ipv4 = { .rs = &rs_ipv4 }; + base16_decode(node_rs_ipv4.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_rs_ipv4)); + + node_t node_ri_ipv6 = { .ri = &ri_ipv6 }; + base16_decode(node_ri_ipv6.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_ri_ipv6)); + + node_t node_rs_ipv6 = { .rs = &rs_ipv6 }; + base16_decode(node_rs_ipv6.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_rs_ipv6)); + + node_t node_md_ipv6 = { .md = &md_ipv6 }; + base16_decode(node_md_ipv6.identity, DIGEST_LEN, + fingerprint2, HEX_DIGEST_LEN); + tt_assert(node_is_a_configured_bridge(&node_md_ipv6)); + + mark_bridge_list(); + sweep_bridge_list(); + + tt_assert(!node_is_a_configured_bridge(&node_with_digest)); + tt_assert(!node_is_a_configured_bridge(&node_ri_ipv4)); + tt_assert(!node_is_a_configured_bridge(&node_ri_ipv6)); + tt_assert(!node_is_a_configured_bridge(&node_rs_ipv4)); + tt_assert(!node_is_a_configured_bridge(&node_rs_ipv6)); + tt_assert(!node_is_a_configured_bridge(&node_md_ipv6)); + + done: + mark_bridge_list(); + sweep_bridge_list(); +} + #undef PT_PRIVATE /* defined(PT_PRIVATE) */ #define B_TEST(name, flags) \ @@ -607,5 +699,6 @@ struct testcase_t bridges_tests[] = { B_TEST(get_transport_by_bridge_addrport_no_ptlist, 0), B_TEST(get_transport_by_bridge_addrport, 0), B_TEST(transport_is_needed, 0), + B_TEST(node_is_a_configured_bridge, 0), END_OF_TESTCASES }; diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c index 2753c42191..daf0296e2a 100644 --- a/src/test/test_cell_formats.c +++ b/src/test/test_cell_formats.c @@ -13,7 +13,7 @@ #include "core/or/connection_or.h" #include "app/config/config.h" #include "lib/crypt_ops/crypto_rand.h" -#include "core/crypto/onion.h" +#include "core/or/onion.h" #include "core/crypto/onion_tap.h" #include "core/crypto/onion_fast.h" #include "core/crypto/onion_ntor.h" diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c index de673de543..0fd60d0a92 100644 --- a/src/test/test_channelpadding.c +++ b/src/test/test_channelpadding.c @@ -2,7 +2,7 @@ /* See LICENSE for licensing information */ #define TOR_CHANNEL_INTERNAL_ -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define NETWORKSTATUS_PRIVATE #define TOR_TIMERS_PRIVATE #include "core/or/or.h" @@ -16,7 +16,7 @@ #include "lib/evloop/compat_libevent.h" #include "app/config/config.h" #include "lib/time/compat_time.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "feature/nodelist/networkstatus.h" #include "test/log_test_helpers.h" #include "lib/tls/tortls.h" diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c index 1d46f8de0d..1be2ff5281 100644 --- a/src/test/test_circuitmux.c +++ b/src/test/test_circuitmux.c @@ -15,6 +15,8 @@ #include "core/or/destroy_cell_queue_st.h" +#include <math.h> + /* XXXX duplicated function from test_circuitlist.c */ static channel_t * new_fake_channel(void) @@ -105,16 +107,19 @@ test_cmux_compute_ticks(void *arg) monotime_coarse_set_mock_time_nsec(now); tick = cell_ewma_get_current_tick_and_fraction(&rem); tt_uint_op(tick, OP_EQ, tick_zero); - tt_double_op(rem, OP_GT, .149999999); - tt_double_op(rem, OP_LT, .150000001); +#ifdef USING_32BIT_MSEC_HACK + const double tolerance = .0005; +#else + const double tolerance = .00000001; +#endif + tt_double_op(fabs(rem - .15), OP_LT, tolerance); /* 25 second later and we should be in another tick. */ now = START_NS + NS_PER_S * 25; monotime_coarse_set_mock_time_nsec(now); tick = cell_ewma_get_current_tick_and_fraction(&rem); tt_uint_op(tick, OP_EQ, tick_zero + 2); - tt_double_op(rem, OP_GT, .499999999); - tt_double_op(rem, OP_LT, .500000001); + tt_double_op(fabs(rem - .5), OP_LT, tolerance); done: ; diff --git a/src/test/test_config.c b/src/test/test_config.c index bf21a8d512..dae4d83766 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -29,15 +29,17 @@ #include "feature/client/entrynodes.h" #include "feature/client/transports.h" #include "feature/relay/ext_orport.h" -#include "feature/stats/geoip.h" +#include "lib/geoip/geoip.h" #include "feature/hibernate/hibernate.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/nodelist.h" #include "core/or/policies.h" #include "feature/rend/rendclient.h" #include "feature/rend/rendservice.h" #include "feature/relay/router.h" +#include "feature/relay/routermode.h" +#include "feature/nodelist/dirlist.h" #include "feature/nodelist/routerlist.h" #include "feature/nodelist/routerset.h" #include "app/config/statefile.h" diff --git a/src/test/test_connection.c b/src/test/test_connection.c index e716c83fe1..0013f47fbc 100644 --- a/src/test/test_connection.c +++ b/src/test/test_connection.c @@ -4,7 +4,7 @@ #include "orconfig.h" #define CONNECTION_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define CONNECTION_OR_PRIVATE #include "core/or/or.h" @@ -13,12 +13,12 @@ #include "core/mainloop/connection.h" #include "core/or/connection_edge.h" #include "feature/hs/hs_common.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "feature/nodelist/microdesc.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/networkstatus.h" #include "feature/rend/rendcache.h" -#include "feature/dircache/directory.h" +#include "feature/dircommon/directory.h" #include "core/or/connection_or.h" #include "lib/net/resolve.h" diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c index 966314be13..b84753ff83 100644 --- a/src/test/test_consdiffmgr.c +++ b/src/test/test_consdiffmgr.c @@ -11,7 +11,7 @@ #include "core/mainloop/cpuworker.h" #include "lib/crypt_ops/crypto_rand.h" #include "feature/nodelist/networkstatus.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/ns_parse.h" #include "lib/evloop/workqueue.h" #include "lib/compress/compress.h" #include "lib/encoding/confline.h" diff --git a/src/test/test_controller.c b/src/test/test_controller.c index 0428ac6fce..4f5a9f58d5 100644 --- a/src/test/test_controller.c +++ b/src/test/test_controller.c @@ -10,7 +10,7 @@ #include "feature/hs/hs_common.h" #include "feature/nodelist/networkstatus.h" #include "feature/rend/rendservice.h" -#include "feature/nodelist/routerlist.h" +#include "feature/nodelist/authcert.h" #include "feature/nodelist/nodelist.h" #include "test/test.h" #include "test/test_helpers.h" diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c index e935b70428..4c404876b0 100644 --- a/src/test/test_controller_events.c +++ b/src/test/test_controller_events.c @@ -322,6 +322,72 @@ test_cntev_event_mask(void *arg) ; } +static char *saved_event_str = NULL; + +static void +mock_queue_control_event_string(uint16_t event, char *msg) +{ + (void)event; + + tor_free(saved_event_str); + saved_event_str = msg; +} + +/* Helper macro for checking bootstrap control event strings */ +#define assert_bootmsg(s) \ + tt_ptr_op(strstr(saved_event_str, "650 STATUS_CLIENT NOTICE " \ + "BOOTSTRAP PROGRESS=" s), OP_EQ, saved_event_str) + +/* Test deferral of directory bootstrap messages (requesting_descriptors) */ +static void +test_cntev_dirboot_defer_desc(void *arg) +{ + (void)arg; + + MOCK(queue_control_event_string, mock_queue_control_event_string); + control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT)); + control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0); + assert_bootmsg("0 TAG=starting"); + /* This event should get deferred */ + control_event_boot_dir(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); + assert_bootmsg("0 TAG=starting"); + control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0); + assert_bootmsg("5 TAG=conn_dir"); + control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); + assert_bootmsg("10 TAG=handshake_dir"); + /* The deferred event should appear */ + control_event_boot_first_orconn(); + assert_bootmsg("45 TAG=requesting_descriptors"); + done: + tor_free(saved_event_str); + UNMOCK(queue_control_event_string); +} + +/* Test deferral of directory bootstrap messages (conn_or) */ +static void +test_cntev_dirboot_defer_orconn(void *arg) +{ + (void)arg; + + MOCK(queue_control_event_string, mock_queue_control_event_string); + control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT)); + control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0); + assert_bootmsg("0 TAG=starting"); + /* This event should get deferred */ + control_event_boot_dir(BOOTSTRAP_STATUS_CONN_OR, 0); + assert_bootmsg("0 TAG=starting"); + control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0); + assert_bootmsg("5 TAG=conn_dir"); + control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); + assert_bootmsg("10 TAG=handshake_dir"); + /* The deferred event should appear */ + control_event_boot_first_orconn(); + assert_bootmsg("80 TAG=conn_or"); + done: + tor_free(saved_event_str); + UNMOCK(queue_control_event_string); +} + #define TEST(name, flags) \ { #name, test_cntev_ ## name, flags, 0, NULL } @@ -330,5 +396,7 @@ struct testcase_t controller_event_tests[] = { TEST(append_cell_stats, TT_FORK), TEST(format_cell_stats, TT_FORK), TEST(event_mask, TT_FORK), + TEST(dirboot_defer_desc, TT_FORK), + TEST(dirboot_defer_orconn, TT_FORK), END_OF_TESTCASES }; diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 078a383dd8..26ba269abd 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -6,49 +6,73 @@ #include "orconfig.h" #include <math.h> +#define BWAUTH_PRIVATE #define CONFIG_PRIVATE #define CONTROL_PRIVATE +#define DIRCACHE_PRIVATE +#define DIRCLIENT_PRIVATE #define DIRSERV_PRIVATE #define DIRVOTE_PRIVATE -#define ROUTER_PRIVATE -#define ROUTERLIST_PRIVATE -#define ROUTERPARSE_PRIVATE +#define DLSTATUS_PRIVATE #define HIBERNATE_PRIVATE #define NETWORKSTATUS_PRIVATE +#define NS_PARSE_PRIVATE +#define NODE_SELECT_PRIVATE #define RELAY_PRIVATE +#define ROUTERLIST_PRIVATE +#define ROUTER_PRIVATE +#define UNPARSEABLE_PRIVATE +#define VOTEFLAGS_PRIVATE #include "core/or/or.h" -#include "feature/client/bridges.h" -#include "core/mainloop/connection.h" -#include "app/config/confparse.h" #include "app/config/config.h" +#include "app/config/confparse.h" +#include "core/mainloop/connection.h" +#include "core/or/relay.h" +#include "core/or/versions.h" +#include "feature/client/bridges.h" +#include "feature/client/entrynodes.h" #include "feature/control/control.h" -#include "lib/encoding/confline.h" -#include "lib/crypt_ops/crypto_ed25519.h" -#include "lib/crypt_ops/crypto_format.h" -#include "lib/crypt_ops/crypto_rand.h" -#include "feature/dircache/directory.h" -#include "feature/dircache/dirserv.h" +#include "feature/dirauth/bwauth.h" #include "feature/dirauth/dirvote.h" -#include "feature/client/entrynodes.h" +#include "feature/dirauth/dsigs_parse.h" +#include "feature/dirauth/process_descs.h" +#include "feature/dirauth/recommend_pkg.h" +#include "feature/dirauth/shared_random_state.h" +#include "feature/dirauth/voteflags.h" +#include "feature/dircache/dircache.h" +#include "feature/dircache/dirserv.h" +#include "feature/dirclient/dirclient.h" +#include "feature/dirclient/dlstatus.h" +#include "feature/dircommon/directory.h" #include "feature/dircommon/fp_pair.h" +#include "feature/dircommon/voting_schedule.h" #include "feature/hibernate/hibernate.h" -#include "lib/memarea/memarea.h" -#include "lib/osinfo/uname.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/dirlist.h" #include "feature/nodelist/networkstatus.h" -#include "feature/relay/router.h" -#include "feature/relay/routerkeys.h" +#include "feature/nodelist/nickname.h" +#include "feature/nodelist/node_select.h" #include "feature/nodelist/routerlist.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/authcert_parse.h" +#include "feature/dirparse/ns_parse.h" +#include "feature/dirparse/routerparse.h" +#include "feature/dirparse/unparseable.h" #include "feature/nodelist/routerset.h" -#include "feature/dirauth/shared_random_state.h" -#include "test/test.h" -#include "test/test_dir_common.h" #include "feature/nodelist/torcert.h" -#include "core/or/relay.h" -#include "test/log_test_helpers.h" -#include "feature/dircommon/voting_schedule.h" +#include "feature/relay/router.h" +#include "feature/relay/routerkeys.h" +#include "feature/relay/routermode.h" #include "lib/compress/compress.h" +#include "lib/crypt_ops/crypto_ed25519.h" +#include "lib/crypt_ops/crypto_format.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/encoding/confline.h" +#include "lib/memarea/memarea.h" +#include "lib/osinfo/uname.h" +#include "test/log_test_helpers.h" +#include "test/test.h" +#include "test/test_dir_common.h" #include "core/or/addr_policy_st.h" #include "feature/nodelist/authority_cert_st.h" diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c index 63bd082eea..eadeb11921 100644 --- a/src/test/test_dir_common.c +++ b/src/test/test_dir_common.c @@ -10,6 +10,8 @@ #include "feature/dirauth/dirvote.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerlist.h" +#include "feature/dirparse/authcert_parse.h" +#include "feature/dirparse/ns_parse.h" #include "test/test_dir_common.h" #include "feature/dircommon/voting_schedule.h" diff --git a/src/test/test_dir_common.h b/src/test/test_dir_common.h index 1e90228edb..1e958a21ff 100644 --- a/src/test/test_dir_common.h +++ b/src/test/test_dir_common.h @@ -5,7 +5,6 @@ #include "core/or/or.h" #include "feature/nodelist/networkstatus.h" -#include "feature/nodelist/routerparse.h" #define TEST_DIR_ROUTER_ID_1 3 #define TEST_DIR_ROUTER_ID_2 5 diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c index b591396913..2ce98769af 100644 --- a/src/test/test_dir_handle_get.c +++ b/src/test/test_dir_handle_get.c @@ -8,27 +8,32 @@ #define CONNECTION_PRIVATE #define CONFIG_PRIVATE #define RENDCACHE_PRIVATE +#define DIRCACHE_PRIVATE #include "core/or/or.h" #include "app/config/config.h" #include "core/mainloop/connection.h" #include "feature/dircache/consdiffmgr.h" -#include "feature/dircache/directory.h" +#include "feature/dircommon/directory.h" +#include "feature/dircache/dircache.h" #include "test/test.h" #include "lib/compress/compress.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendcache.h" #include "feature/relay/router.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/dirlist.h" #include "feature/nodelist/routerlist.h" #include "test/rend_test_helpers.h" #include "feature/nodelist/microdesc.h" #include "test/test_helpers.h" #include "feature/nodelist/nodelist.h" #include "feature/client/entrynodes.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/authcert_parse.h" #include "feature/nodelist/networkstatus.h" #include "core/proto/proto_http.h" -#include "feature/stats/geoip.h" +#include "lib/geoip/geoip.h" +#include "feature/stats/geoip_stats.h" #include "feature/dircache/dirserv.h" #include "feature/dirauth/dirvote.h" #include "test/log_test_helpers.h" diff --git a/src/test/test_dns.c b/src/test/test_dns.c index 8369f844f6..ea0fcf8c5e 100644 --- a/src/test/test_dns.c +++ b/src/test/test_dns.c @@ -1,6 +1,7 @@ /* Copyright (c) 2015-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#include "orconfig.h" #include "core/or/or.h" #include "test/test.h" @@ -13,9 +14,71 @@ #include "core/or/edge_connection_st.h" #include "core/or/or_circuit_st.h" +#include "app/config/or_options_st.h" +#include "app/config/config.h" + +#include <event2/event.h> +#include <event2/dns.h> #define NS_MODULE dns +#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR +#define NS_SUBMODULE configure_nameservers_fallback + +static or_options_t options = { + .ORPort_set = 1, +}; + +static const or_options_t * +mock_get_options(void) +{ + return &options; +} + +static void +NS(test_main)(void *arg) +{ + (void)arg; + tor_addr_t *nameserver_addr = NULL; + + MOCK(get_options, mock_get_options); + + options.ServerDNSResolvConfFile = (char *)"no_such_file!!!"; + + dns_init(); // calls configure_nameservers() + + tt_int_op(number_of_configured_nameservers(), OP_EQ, 1); + + nameserver_addr = configured_nameserver_address(0); + + tt_assert(tor_addr_family(nameserver_addr) == AF_INET); + tt_assert(tor_addr_eq_ipv4h(nameserver_addr, 0x7f000001)); + +#ifndef _WIN32 + tor_free(nameserver_addr); + + options.ServerDNSResolvConfFile = (char *)"/dev/null"; + + dns_init(); + + tt_int_op(number_of_configured_nameservers(), OP_EQ, 1); + + nameserver_addr = configured_nameserver_address(0); + + tt_assert(tor_addr_family(nameserver_addr) == AF_INET); + tt_assert(tor_addr_eq_ipv4h(nameserver_addr, 0x7f000001)); +#endif + + UNMOCK(get_options); + + done: + tor_free(nameserver_addr); + return; +} + +#undef NS_SUBMODULE +#endif + #define NS_SUBMODULE clip_ttl static void @@ -736,6 +799,9 @@ NS(test_main)(void *arg) #undef NS_SUBMODULE struct testcase_t dns_tests[] = { +#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR + TEST_CASE(configure_nameservers_fallback), +#endif TEST_CASE(clip_ttl), TEST_CASE(resolve), TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve), diff --git a/src/test/test_dos.c b/src/test/test_dos.c index b411e7b38a..40a4c6ba29 100644 --- a/src/test/test_dos.c +++ b/src/test/test_dos.c @@ -9,7 +9,7 @@ #include "core/or/dos.h" #include "core/or/circuitlist.h" #include "lib/crypt_ops/crypto_rand.h" -#include "feature/stats/geoip.h" +#include "feature/stats/geoip_stats.h" #include "core/or/channel.h" #include "feature/nodelist/microdesc.h" #include "feature/nodelist/networkstatus.h" @@ -500,4 +500,3 @@ struct testcase_t dos_tests[] = { NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index cb694106c4..b67c9fae53 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -8,7 +8,7 @@ #define STATEFILE_PRIVATE #define ENTRYNODES_PRIVATE #define ROUTERLIST_PRIVATE -#define DIRECTORY_PRIVATE +#define DIRCLIENT_PRIVATE #include "core/or/or.h" #include "test/test.h" @@ -19,13 +19,13 @@ #include "app/config/config.h" #include "app/config/confparse.h" #include "lib/crypt_ops/crypto_rand.h" -#include "feature/dircache/directory.h" +#include "feature/dircommon/directory.h" +#include "feature/dirclient/dirclient.h" #include "feature/client/entrynodes.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/networkstatus.h" #include "core/or/policies.h" #include "feature/nodelist/routerlist.h" -#include "feature/nodelist/routerparse.h" #include "feature/nodelist/routerset.h" #include "app/config/statefile.h" diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c index ff987563c6..71be9131c7 100644 --- a/src/test/test_extorport.c +++ b/src/test/test_extorport.c @@ -3,7 +3,7 @@ #define CONNECTION_PRIVATE #define EXT_ORPORT_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #include "core/or/or.h" #include "lib/container/buffers.h" #include "core/mainloop/connection.h" @@ -12,11 +12,12 @@ #include "feature/control/control.h" #include "lib/crypt_ops/crypto_rand.h" #include "feature/relay/ext_orport.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "core/or/or_connection_st.h" #include "test/test.h" +#include "test/test_helpers.h" #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> @@ -89,22 +90,6 @@ connection_write_to_buf_impl_replacement(const char *string, size_t len, buf_add(conn->outbuf, string, len); } -static char * -buf_get_contents(buf_t *buf, size_t *sz_out) -{ - char *out; - *sz_out = buf_datalen(buf); - if (*sz_out >= ULONG_MAX) - return NULL; /* C'mon, really? */ - out = tor_malloc(*sz_out + 1); - if (buf_get_bytes(buf, out, (unsigned long)*sz_out) != 0) { - tor_free(out); - return NULL; - } - out[*sz_out] = '\0'; /* Hopefully gratuitous. */ - return out; -} - static void test_ext_or_write_command(void *arg) { @@ -463,7 +448,7 @@ test_ext_or_handshake(void *arg) memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32); ext_or_auth_cookie_is_set = 1; - init_connection_lists(); + tor_init_connection_lists(); conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET); tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn)); diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c index 9df8ea7988..6f9c39063b 100644 --- a/src/test/test_geoip.c +++ b/src/test/test_geoip.c @@ -10,7 +10,8 @@ #define GEOIP_PRIVATE #include "core/or/or.h" #include "app/config/config.h" -#include "feature/stats/geoip.h" +#include "lib/geoip/geoip.h" +#include "feature/stats/geoip_stats.h" #include "test/test.h" /* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs @@ -403,7 +404,8 @@ test_geoip_load_file(void *arg) /* A nonexistant filename should fail. */ tt_int_op(-1, OP_EQ, - geoip_load_file(AF_INET, "/you/did/not/put/a/file/here/I/hope")); + geoip_load_file(AF_INET, "/you/did/not/put/a/file/here/I/hope", + LOG_INFO)); /* We start out with only "Ningunpartia" in the database. */ tt_int_op(1, OP_EQ, geoip_get_n_countries()); @@ -417,7 +419,7 @@ test_geoip_load_file(void *arg) const char *fname = get_fname("geoip"); tt_int_op(0, OP_EQ, write_str_to_file(fname, GEOIP_CONTENT, 1)); - int rv = geoip_load_file(AF_INET, fname); + int rv = geoip_load_file(AF_INET, fname, LOG_WARN); if (rv != 0) { TT_GRIPE(("Unable to load geoip from %s", escaped(fname))); } @@ -467,7 +469,8 @@ test_geoip6_load_file(void *arg) /* A nonexistant filename should fail. */ tt_int_op(-1, OP_EQ, - geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope")); + geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope", + LOG_INFO)); /* Any lookup attempt should say "-1" because we have no info */ tor_inet_pton(AF_INET6, "2001:4860:4860::8888", &iaddr6); @@ -493,7 +496,7 @@ test_geoip6_load_file(void *arg) "2001:4878:205::,2001:4878:214:ffff:ffff:ffff:ffff:ffff,US\n"; tt_int_op(0, OP_EQ, write_str_to_file(fname6, CONTENT, 1)); - tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, fname6)); + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, fname6, LOG_WARN)); /* Check that we loaded some countries; this will fail if there are ever * fewer than 5 countries in our test data above. */ @@ -545,11 +548,11 @@ test_geoip_load_2nd_file(void *arg) tt_int_op(0, OP_EQ, write_str_to_file(fname_empty, "\n", 1)); /* Load 1st geoip file */ - tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_geoip)); + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_geoip, LOG_WARN)); /* Load 2nd geoip (empty) file */ /* It has to be the same IP address family */ - tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_empty)); + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_empty, LOG_WARN)); /* Check that there is no geoip information for 8.8.8.8, */ /* since loading the empty 2nd file should have delete it. */ diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c index f45a723295..d6f4cd63f2 100644 --- a/src/test/test_guardfraction.c +++ b/src/test/test_guardfraction.c @@ -1,16 +1,16 @@ /* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#define DIRSERV_PRIVATE -#define ROUTERPARSE_PRIVATE +#define GUARDFRACTION_PRIVATE #define NETWORKSTATUS_PRIVATE +#define NS_PARSE_PRIVATE #include "orconfig.h" #include "core/or/or.h" #include "app/config/config.h" -#include "feature/dircache/dirserv.h" +#include "feature/dirauth/guardfraction.h" #include "feature/client/entrynodes.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/ns_parse.h" #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/networkstatus_st.h" @@ -422,4 +422,3 @@ struct testcase_t guardfraction_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c index c9138611d8..6ac73bff5c 100644 --- a/src/test/test_helpers.c +++ b/src/test/test_helpers.c @@ -9,7 +9,7 @@ #define ROUTERLIST_PRIVATE #define CONFIG_PRIVATE #define CONNECTION_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #include "orconfig.h" #include "core/or/or.h" @@ -19,7 +19,7 @@ #include "app/config/confparse.h" #include "core/mainloop/connection.h" #include "lib/crypt_ops/crypto_rand.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "feature/nodelist/nodelist.h" #include "core/or/relay.h" #include "feature/nodelist/routerlist.h" @@ -125,6 +125,25 @@ connection_write_to_buf_mock(const char *string, size_t len, buf_add(conn->outbuf, string, len); } +char * +buf_get_contents(buf_t *buf, size_t *sz_out) +{ + tor_assert(buf); + tor_assert(sz_out); + + char *out; + *sz_out = buf_datalen(buf); + if (*sz_out >= ULONG_MAX) + return NULL; /* C'mon, really? */ + out = tor_malloc(*sz_out + 1); + if (buf_get_bytes(buf, out, (unsigned long)*sz_out) != 0) { + tor_free(out); + return NULL; + } + out[*sz_out] = '\0'; /* Hopefully gratuitous. */ + return out; +} + /* Set up a fake origin circuit with the specified number of cells, * Return a pointer to the newly-created dummy circuit */ circuit_t * @@ -217,7 +236,7 @@ test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose) mock_connection_connect_sockaddr); MOCK(tor_close_socket, fake_close_socket); - init_connection_lists(); + tor_init_connection_lists(); conn = connection_new(type, TEST_CONN_FAMILY); tt_assert(conn); diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h index 3196c93e6b..72bf7f2f71 100644 --- a/src/test/test_helpers.h +++ b/src/test/test_helpers.h @@ -4,6 +4,8 @@ #ifndef TOR_TEST_HELPERS_H #define TOR_TEST_HELPERS_H +#define BUFFERS_PRIVATE + #include "core/or/or.h" const char *get_yesterday_date_str(void); @@ -18,6 +20,7 @@ void helper_setup_fake_routerlist(void); #define GET(path) "GET " path " HTTP/1.0\r\n\r\n" void connection_write_to_buf_mock(const char *string, size_t len, connection_t *conn, int compressed); +char *buf_get_contents(buf_t *buf, size_t *sz_out); int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name, uint16_t family, tor_addr_t *out); diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c index 728bb4a2f5..203a1d7039 100644 --- a/src/test/test_hs_cache.c +++ b/src/test/test_hs_cache.c @@ -7,13 +7,15 @@ */ #define CONNECTION_PRIVATE -#define DIRECTORY_PRIVATE +#define DIRCACHE_PRIVATE +#define DIRCLIENT_PRIVATE #define HS_CACHE_PRIVATE #include "trunnel/ed25519_cert.h" #include "feature/hs/hs_cache.h" #include "feature/rend/rendcache.h" -#include "feature/dircache/directory.h" +#include "feature/dircache/dircache.h" +#include "feature/dirclient/dirclient.h" #include "feature/nodelist/networkstatus.h" #include "core/mainloop/connection.h" #include "core/proto/proto_http.h" diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c index c91e82ed4a..91b3ed1ec4 100644 --- a/src/test/test_hs_client.c +++ b/src/test/test_hs_client.c @@ -8,7 +8,7 @@ #define CONFIG_PRIVATE #define CRYPTO_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define HS_CLIENT_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define CIRCUITBUILD_PRIVATE @@ -25,8 +25,8 @@ #include "lib/crypt_ops/crypto_cipher.h" #include "lib/crypt_ops/crypto_dh.h" #include "core/or/channeltls.h" -#include "feature/dircache/directory.h" -#include "core/mainloop/main.h" +#include "feature/dircommon/directory.h" +#include "core/mainloop/mainloop.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerset.h" @@ -523,6 +523,9 @@ mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason, (void) line; (void) file; conn->edge_.end_reason = endreason; + /* This function ultimately will flag this so make sure we do also in the + * MOCK one so we can assess closed connections vs open ones. */ + conn->edge_.base_.marked_for_close = 1; } static void @@ -771,6 +774,218 @@ test_config_client_authorization(void *arg) UNMOCK(check_private_dir); } +static entry_connection_t * +helper_build_socks_connection(const ed25519_public_key_t *service_pk, + int conn_state) +{ + entry_connection_t *socks = entry_connection_new(CONN_TYPE_AP, AF_INET); + ENTRY_TO_EDGE_CONN(socks)->hs_ident = hs_ident_edge_conn_new(service_pk); + TO_CONN(ENTRY_TO_EDGE_CONN(socks))->state = conn_state; + smartlist_add(get_connection_array(), &socks->edge_.base_); + return socks; +} + +static void +test_desc_has_arrived_cleanup(void *arg) +{ + /* The goal of this test is to make sure we clean up everything in between + * two descriptors from the same .onion. Because intro points can change + * from one descriptor to another, once we received a new descriptor, we + * need to cleanup the remaining circuits so they aren't used or selected + * when establishing a connection with the newly stored descriptor. + * + * This test was created because of #27410. */ + + int ret; + char *desc_str = NULL; + hs_descriptor_t *desc = NULL; + const hs_descriptor_t *cached_desc; + ed25519_keypair_t signing_kp; + entry_connection_t *socks1 = NULL, *socks2 = NULL; + hs_ident_dir_conn_t hs_dir_ident; + + (void) arg; + + hs_init(); + + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + MOCK(connection_mark_unattached_ap_, + mock_connection_mark_unattached_ap_); + MOCK(router_have_minimum_dir_info, + mock_router_have_minimum_dir_info_true); + + /* Set consensus time before our time so the cache lookup can always + * validate that the entry is not expired. */ + parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", &mock_ns.valid_after); + parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", &mock_ns.fresh_until); + parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC", &mock_ns.valid_until); + + /* Build a descriptor for a specific .onion. */ + ret = ed25519_keypair_generate(&signing_kp, 0); + tt_int_op(ret, OP_EQ, 0); + desc = hs_helper_build_hs_desc_with_ip(&signing_kp); + tt_assert(desc); + ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &desc_str); + tt_int_op(ret, OP_EQ, 0); + + /* Store in the client cache. */ + ret = hs_cache_store_as_client(desc_str, &signing_kp.pubkey); + tt_int_op(ret, OP_EQ, 0); + cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey); + tt_assert(cached_desc); + hs_helper_desc_equal(desc, cached_desc); + + /* Create two SOCKS connection for the same .onion both in the waiting for a + * descriptor state. */ + socks1 = helper_build_socks_connection(&signing_kp.pubkey, + AP_CONN_STATE_RENDDESC_WAIT); + tt_assert(socks1); + socks2 = helper_build_socks_connection(&signing_kp.pubkey, + AP_CONN_STATE_RENDDESC_WAIT); + tt_assert(socks2); + + /* Now, we'll make the intro points in the current descriptor unusable so + * the hs_client_desc_has_arrived() will take the right code path that we + * want to test that is the fetched descriptor has bad intro points. */ + SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points, + hs_desc_intro_point_t *, ip) { + hs_cache_client_intro_state_note(&signing_kp.pubkey, + &ip->auth_key_cert->signed_key, + INTRO_POINT_FAILURE_GENERIC); + } SMARTLIST_FOREACH_END(ip); + + /* Simulate that a new descriptor just arrived. We should have both of our + * SOCKS connection to be ended with a resolved failed. */ + hs_ident_dir_conn_init(&signing_kp.pubkey, + &desc->plaintext_data.blinded_pubkey, &hs_dir_ident); + hs_client_desc_has_arrived(&hs_dir_ident); + tt_int_op(socks1->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED); + /* XXX: MUST work with OP_EQ. */ + tt_int_op(socks2->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED); + + /* Now let say tor cleans up the intro state cache which resets all intro + * point failure count. */ + hs_cache_client_intro_state_purge(); + + /* Retrying all SOCKS which should basically do nothing since we don't have + * any pending SOCKS connection in AP_CONN_STATE_RENDDESC_WAIT state. */ + /* XXX: BUG() is triggered here, shouldn't if socks2 wasn't alive. */ + retry_all_socks_conn_waiting_for_desc(); + + done: + connection_free_minimal(ENTRY_TO_CONN(socks1)); + connection_free_minimal(ENTRY_TO_CONN(socks2)); + hs_descriptor_free(desc); + tor_free(desc_str); + hs_free_all(); + + UNMOCK(networkstatus_get_live_consensus); + UNMOCK(connection_mark_unattached_ap_); + UNMOCK(router_have_minimum_dir_info); +} + +static void +test_close_intro_circuits_new_desc(void *arg) +{ + int ret; + ed25519_keypair_t service_kp; + circuit_t *circ = NULL; + origin_circuit_t *ocirc = NULL; + hs_descriptor_t *desc1 = NULL, *desc2 = NULL; + + (void) arg; + + hs_init(); + + /* This is needed because of the client cache expiration timestamp is based + * on having a consensus. See cached_client_descriptor_has_expired(). */ + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + /* Set consensus time */ + parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", + &mock_ns.valid_after); + parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", + &mock_ns.fresh_until); + parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC", + &mock_ns.valid_until); + + /* Generate service keypair */ + tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0)); + + /* Create and add to the global list a dummy client introduction circuits. + * We'll then make sure the hs_ident is attached to a dummy descriptor. */ + circ = dummy_origin_circuit_new(0); + tt_assert(circ); + circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING; + ocirc = TO_ORIGIN_CIRCUIT(circ); + + /* Build the first descriptor and cache it. */ + { + char *encoded; + desc1 = hs_helper_build_hs_desc_with_ip(&service_kp); + tt_assert(desc1); + ret = hs_desc_encode_descriptor(desc1, &service_kp, NULL, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + + /* Store it */ + ret = hs_cache_store_as_client(encoded, &service_kp.pubkey); + tt_int_op(ret, OP_EQ, 0); + tor_free(encoded); + tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey)); + } + + /* We'll pick one introduction point and associate it with the circuit. */ + { + const hs_desc_intro_point_t *ip = + smartlist_get(desc1->encrypted_data.intro_points, 0); + tt_assert(ip); + ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey, + HS_IDENT_CIRCUIT_INTRO); + ed25519_pubkey_copy(ô->hs_ident->intro_auth_pk, + &ip->auth_key_cert->signed_key); + } + + /* Before we are about to clean up the intro circuits, make sure it is + * actually there. */ + tt_assert(circuit_get_next_intro_circ(NULL, true)); + + /* Build the second descriptor for the same service and cache it. */ + { + char *encoded; + desc2 = hs_helper_build_hs_desc_with_ip(&service_kp); + tt_assert(desc2); + tt_mem_op(&desc1->plaintext_data.signing_pubkey, OP_EQ, + &desc2->plaintext_data.signing_pubkey, ED25519_PUBKEY_LEN); + /* To replace the existing descriptor, the revision counter needs to be + * bigger. */ + desc2->plaintext_data.revision_counter = + desc1->plaintext_data.revision_counter + 1; + + ret = hs_desc_encode_descriptor(desc2, &service_kp, NULL, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + + hs_cache_store_as_client(encoded, &service_kp.pubkey); + tt_int_op(ret, OP_EQ, 0); + tor_free(encoded); + tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey)); + } + + /* Once stored, our intro circuit should be closed because it is related to + * an old introduction point that doesn't exists anymore. */ + tt_assert(!circuit_get_next_intro_circ(NULL, true)); + + done: + circuit_free(circ); + hs_descriptor_free(desc1); + hs_descriptor_free(desc2); + hs_free_all(); + UNMOCK(networkstatus_get_live_consensus); +} + struct testcase_t hs_client_tests[] = { { "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy, TT_FORK, NULL, NULL }, @@ -786,5 +1001,10 @@ struct testcase_t hs_client_tests[] = { NULL, NULL }, { "config_client_authorization", test_config_client_authorization, TT_FORK, NULL, NULL }, + { "desc_has_arrived_cleanup", test_desc_has_arrived_cleanup, + TT_FORK, NULL, NULL }, + { "close_intro_circuits_new_desc", test_close_intro_circuits_new_desc, + TT_FORK, NULL, NULL }, + END_OF_TESTCASES }; diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c index c60d6e2640..95f7ed14ba 100644 --- a/src/test/test_hs_common.c +++ b/src/test/test_hs_common.c @@ -24,7 +24,7 @@ #include "feature/hs/hs_service.h" #include "app/config/config.h" #include "feature/nodelist/networkstatus.h" -#include "feature/dircache/directory.h" +#include "feature/dirclient/dirclient.h" #include "feature/dirauth/dirvote.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerlist.h" diff --git a/src/test/test_hs_config.c b/src/test/test_hs_config.c index 553b96758a..b6ab0c21f9 100644 --- a/src/test/test_hs_config.c +++ b/src/test/test_hs_config.c @@ -366,6 +366,22 @@ test_invalid_service_v3(void *arg) teardown_capture_of_logs(); } + /* v2-specific HiddenServiceAuthorizeClient set. */ + { + const char *conf = + "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" + "HiddenServiceVersion 3\n" + "HiddenServiceAuthorizeClient stealth client1\n"; + setup_full_capture_of_logs(LOG_WARN); + ret = helper_config_service(conf, validate_only); + tt_int_op(ret, OP_EQ, -1); + expect_log_msg_containing("Hidden service option " + "HiddenServiceAuthorizeClient is incompatible " + "with version 3 of service in " + "/tmp/tor-test-hs-RANDOM/hs1"); + teardown_capture_of_logs(); + } + done: ; } diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c index 4889281cb1..428ca1024b 100644 --- a/src/test/test_hs_descriptor.c +++ b/src/test/test_hs_descriptor.c @@ -675,6 +675,8 @@ test_decode_bad_signature(void *arg) (void) arg; + memset(&desc_plaintext, 0, sizeof(desc_plaintext)); + /* Update approx time to dodge cert expiration */ update_approx_time(1502661599); @@ -907,7 +909,7 @@ test_build_authorized_client(void *arg) client_pubkey_b16, strlen(client_pubkey_b16)); - MOCK(crypto_strongest_rand, mock_crypto_strongest_rand); + MOCK(crypto_strongest_rand_, mock_crypto_strongest_rand); hs_desc_build_authorized_client(subcredential, &client_auth_pk, &auth_ephemeral_sk, @@ -923,7 +925,7 @@ test_build_authorized_client(void *arg) done: tor_free(desc_client); tor_free(mem_op_hex_tmp); - UNMOCK(crypto_strongest_rand); + UNMOCK(crypto_strongest_rand_); } struct testcase_t hs_descriptor[] = { diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c index 6a061eaea4..ee2d71aa75 100644 --- a/src/test/test_hs_service.c +++ b/src/test/test_hs_service.c @@ -10,17 +10,17 @@ #define CIRCUITLIST_PRIVATE #define CONFIG_PRIVATE #define CONNECTION_PRIVATE +#define CONNECTION_EDGE_PRIVATE #define CRYPTO_PRIVATE #define HS_COMMON_PRIVATE #define HS_SERVICE_PRIVATE #define HS_INTROPOINT_PRIVATE #define HS_CIRCUIT_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #define NETWORKSTATUS_PRIVATE #define STATEFILE_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define HS_CLIENT_PRIVATE -#define ROUTERPARSE_PRIVATE #include "test/test.h" #include "test/test_helpers.h" @@ -30,30 +30,33 @@ #include "core/or/or.h" #include "app/config/config.h" +#include "app/config/statefile.h" +#include "core/crypto/hs_ntor.h" +#include "core/mainloop/connection.h" +#include "core/mainloop/mainloop.h" #include "core/or/circuitbuild.h" #include "core/or/circuitlist.h" #include "core/or/circuituse.h" -#include "lib/crypt_ops/crypto_rand.h" -#include "lib/fs/dir.h" -#include "feature/dirauth/dirvote.h" -#include "feature/nodelist/networkstatus.h" -#include "feature/nodelist/nodelist.h" +#include "core/or/connection_edge.h" +#include "core/or/edge_connection_st.h" #include "core/or/relay.h" -#include "feature/nodelist/routerparse.h" +#include "core/or/versions.h" +#include "feature/dirauth/dirvote.h" +#include "feature/dirauth/shared_random_state.h" +#include "feature/dircommon/voting_schedule.h" +#include "feature/hs/hs_circuit.h" +#include "feature/hs/hs_circuitmap.h" +#include "feature/hs/hs_client.h" #include "feature/hs/hs_common.h" #include "feature/hs/hs_config.h" #include "feature/hs/hs_ident.h" #include "feature/hs/hs_intropoint.h" -#include "core/crypto/hs_ntor.h" -#include "feature/hs/hs_circuit.h" -#include "feature/hs/hs_circuitmap.h" #include "feature/hs/hs_service.h" -#include "feature/hs/hs_client.h" -#include "core/mainloop/main.h" +#include "feature/nodelist/networkstatus.h" +#include "feature/nodelist/nodelist.h" #include "feature/rend/rendservice.h" -#include "app/config/statefile.h" -#include "feature/dirauth/shared_random_state.h" -#include "feature/dircommon/voting_schedule.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/fs/dir.h" #include "core/or/cpath_build_state_st.h" #include "core/or/crypt_path_st.h" @@ -534,6 +537,7 @@ test_load_keys_with_client_auth(void *arg) tt_int_op(get_hs_service_map_size(), OP_EQ, 1); service = get_first_service(); + tt_assert(service); tt_assert(service->config.clients); tt_int_op(smartlist_len(service->config.clients), OP_EQ, smartlist_len(pubkey_b32_list)); @@ -563,9 +567,7 @@ test_load_keys_with_client_auth(void *arg) } SMARTLIST_FOREACH_END(pubkey_b32); done: - if (pubkey_b32_list) { - SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s)); - } + SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s)); smartlist_free(pubkey_b32_list); tor_free(hsdir_v3); hs_free_all(); @@ -746,6 +748,8 @@ test_helper_functions(void *arg) MOCK(node_get_by_id, mock_node_get_by_id); hs_service_init(); + time_t now = time(NULL); + update_approx_time(now); service = helper_create_service(); @@ -805,7 +809,6 @@ test_helper_functions(void *arg) /* Testing can_service_launch_intro_circuit() */ { - time_t now = time(NULL); /* Put the start of the retry period back in time, we should be allowed. * to launch intro circuit. */ service->state.num_intro_circ_launched = 2; @@ -829,7 +832,6 @@ test_helper_functions(void *arg) /* Testing intro_point_should_expire(). */ { - time_t now = time(NULL); /* Just some basic test of the current state. */ tt_u64_op(ip->introduce2_max, OP_GE, INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS); @@ -1455,7 +1457,7 @@ test_build_update_descriptors(void *arg) /* Time to test the update of those descriptors. At first, we have no node * in the routerlist so this will find NO suitable node for the IPs. */ setup_full_capture_of_logs(LOG_INFO); - update_all_descriptors(now); + update_all_descriptors_intro_points(now); expect_log_msg_containing("Unable to find a suitable node to be an " "introduction point for service"); teardown_capture_of_logs(); @@ -1506,7 +1508,7 @@ test_build_update_descriptors(void *arg) /* We expect to pick only one intro point from the node above. */ setup_full_capture_of_logs(LOG_INFO); - update_all_descriptors(now); + update_all_descriptors_intro_points(now); tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */ tor_free(node->ri->cache_info.signing_key_cert); tor_free(node->ri->onion_pkey); @@ -2005,6 +2007,96 @@ test_authorized_client_config_equal(void *arg) tor_free(config2); } +/** Test that client circuit ID gets correctly exported */ +static void +test_export_client_circuit_id(void *arg) +{ + origin_circuit_t *or_circ = NULL; + size_t sz; + char *cp1=NULL, *cp2=NULL; + connection_t *conn = NULL; + + (void) arg; + + MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock); + + hs_service_init(); + + /* Create service */ + hs_service_t *service = helper_create_service(); + /* Check that export circuit ID detection works */ + service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_NONE; + tt_int_op(0, OP_EQ, + hs_service_exports_circuit_id(&service->keys.identity_pk)); + service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_HAPROXY; + tt_int_op(1, OP_EQ, + hs_service_exports_circuit_id(&service->keys.identity_pk)); + + /* Create client connection */ + conn = test_conn_get_connection(AP_CONN_STATE_CIRCUIT_WAIT, CONN_TYPE_AP, 0); + + /* Create client edge conn hs_ident */ + edge_connection_t *edge_conn = TO_EDGE_CONN(conn); + edge_conn->hs_ident = hs_ident_edge_conn_new(&service->keys.identity_pk); + edge_conn->hs_ident->orig_virtual_port = 42; + + /* Create rend circuit */ + or_circ = origin_circuit_new(); + or_circ->base_.purpose = CIRCUIT_PURPOSE_C_REND_JOINED; + edge_conn->on_circuit = TO_CIRCUIT(or_circ); + or_circ->global_identifier = 666; + + /* Export circuit ID */ + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + + /* Check contents */ + cp1 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_EQ, + "PROXY TCP6 fc00:dead:beef:4dad::0:29a ::1 666 42\r\n"); + + /* Change circ GID and see that the reported circuit ID also changes */ + or_circ->global_identifier = 22; + + /* check changes */ + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + cp2 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_NE, cp2); + tor_free(cp1); + + /* Check that GID with UINT32_MAX works. */ + or_circ->global_identifier = UINT32_MAX; + + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + cp1 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_EQ, + "PROXY TCP6 fc00:dead:beef:4dad::ffff:ffff ::1 65535 42\r\n"); + tor_free(cp1); + + /* Check that GID with UINT16_MAX works. */ + or_circ->global_identifier = UINT16_MAX; + + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + cp1 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_EQ, + "PROXY TCP6 fc00:dead:beef:4dad::0:ffff ::1 65535 42\r\n"); + tor_free(cp1); + + /* Check that GID with UINT16_MAX + 7 works. */ + or_circ->global_identifier = UINT16_MAX + 7; + + export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); + cp1 = buf_get_contents(conn->outbuf, &sz); + tt_str_op(cp1, OP_EQ, "PROXY TCP6 fc00:dead:beef:4dad::1:6 ::1 6 42\r\n"); + + done: + UNMOCK(connection_write_to_buf_impl_); + circuit_free_(TO_CIRCUIT(or_circ)); + connection_free_minimal(conn); + hs_service_free(service); + tor_free(cp1); + tor_free(cp2); +} + struct testcase_t hs_service_tests[] = { { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK, NULL, NULL }, @@ -2046,6 +2138,8 @@ struct testcase_t hs_service_tests[] = { NULL, NULL }, { "authorized_client_config_equal", test_authorized_client_config_equal, TT_FORK, NULL, NULL }, + { "export_client_circuit_id", test_export_client_circuit_id, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c index df3fa67eb1..82a91a9ae2 100644 --- a/src/test/test_link_handshake.c +++ b/src/test/test_link_handshake.c @@ -942,15 +942,25 @@ test_link_handshake_send_authchallenge(void *arg) cell1 = mock_got_var_cell; tt_int_op(0, OP_EQ, connection_or_send_auth_challenge_cell(c1)); cell2 = mock_got_var_cell; +#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS tt_int_op(38, OP_EQ, cell1->payload_len); tt_int_op(38, OP_EQ, cell2->payload_len); +#else + tt_int_op(36, OP_EQ, cell1->payload_len); + tt_int_op(36, OP_EQ, cell2->payload_len); +#endif tt_int_op(0, OP_EQ, cell1->circ_id); tt_int_op(0, OP_EQ, cell2->circ_id); tt_int_op(CELL_AUTH_CHALLENGE, OP_EQ, cell1->command); tt_int_op(CELL_AUTH_CHALLENGE, OP_EQ, cell2->command); +#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS tt_mem_op("\x00\x02\x00\x01\x00\x03", OP_EQ, cell1->payload + 32, 6); tt_mem_op("\x00\x02\x00\x01\x00\x03", OP_EQ, cell2->payload + 32, 6); +#else + tt_mem_op("\x00\x01\x00\x03", OP_EQ, cell1->payload + 32, 4); + tt_mem_op("\x00\x01\x00\x03", OP_EQ, cell2->payload + 32, 4); +#endif tt_mem_op(cell1->payload, OP_NE, cell2->payload, 32); done: @@ -992,6 +1002,8 @@ static void * recv_authchallenge_setup(const struct testcase_t *test) { (void)test; + + testing__connection_or_pretend_TLSSECRET_is_supported = 1; authchallenge_data_t *d = tor_malloc_zero(sizeof(*d)); d->c = or_connection_new(CONN_TYPE_OR, AF_INET); d->chan = tor_malloc_zero(sizeof(*d->chan)); @@ -1205,6 +1217,8 @@ authenticate_data_setup(const struct testcase_t *test) authenticate_data_t *d = tor_malloc_zero(sizeof(*d)); int is_ed = d->is_ed = (test->setup_data == (void*)3); + testing__connection_or_pretend_TLSSECRET_is_supported = 1; + scheduler_init(); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); diff --git a/src/test/test_mainloop.c b/src/test/test_mainloop.c index f85c224ae9..92ce2e9918 100644 --- a/src/test/test_mainloop.c +++ b/src/test/test_mainloop.c @@ -10,7 +10,7 @@ #include "test/log_test_helpers.h" #include "core/or/or.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" static const uint64_t BILLION = 1000000000; diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index ec4779ead1..8ede2690ec 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -4,13 +4,14 @@ #include "orconfig.h" #include "core/or/or.h" -#include "app/config/config.h" #define DIRVOTE_PRIVATE +#include "app/config/config.h" #include "feature/dirauth/dirvote.h" +#include "feature/dirparse/microdesc_parse.h" +#include "feature/dirparse/routerparse.h" #include "feature/nodelist/microdesc.h" #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/routerlist.h" -#include "feature/nodelist/routerparse.h" #include "feature/nodelist/torcert.h" #include "feature/nodelist/microdesc_st.h" diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c index cdd5e95cf0..1af6db68ec 100644 --- a/src/test/test_nodelist.c +++ b/src/test/test_nodelist.c @@ -19,6 +19,7 @@ #include "feature/nodelist/routerstatus_st.h" #include "test/test.h" +#include "test/log_test_helpers.h" /** Test the case when node_get_by_id() returns NULL, * node_get_verbose_nickname_by_id should return the base 16 encoding @@ -126,9 +127,10 @@ mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f) static void test_nodelist_ed_id(void *arg) { - routerstatus_t *rs[4]; - microdesc_t *md[4]; - routerinfo_t *ri[4]; +#define N_NODES 5 + routerstatus_t *rs[N_NODES]; + microdesc_t *md[N_NODES]; + routerinfo_t *ri[N_NODES]; networkstatus_t *ns; int i; (void)arg; @@ -145,7 +147,7 @@ test_nodelist_ed_id(void *arg) /* Make a bunch of dummy objects that we can play around with. Only set the necessary fields */ - for (i = 0; i < 4; ++i) { + for (i = 0; i < N_NODES; ++i) { rs[i] = tor_malloc_zero(sizeof(*rs[i])); md[i] = tor_malloc_zero(sizeof(*md[i])); ri[i] = tor_malloc_zero(sizeof(*ri[i])); @@ -162,7 +164,7 @@ test_nodelist_ed_id(void *arg) memcpy(&ri[i]->cache_info.signing_key_cert->signing_key, md[i]->ed25519_identity_pkey, sizeof(ed25519_public_key_t)); - if (i != 3) + if (i < 3) smartlist_add(ns->routerstatus_list, rs[i]); } @@ -192,13 +194,30 @@ test_nodelist_ed_id(void *arg) /* Register the 4th by ri only -- we never put it into the networkstatus, * so it has to be independent */ - n = nodelist_set_routerinfo(ri[3], &ri_old); - tt_ptr_op(n, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); + node_t *n3 = nodelist_set_routerinfo(ri[3], &ri_old); + tt_ptr_op(n3, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); tt_ptr_op(ri_old, OP_EQ, NULL); tt_int_op(4, OP_EQ, smartlist_len(nodelist_get_list())); + /* Register the 5th by ri only, and rewrite its ed25519 pubkey to be + * the same as the 4th, to test the duplicate ed25519 key logging in + * nodelist.c */ + memcpy(md[4]->ed25519_identity_pkey, md[3]->ed25519_identity_pkey, + sizeof(ed25519_public_key_t)); + memcpy(&ri[4]->cache_info.signing_key_cert->signing_key, + md[3]->ed25519_identity_pkey, sizeof(ed25519_public_key_t)); + + setup_capture_of_logs(LOG_NOTICE); + node_t *n4 = nodelist_set_routerinfo(ri[4], &ri_old); + tt_ptr_op(ri_old, OP_EQ, NULL); + tt_int_op(5, OP_EQ, smartlist_len(nodelist_get_list())); + tt_ptr_op(n4, OP_NE, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); + tt_ptr_op(n3, OP_EQ, node_get_by_ed25519_id(md[3]->ed25519_identity_pkey)); + expect_log_msg_containing("Reused ed25519_id"); + done: - for (i = 0; i < 4; ++i) { + teardown_capture_of_logs(); + for (i = 0; i < N_NODES; ++i) { tor_free(rs[i]); tor_free(md[i]->ed25519_identity_pkey); tor_free(md[i]); @@ -209,6 +228,7 @@ test_nodelist_ed_id(void *arg) networkstatus_vote_free(ns); UNMOCK(networkstatus_get_latest_consensus); UNMOCK(networkstatus_get_latest_consensus_by_flavor); +#undef N_NODES } #define NODE(name, flags) \ diff --git a/src/test/test_oos.c b/src/test/test_oos.c index 5f9942d8ae..fb0daa7a8d 100644 --- a/src/test/test_oos.c +++ b/src/test/test_oos.c @@ -9,8 +9,8 @@ #include "app/config/config.h" #include "core/mainloop/connection.h" #include "core/or/connection_or.h" -#include "feature/dircache/directory.h" -#include "core/mainloop/main.h" +#include "feature/dircommon/directory.h" +#include "core/mainloop/mainloop.h" #include "test/test.h" #include "feature/dircommon/dir_connection_st.h" diff --git a/src/test/test_options.c b/src/test/test_options.c index 56b7f3cf0f..f14e620eeb 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -8,11 +8,11 @@ #include "app/config/confparse.h" #include "app/config/config.h" #include "test/test.h" -#include "feature/stats/geoip.h" +#include "lib/geoip/geoip.h" #define ROUTERSET_PRIVATE #include "feature/nodelist/routerset.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "test/log_test_helpers.h" #include "lib/sandbox/sandbox.h" diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c new file mode 100644 index 0000000000..6da125dd0a --- /dev/null +++ b/src/test/test_parsecommon.c @@ -0,0 +1,594 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "core/or/or.h" +#include "test/test.h" +#include "lib/memarea/memarea.h" +#include "lib/encoding/binascii.h" +#include "feature/dirparse/parsecommon.h" +#include "test/log_test_helpers.h" + +static void +test_parsecommon_tokenize_string_null(void *arg) +{ + + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + const char *str_with_null = "a\0bccccccccc"; + + int retval = + tokenize_string(area, str_with_null, + str_with_null + 3, + tokens, NULL, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +static void +test_parsecommon_tokenize_string_multiple_lines(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T01("uptime", K_UPTIME, GE(1), NO_OBJ), + T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ), + T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ), + END_OF_TABLE, + }; + + char *str = tor_strdup( + "hibernating 0\nuptime 1024\n" + "published 2018-10-15 10:00:00\n"); + + int retval = + tokenize_string(area, str, NULL, + tokens, table, 0); + + tt_int_op(smartlist_len(tokens), OP_EQ, 3); + directory_token_t *token = smartlist_get(tokens, 0); + + tt_int_op(token->tp, OP_EQ, K_HIBERNATING); + + token = smartlist_get(tokens, 1); + + tt_int_op(token->tp, OP_EQ, K_UPTIME); + + token = smartlist_get(tokens, 2); + + tt_int_op(token->tp, OP_EQ, K_PUBLISHED); + + tt_int_op(retval, OP_EQ, 0); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +static void +test_parsecommon_tokenize_string_min_cnt(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T01("uptime", K_UPTIME, EQ(2), NO_OBJ), + T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ), + END_OF_TABLE, + }; + + // Missing "uptime" + char *str = tor_strdup("uptime 1024\nhibernating 0\n"); + + int retval = + tokenize_string(area, str, NULL, + tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +static void +test_parsecommon_tokenize_string_max_cnt(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T01("uptime", K_UPTIME, EQ(1), NO_OBJ), + T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ), + END_OF_TABLE, + }; + + // "uptime" expected once, but occurs twice in input. + char *str = tor_strdup( + "uptime 1024\nuptime 2048\nhibernating 0\n"); + + int retval = + tokenize_string(area, str, NULL, + tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +static void +test_parsecommon_tokenize_string_at_start(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ), + T01("uptime", K_UPTIME, EQ(1), NO_OBJ), + END_OF_TABLE, + }; + + // "client-name" is not the first line. + char *str = tor_strdup( + "uptime 1024\nclient-name Alice\n"); + + int retval = + tokenize_string(area, str, NULL, tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +static void +test_parsecommon_tokenize_string_at_end(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T1_END("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ), + T01("uptime", K_UPTIME, EQ(1), NO_OBJ), + END_OF_TABLE, + }; + + // "client-name" is not the last line. + char *str = tor_strdup( + "client-name Alice\nuptime 1024\n"); + + int retval = + tokenize_string(area, str, NULL, tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +static void +test_parsecommon_tokenize_string_no_annotations(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ), + END_OF_TABLE, + }; + + char *str = tor_strdup("@last-listed 2018-09-21 15:30:03\n"); + + int retval = + tokenize_string(area, str, NULL, tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +static void +test_parsecommon_get_next_token_success(void *arg) +{ + memarea_t *area = memarea_new(); + const char *str = "uptime 1024"; + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t table = T01("uptime", K_UPTIME, GE(1), NO_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &table); + + tt_int_op(token->tp, OP_EQ, K_UPTIME); + tt_int_op(token->n_args, OP_EQ, 1); + tt_str_op(*(token->args), OP_EQ, "1024"); + tt_assert(!token->object_type); + tt_int_op(token->object_size, OP_EQ, 0); + tt_assert(!token->object_body); + + tt_ptr_op(*s, OP_EQ, end); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_concat_args(void *arg) +{ + memarea_t *area = memarea_new(); + const char *str = "proto A=1 B=2"; + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T01("proto", K_PROTO, CONCAT_ARGS, NO_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, K_PROTO); + tt_int_op(token->n_args, OP_EQ, 1); + tt_str_op(*(token->args), OP_EQ, "A=1 B=2"); + + done: + memarea_drop_all(area); +} + +static void +test_parsecommon_get_next_token_parse_keys(void *arg) +{ + (void)arg; + + memarea_t *area = memarea_new(); + const char *str = + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBAMDdIya33BfNlHOkzoTKSTT8EjD64waMfUr372syVHiFjHhObwKwGA5u\n" + "sHaMIe9r+Ij/4C1dKyuXkcz3DOl6gWNhTD7dZ89I+Okoh1jWe30jxCiAcywC22p5\n" + "XLhrDkX1A63Z7XCH9ltwU2WMqWsVM98N2GR6MTujP7wtqdLExYN1AgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n"; + + const char *end = str + strlen(str); + const char **s = (const char **)&str; + directory_token_t *token = NULL; + directory_token_t *token2 = NULL; + + token_rule_t rule = T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024); + + token = get_next_token(area, s, end, &rule); + tt_assert(token); + + tt_int_op(token->tp, OP_EQ, R_IPO_ONION_KEY); + tt_int_op(token->n_args, OP_EQ, 0); + tt_str_op(token->object_type, OP_EQ, "RSA PUBLIC KEY"); + tt_int_op(token->object_size, OP_EQ, 0); + tt_assert(!token->object_body); + tt_assert(token->key); + tt_assert(!token->error); + + const char *str2 = + "client-key\n" + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIICXAIBAAKBgQCwS810a2auH2PQchOBz9smNgjlDu31aq0IYlUohSYbhcv5AJ+d\n" + "DY0nfZWzS+mZPwzL3UiEnTt6PVv7AgoZ5V9ZJWJTKIURjJpkK0mstfJKHKIZhf84\n" + "pmFfRej9GQViB6NLtp1obOXJgJixSlMfw9doDI4NoAnEISCyH/tD77Qs2wIDAQAB\n" + "AoGAbDg8CKkdQOnX9c7xFpCnsE8fKqz9eddgHHNwXw1NFTwOt+2gDWKSMZmv2X5S\n" + "CVZg3owZxf5W0nT0D6Ny2+6nliak7foYAvkD0BsCiBhgftwC0zAo6k5rIbUKB3PJ\n" + "QLFXgpJhqWuXkODyt/hS/GTernR437WVSEGp1bnALqiFabECQQDaqHOxzoWY/nvH\n" + "KrfUi8EhqCnqERlRHwrW0MQZ1RPvF16OPPma+xa+ht/amfh3vYN5tZY82Zm43gGl\n" + "XWL5cZhNAkEAzmdSootYVnqLLLRMfHKXnO1XbaEcA/08MDNKGlSclBJixFenE8jX\n" + "iQsUbHwMJuGONvzWpRGPBP2f8xBd28ZtxwJARY+LZshtpfNniz/ixYJESaHG28je\n" + "xfjbKOW3TQSFV+2WTifFvHEeljQwKMoMyoMGvYRwLCGJjs9JtMLVxsdFjQJBAKwD\n" + "3BBvBQ39TuPQ1zWX4tb7zjMlY83HTFP3Sriq71tP/1QWoL2SUl56B2lp8E6vB/C3\n" + "wsMK4SCNprHRYAd7VZ0CQDKn6Zhd11P94PLs0msybFEh1VXr6CEW/BrxBgbL4ls6\n" + "dbX5XO0z4Ra8gYXgObgimhyMDYO98Idt5+Z3HIdyrSc=\n" + "-----END RSA PRIVATE KEY-----\n"; + + const char *end2 = str2 + strlen(str2); + const char **s2 = (const char **)&str2; + + token_rule_t rule2 = T01("client-key", C_CLIENT_KEY, NO_ARGS, + NEED_SKEY_1024); + + token2 = get_next_token(area, s2, end2, &rule2); + tt_assert(token2); + + tt_int_op(token2->tp, OP_EQ, C_CLIENT_KEY); + tt_int_op(token2->n_args, OP_EQ, 0); + tt_str_op(token2->object_type, OP_EQ, "RSA PRIVATE KEY"); + tt_int_op(token2->object_size, OP_EQ, 0); + tt_assert(!token2->object_body); + tt_assert(token2->key); + tt_assert(!token->error); + + done: + if (token) token_clear(token); + if (token2) token_clear(token2); + memarea_drop_all(area); +} + +static void +test_parsecommon_get_next_token_object(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-----\n" + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n" + "-----END SIGNATURE-----\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, K_DIRECTORY_SIGNATURE); + tt_int_op(token->n_args, OP_EQ, 2); + tt_str_op(token->args[0], OP_EQ, + "0232AF901C31A04EE9848595AF9BB7620D4C5B2E"); + tt_str_op(token->args[1], OP_EQ, + "CD1FD971855430880D3C31E0331C5C55800C2F79"); + + tt_assert(!token->error); + + char decoded[256]; + const char *signature = + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n"; + tt_assert(signature); + size_t signature_len = strlen(signature); + base64_decode(decoded, sizeof(decoded), signature, signature_len); + + tt_str_op(token->object_type, OP_EQ, "SIGNATURE"); + tt_int_op(token->object_size, OP_EQ, 256); + tt_mem_op(token->object_body, OP_EQ, decoded, 256); + + tt_assert(!token->key); + + done: + memarea_drop_all(area); +} + +static void +test_parsecommon_get_next_token_err_too_many_args(void *arg) +{ + memarea_t *area = memarea_new(); + const char *str = "uptime 1024 1024 1024"; + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t table = T01("uptime", K_UPTIME, EQ(1), NO_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &table); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Too many arguments to uptime"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_too_few_args(void *arg) +{ + memarea_t *area = memarea_new(); + const char *str = "uptime"; + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t table = T01("uptime", K_UPTIME, EQ(1), NO_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &table); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Too few arguments to uptime"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_obj_missing_endline(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-----\n" + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Malformed object: missing object end line"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_bad_beginline(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-Z---\n" + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n" + "-----END SIGNATURE-----\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Malformed object: bad begin line"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_tag_mismatch(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-----\n" + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n" + "-----END SOMETHINGELSE-----\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, + "Malformed object: mismatched end tag SIGNATURE"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_bad_base64(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-----\n" + "%%@%%%%%%%!!!'\n" + "-----END SIGNATURE-----\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Malformed object: bad base64-encoded data"); + + done: + memarea_drop_all(area); + return; +} + +#define PARSECOMMON_TEST(name) \ + { #name, test_parsecommon_ ## name, 0, NULL, NULL } + +struct testcase_t parsecommon_tests[] = { + PARSECOMMON_TEST(tokenize_string_null), + PARSECOMMON_TEST(tokenize_string_multiple_lines), + PARSECOMMON_TEST(tokenize_string_min_cnt), + PARSECOMMON_TEST(tokenize_string_max_cnt), + PARSECOMMON_TEST(tokenize_string_at_start), + PARSECOMMON_TEST(tokenize_string_at_end), + PARSECOMMON_TEST(tokenize_string_no_annotations), + PARSECOMMON_TEST(get_next_token_success), + PARSECOMMON_TEST(get_next_token_concat_args), + PARSECOMMON_TEST(get_next_token_parse_keys), + PARSECOMMON_TEST(get_next_token_object), + PARSECOMMON_TEST(get_next_token_err_too_many_args), + PARSECOMMON_TEST(get_next_token_err_too_few_args), + PARSECOMMON_TEST(get_next_token_err_obj_missing_endline), + PARSECOMMON_TEST(get_next_token_err_bad_beginline), + PARSECOMMON_TEST(get_next_token_err_tag_mismatch), + PARSECOMMON_TEST(get_next_token_err_bad_base64), + END_OF_TESTCASES +}; diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c index b447ae8888..86dedd85d8 100644 --- a/src/test/test_periodic_event.c +++ b/src/test/test_periodic_event.c @@ -9,7 +9,7 @@ #define CONFIG_PRIVATE #define HS_SERVICE_PRIVATE -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #include "test/test.h" #include "test/test_helpers.h" @@ -18,7 +18,7 @@ #include "app/config/config.h" #include "feature/hibernate/hibernate.h" #include "feature/hs/hs_service.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "core/mainloop/periodic.h" /** Helper function: This is replaced in some tests for the event callbacks so @@ -87,15 +87,19 @@ test_pe_launch(void *arg) item->fn = dumb_event_fn; } - /* Lets make sure that before intialization, we can't scan the periodic - * events list and launch them. Lets try by being a Client. */ options = get_options_mutable(); options->SocksPort_set = 1; periodic_events_on_new_options(options); +#if 0 + /* Lets make sure that before intialization, we can't scan the periodic + * events list and launch them. Lets try by being a Client. */ + /* XXXX We make sure these events are initialized now way earlier than we + * did before. */ for (int i = 0; periodic_events[i].name; ++i) { periodic_event_item_t *item = &periodic_events[i]; tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0); } +#endif initialize_periodic_events(); diff --git a/src/test/test_policy.c b/src/test/test_policy.c index 6a07e5b1f8..afe608f5f7 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -1,19 +1,20 @@ /* Copyright (c) 2013-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "core/or/or.h" #define CONFIG_PRIVATE -#include "app/config/config.h" -#include "feature/relay/router.h" -#include "feature/nodelist/routerparse.h" #define POLICIES_PRIVATE + +#include "core/or/or.h" +#include "app/config/config.h" #include "core/or/policies.h" +#include "feature/dirparse/policy_parse.h" +#include "feature/relay/router.h" #include "lib/encoding/confline.h" #include "test/test.h" #include "core/or/addr_policy_st.h" -#include "feature/nodelist/node_st.h" #include "core/or/port_cfg_st.h" +#include "feature/nodelist/node_st.h" #include "feature/nodelist/routerinfo_st.h" #include "feature/nodelist/routerstatus_st.h" diff --git a/src/test/test_protover.c b/src/test/test_protover.c index ac8e98250e..5f9a8b7937 100644 --- a/src/test/test_protover.c +++ b/src/test/test_protover.c @@ -10,6 +10,7 @@ #include "core/or/or.h" #include "core/or/connection_or.h" +#include "lib/tls/tortls.h" static void test_protover_parse(void *arg) @@ -167,6 +168,14 @@ test_protover_vote(void *arg) tt_str_op(result, OP_EQ, ""); tor_free(result); + /* Don't count double-voting. */ + smartlist_clear(lst); + smartlist_add(lst, (void*) "Foo=1 Foo=1"); + smartlist_add(lst, (void*) "Bar=1-2,2-3"); + result = protover_compute_vote(lst, 2); + tt_str_op(result, OP_EQ, ""); + tor_free(result); + /* Bad votes: the result must be empty */ smartlist_clear(lst); smartlist_add(lst, (void*) "Faux=10-5"); @@ -259,6 +268,7 @@ test_protover_all_supported(void *arg) tt_ptr_op(msg, OP_EQ, NULL); // Some things we don't support + tt_assert(! protover_all_supported("Wombat=9", NULL)); tt_assert(! protover_all_supported("Wombat=9", &msg)); tt_str_op(msg, OP_EQ, "Wombat=9"); tor_free(msg); @@ -290,13 +300,13 @@ test_protover_all_supported(void *arg) tor_free(msg); /* We shouldn't be able to DoS ourselves parsing a large range. */ - tt_assert(! protover_all_supported("Sleen=0-2147483648", &msg)); - tt_str_op(msg, OP_EQ, "Sleen=0-2147483648"); + tt_assert(! protover_all_supported("Sleen=1-2147483648", &msg)); + tt_str_op(msg, OP_EQ, "Sleen=1-2147483648"); tor_free(msg); /* This case is allowed. */ - tt_assert(! protover_all_supported("Sleen=0-4294967294", &msg)); - tt_str_op(msg, OP_EQ, "Sleen=0-4294967294"); + tt_assert(! protover_all_supported("Sleen=1-4294967294", &msg)); + tt_str_op(msg, OP_EQ, "Sleen=1-4294967294"); tor_free(msg); /* If we get a (barely) valid (but unsupported list, we say "yes, that's @@ -313,7 +323,7 @@ test_protover_all_supported(void *arg) /* If we get a completely unparseable list, protover_all_supported should * hit a fatal assertion for BUG(entries == NULL). */ tor_capture_bugs_(1); - tt_assert(protover_all_supported("Sleen=0-4294967295", &msg)); + tt_assert(protover_all_supported("Sleen=1-4294967295", &msg)); tor_end_capture_bugs_(); /* Protocol name too long */ @@ -444,10 +454,12 @@ test_protover_supported_protocols(void *arg) } } +#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS /* Legacy LinkAuth does not appear anywhere in the code. */ tt_assert(protocol_list_supports_protocol(supported_protocols, PRT_LINKAUTH, PROTOVER_LINKAUTH_V1)); +#endif /* Latest LinkAuth is not exposed in the headers. */ tt_assert(protocol_list_supports_protocol(supported_protocols, PRT_LINKAUTH, @@ -543,16 +555,20 @@ test_protover_vote_roundtrip(void *args) const char *input; const char *expected_output; } examples[] = { + { "Risqu\u00e9=1", NULL }, + { ",,,=1", NULL }, + { "\xc1=1", NULL }, + { "Foo_Bar=1", NULL }, { "Fkrkljdsf", NULL }, { "Zn=4294967295", NULL }, { "Zn=4294967295-1", NULL }, { "Zn=4294967293-4294967295", NULL }, /* Will fail because of 4294967295. */ - { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=0,4294967295", + { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=1,4294967295", NULL }, - { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=0,4294967294", - "Bar=3 Foo=1,3 Quux=9-12,14-16,900 Zn=0,4294967294" }, - { "Zu16=0,65536", "Zu16=0,65536" }, + { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=1,4294967294", + "Bar=3 Foo=1,3 Quux=9-12,14-16,900 Zn=1,4294967294" }, + { "Zu16=1,65536", "Zu16=1,65536" }, { "N-1=1,2", "N-1=1-2" }, { "-1=4294967295", NULL }, { "-1=3", "-1=3" }, @@ -589,9 +605,9 @@ test_protover_vote_roundtrip(void *args) { "Sleen=1-501", "Sleen=1-501" }, { "Sleen=1-65537", NULL }, /* Both C/Rust implementations should be able to handle this mild DoS. */ - { "Sleen=0-2147483648", NULL }, + { "Sleen=1-2147483648", NULL }, /* Rust tests are built in debug mode, so ints are bounds-checked. */ - { "Sleen=0-4294967295", NULL }, + { "Sleen=1-4294967295", NULL }, }; unsigned u; smartlist_t *votes = smartlist_new(); @@ -633,4 +649,3 @@ struct testcase_t protover_tests[] = { PV_TEST(vote_roundtrip, 0), END_OF_TESTCASES }; - diff --git a/src/test/test_rebind.py b/src/test/test_rebind.py new file mode 100644 index 0000000000..7ba3a5796d --- /dev/null +++ b/src/test/test_rebind.py @@ -0,0 +1,93 @@ +from __future__ import print_function + +import sys +import subprocess +import socket +import os +import time +import random + +def try_connecting_to_socksport(): + socks_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if socks_socket.connect_ex(('127.0.0.1', socks_port)): + tor_process.terminate() + print('FAIL') + sys.exit('Cannot connect to SOCKSPort') + socks_socket.close() + +def wait_for_log(s): + while True: + l = tor_process.stdout.readline() + if s in l.decode('utf8'): + return + +def pick_random_port(): + port = 0 + random.seed() + + for i in range(8): + port = random.randint(10000, 60000) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if s.connect_ex(('127.0.0.1', port)) == 0: + s.close() + else: + break + + return port + +if sys.hexversion < 0x02070000: + sys.exit("ERROR: unsupported Python version (should be >= 2.7)") + +if sys.hexversion > 0x03000000 and sys.hexversion < 0x03010000: + sys.exit("ERROR: unsupported Python3 version (should be >= 3.1)") + +control_port = pick_random_port() +socks_port = pick_random_port() + +assert control_port != 0 +assert socks_port != 0 + +if not os.path.exists(sys.argv[1]): + sys.exit('ERROR: cannot find tor at %s' % sys.argv[1]) + +tor_path = sys.argv[1] + +tor_process = subprocess.Popen([tor_path, + '-ControlPort', '127.0.0.1:{}'.format(control_port), + '-SOCKSPort', '127.0.0.1:{}'.format(socks_port), + '-FetchServerDescriptors', '0'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + +if tor_process == None: + sys.exit('ERROR: running tor failed') + +if len(sys.argv) < 2: + sys.exit('Usage: %s <path-to-tor>' % sys.argv[0]) + +wait_for_log('Opened Control listener on') + +try_connecting_to_socksport() + +control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +if control_socket.connect_ex(('127.0.0.1', control_port)): + tor_process.terminate() + print('FAIL') + sys.exit('Cannot connect to ControlPort') + +control_socket.sendall('AUTHENTICATE \r\n'.encode('utf8')) +control_socket.sendall('SETCONF SOCKSPort=0.0.0.0:{}\r\n'.format(socks_port).encode('utf8')) +wait_for_log('Opened Socks listener') + +try_connecting_to_socksport() + +control_socket.sendall('SETCONF SOCKSPort=127.0.0.1:{}\r\n'.format(socks_port).encode('utf8')) +wait_for_log('Opened Socks listener') + +try_connecting_to_socksport() + +control_socket.sendall('SIGNAL HALT\r\n'.encode('utf8')) + +time.sleep(0.1) +print('OK') +tor_process.terminate() diff --git a/src/test/test_rebind.sh b/src/test/test_rebind.sh new file mode 100755 index 0000000000..76eb9f2e4d --- /dev/null +++ b/src/test/test_rebind.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +set -x + +UNAME_OS=$(uname -s | cut -d_ -f1) +if test "$UNAME_OS" = 'CYGWIN' || \ + test "$UNAME_OS" = 'MSYS' || \ + test "$UNAME_OS" = 'MINGW'; then + if test "$APPVEYOR" = 'True'; then + echo "This test is disabled on Windows CI, as it requires firewall examptions. Skipping." >&2 + exit 77 + fi +fi + +exitcode=0 + +"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_rebind.py" "${TESTING_TOR_BINARY}" || exitcode=1 + +exit ${exitcode} diff --git a/src/test/test_relay.c b/src/test/test_relay.c index 25084fab37..4311392be8 100644 --- a/src/test/test_relay.c +++ b/src/test/test_relay.c @@ -1,12 +1,17 @@ /* Copyright (c) 2014-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include "core/or/or.h" #define CIRCUITBUILD_PRIVATE +#define RELAY_PRIVATE +#define REPHIST_PRIVATE +#include "core/or/or.h" #include "core/or/circuitbuild.h" #include "core/or/circuitlist.h" -#define RELAY_PRIVATE +#include "core/or/channeltls.h" +#include "feature/stats/rephist.h" #include "core/or/relay.h" +#include "feature/stats/rephist.h" +#include "lib/container/order.h" /* For init/free stuff */ #include "core/or/scheduler.h" @@ -31,10 +36,9 @@ new_fake_orcirc(channel_t *nchan, channel_t *pchan) circ = &(orcirc->base_); circ->magic = OR_CIRCUIT_MAGIC; - circ->n_chan = nchan; - circ->n_circ_id = get_unique_circ_id_by_chan(nchan); - circ->n_mux = NULL; /* ?? */ + circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan); cell_queue_init(&(circ->n_chan_cells)); + circ->n_hop = NULL; circ->streams_blocked_on_n_chan = 0; circ->streams_blocked_on_p_chan = 0; @@ -47,14 +51,109 @@ new_fake_orcirc(channel_t *nchan, channel_t *pchan) circ->deliver_window = CIRCWINDOW_START_MAX; circ->n_chan_create_cell = NULL; - orcirc->p_chan = pchan; - orcirc->p_circ_id = get_unique_circ_id_by_chan(pchan); + circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan); cell_queue_init(&(orcirc->p_chan_cells)); return orcirc; } static void +assert_circuit_ok_mock(const circuit_t *c) +{ + (void) c; + return; +} + +static void +test_relay_close_circuit(void *arg) +{ + channel_t *nchan = NULL, *pchan = NULL; + or_circuit_t *orcirc = NULL; + cell_t *cell = NULL; + int old_count, new_count; + + (void)arg; + + /* Make fake channels to be nchan and pchan for the circuit */ + nchan = new_fake_channel(); + tt_assert(nchan); + + pchan = new_fake_channel(); + tt_assert(pchan); + + /* Make a fake orcirc */ + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc), + CELL_DIRECTION_OUT); + circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc), + CELL_DIRECTION_IN); + + /* Make a cell */ + cell = tor_malloc_zero(sizeof(cell_t)); + make_fake_cell(cell); + + MOCK(scheduler_channel_has_waiting_cells, + scheduler_channel_has_waiting_cells_mock); + MOCK(assert_circuit_ok, + assert_circuit_ok_mock); + + /* Append it */ + old_count = get_mock_scheduler_has_waiting_cells_count(); + append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell, + CELL_DIRECTION_OUT, 0); + new_count = get_mock_scheduler_has_waiting_cells_count(); + tt_int_op(new_count, OP_EQ, old_count + 1); + + /* Now try the reverse direction */ + old_count = get_mock_scheduler_has_waiting_cells_count(); + append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell, + CELL_DIRECTION_IN, 0); + new_count = get_mock_scheduler_has_waiting_cells_count(); + tt_int_op(new_count, OP_EQ, old_count + 1); + + /* Ensure our write totals are 0 */ + tt_u64_op(find_largest_max(write_array), OP_EQ, 0); + + /* Mark the circuit for close */ + circuit_mark_for_close(TO_CIRCUIT(orcirc), 0); + + /* Check our write totals. */ + advance_obs(write_array); + commit_max(write_array); + /* Check for two cells plus overhead */ + tt_u64_op(find_largest_max(write_array), OP_EQ, + 2*(get_cell_network_size(nchan->wide_circ_ids) + +TLS_PER_CELL_OVERHEAD)); + + UNMOCK(scheduler_channel_has_waiting_cells); + + /* Get rid of the fake channels */ + MOCK(scheduler_release_channel, scheduler_release_channel_mock); + channel_mark_for_close(nchan); + channel_mark_for_close(pchan); + UNMOCK(scheduler_release_channel); + + /* Shut down channels */ + channel_free_all(); + + done: + tor_free(cell); + if (orcirc) { + circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc)); + circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc)); + cell_queue_clear(&orcirc->base_.n_chan_cells); + cell_queue_clear(&orcirc->p_chan_cells); + } + tor_free(orcirc); + free_fake_channel(nchan); + free_fake_channel(pchan); + UNMOCK(assert_circuit_ok); + + return; +} + +static void test_relay_append_cell_to_circuit_queue(void *arg) { channel_t *nchan = NULL, *pchan = NULL; @@ -129,5 +228,7 @@ test_relay_append_cell_to_circuit_queue(void *arg) struct testcase_t relay_tests[] = { { "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue, TT_FORK, NULL, NULL }, + { "close_circ_rephist", test_relay_close_circuit, + TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c index a6c152f738..3d3addfb9e 100644 --- a/src/test/test_relaycell.c +++ b/src/test/test_relaycell.c @@ -5,22 +5,31 @@ #define RELAY_PRIVATE #define CIRCUITLIST_PRIVATE +#define CONNECTION_EDGE_PRIVATE +#define CONNECTION_PRIVATE + #include "core/or/or.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "app/config/config.h" #include "core/mainloop/connection.h" #include "lib/crypt_ops/crypto_cipher.h" +#include "lib/crypt_ops/crypto_rand.h" #include "core/or/circuitbuild.h" #include "core/or/circuitlist.h" #include "core/or/connection_edge.h" #include "core/or/relay.h" #include "test/test.h" +#include "test/log_test_helpers.h" #include "core/or/cell_st.h" #include "core/or/crypt_path_st.h" #include "core/or/entry_connection_st.h" #include "core/or/origin_circuit_st.h" #include "core/or/socks_request_st.h" +#include "core/or/half_edge_st.h" + +#include "feature/client/circpathbias.h" +#include "core/or/connection_edge.h" static int srm_ncalls; static entry_connection_t *srm_conn; @@ -31,11 +40,6 @@ static uint8_t srm_answer[512]; static int srm_ttl; static time_t srm_expires; -void connection_free_minimal(connection_t*); -int connected_cell_format_payload(uint8_t *payload_out, - const tor_addr_t *addr, - uint32_t ttl); - /* Mock replacement for connection_ap_hannshake_socks_resolved() */ static void socks_resolved_mock(entry_connection_t *conn, @@ -108,6 +112,16 @@ mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason, } static void +mock_mark_circ_for_close(circuit_t *circ, int reason, int line, + const char *file) +{ + (void)reason; (void)line; (void)file; + + circ->marked_for_close = 1; + return; +} + +static void mock_mark_for_close(connection_t *conn, int line, const char *file) { @@ -125,19 +139,38 @@ mock_start_reading(connection_t *conn) return; } -static void -test_circbw_relay(void *arg) +static int +mock_send_command(streamid_t stream_id, circuit_t *circ, + uint8_t relay_command, const char *payload, + size_t payload_len, crypt_path_t *cpath_layer, + const char *filename, int lineno) +{ + (void)stream_id; (void)circ; + (void)relay_command; (void)payload; + (void)payload_len; (void)cpath_layer; + (void)filename; (void)lineno; + + return 0; +} + +static entry_connection_t * +fake_entry_conn(origin_circuit_t *oncirc, streamid_t id) { - cell_t cell; - relay_header_t rh; - tor_addr_t addr; edge_connection_t *edgeconn; entry_connection_t *entryconn; - origin_circuit_t *circ; - int delivered = 0; - int overhead = 0; - (void)arg; + entryconn = entry_connection_new(CONN_TYPE_AP, AF_INET); + edgeconn = ENTRY_TO_EDGE_CONN(entryconn); + edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT; + edgeconn->deliver_window = STREAMWINDOW_START; + edgeconn->package_window = STREAMWINDOW_START; + + edgeconn->stream_id = id; + edgeconn->on_circuit = TO_CIRCUIT(oncirc); + edgeconn->cpath_layer = oncirc->cpath; + + return entryconn; +} #define PACK_CELL(id, cmd, body_s) do { \ memset(&cell, 0, sizeof(cell)); \ @@ -160,18 +193,521 @@ test_circbw_relay(void *arg) tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, overhead); \ } while (0) +static int +subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) +{ + cell_t cell; + relay_header_t rh; + edge_connection_t *edgeconn; + entry_connection_t *entryconn2=NULL; + entry_connection_t *entryconn3=NULL; + entry_connection_t *entryconn4=NULL; + int delivered = circ->n_delivered_read_circ_bw; + int overhead = circ->n_overhead_read_circ_bw; + + /* Make new entryconns */ + entryconn2 = fake_entry_conn(circ, init_id); + entryconn2->socks_request->has_finished = 1; + entryconn3 = fake_entry_conn(circ, init_id+1); + entryconn3->socks_request->has_finished = 1; + entryconn4 = fake_entry_conn(circ, init_id+2); + entryconn4->socks_request->has_finished = 1; + edgeconn = ENTRY_TO_EDGE_CONN(entryconn2); + edgeconn->package_window = 23; + edgeconn->base_.state = AP_CONN_STATE_OPEN; + + int data_cells = edgeconn->deliver_window; + int sendme_cells = (STREAMWINDOW_START-edgeconn->package_window) + /STREAMWINDOW_INCREMENT; + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + connection_edge_reached_eof(edgeconn); + + /* Data cell not in the half-opened list */ + PACK_CELL(4000, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Sendme cell not in the half-opened list */ + PACK_CELL(4000, RELAY_COMMAND_SENDME, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Connected cell not in the half-opened list */ + PACK_CELL(4000, RELAY_COMMAND_CONNECTED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Resolved cell not in the half-opened list */ + PACK_CELL(4000, RELAY_COMMAND_RESOLVED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Connected cell: not counted -- we were open */ + edgeconn = ENTRY_TO_EDGE_CONN(entryconn2); + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* DATA cells up to limit */ + while (data_cells > 0) { + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + data_cells--; + } + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* SENDME cells up to limit */ + while (sendme_cells > 0) { + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + sendme_cells--; + } + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Only one END cell */ + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn2)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + edgeconn = ENTRY_TO_EDGE_CONN(entryconn3); + edgeconn->base_.state = AP_CONN_STATE_OPEN; + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + /* sendme cell on open entryconn with full window */ + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); + int ret = + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + tt_int_op(ret, OP_EQ, -END_CIRC_REASON_TORPROTOCOL); + ASSERT_UNCOUNTED_BW(); + + /* connected cell on a after EOF */ + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT; + connection_edge_reached_eof(edgeconn); + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* DATA and SENDME after END cell */ + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); + ret = + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + tt_int_op(ret, OP_NE, -END_CIRC_REASON_TORPROTOCOL); + ASSERT_UNCOUNTED_BW(); + + ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn3)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Resolved: 1 counted, more not */ + edgeconn = ENTRY_TO_EDGE_CONN(entryconn4); + entryconn4->socks_request->command = SOCKS_COMMAND_RESOLVE; + edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT; + edgeconn->on_circuit = TO_CIRCUIT(circ); + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + connection_edge_reached_eof(edgeconn); + + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED, + "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_COUNTED_BW(); + + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED, + "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Data not counted after resolved */ + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* End not counted after resolved */ + ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn4)->outbuf_flushlen = 0; + PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); + if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + else + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + connection_free_minimal(ENTRY_TO_CONN(entryconn2)); + connection_free_minimal(ENTRY_TO_CONN(entryconn3)); + connection_free_minimal(ENTRY_TO_CONN(entryconn4)); + return 1; + done: + connection_free_minimal(ENTRY_TO_CONN(entryconn2)); + connection_free_minimal(ENTRY_TO_CONN(entryconn3)); + connection_free_minimal(ENTRY_TO_CONN(entryconn4)); + return 0; +} + +static int +halfstream_insert(origin_circuit_t *circ, edge_connection_t *edgeconn, + streamid_t *streams, int num, int random) +{ + int inserted = 0; + + /* Insert num random elements */ + while (inserted < num) { + streamid_t id; + + if (random) + id = (streamid_t)crypto_rand_int(65535)+1; + else + id = get_unique_stream_id_by_circ(circ); + + edgeconn->stream_id = id; + + /* Ensure it isn't there */ + if (connection_half_edge_find_stream_id(circ->half_streams, id)) { + continue; + } + + connection_half_edge_add(edgeconn, circ); + if (streams) + streams[inserted] = id; + inserted++; + } + + return inserted; +} + +static void +subtest_halfstream_insertremove(int num) +{ + origin_circuit_t *circ = + helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0); + edge_connection_t *edgeconn; + entry_connection_t *entryconn; + streamid_t *streams = tor_malloc_zero(num*sizeof(streamid_t)); + int i = 0; + + circ->cpath->state = CPATH_STATE_AWAITING_KEYS; + circ->cpath->deliver_window = CIRCWINDOW_START; + + entryconn = fake_entry_conn(circ, 23); + edgeconn = ENTRY_TO_EDGE_CONN(entryconn); + + /* Explicity test all operations on an absent stream list */ + tt_int_op(connection_half_edge_is_valid_data(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 23), OP_EQ, 0); + + /* Insert a duplicate element; verify that other elements absent; + * ensure removing it once works */ + edgeconn->stream_id = 23; + connection_half_edge_add(edgeconn, circ); + connection_half_edge_add(edgeconn, circ); + connection_half_edge_add(edgeconn, circ); + + /* Verify that other elements absent */ + tt_int_op(connection_half_edge_is_valid_data(circ->half_streams, + 22), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams, + 22), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams, + 22), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams, + 22), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 22), OP_EQ, 0); + + tt_int_op(connection_half_edge_is_valid_data(circ->half_streams, + 24), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams, + 24), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams, + 24), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams, + 24), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 24), OP_EQ, 0); + + /* Verify we only remove it once */ + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 23), OP_EQ, 1); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 23), OP_EQ, 0); + + halfstream_insert(circ, edgeconn, streams, num, 1); + + /* Remove half of them */ + for (i = 0; i < num/2; i++) { + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + streams[i]), + OP_EQ, 1); + } + + /* Verify first half of list is gone */ + for (i = 0; i < num/2; i++) { + tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams, + streams[i]), + OP_EQ, NULL); + } + + /* Verify second half of list is present */ + for (; i < num; i++) { + tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams, + streams[i]), + OP_NE, NULL); + } + + /* Remove other half. Verify list is empty. */ + for (i = num/2; i < num; i++) { + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + streams[i]), + OP_EQ, 1); + } + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 0); + + /* Explicity test all operations on an empty stream list */ + tt_int_op(connection_half_edge_is_valid_data(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams, + 23), OP_EQ, 0); + tt_int_op(connection_half_edge_is_valid_end(circ->half_streams, + 23), OP_EQ, 0); + + /* For valgrind, leave some around then free the circ */ + halfstream_insert(circ, edgeconn, NULL, 10, 0); + + done: + tor_free(streams); + circuit_free_(TO_CIRCUIT(circ)); + connection_free_minimal(ENTRY_TO_CONN(entryconn)); +} + +static void +test_halfstream_insertremove(void *arg) +{ + (void)arg; + + /* Suppress the WARN message we generate in this test */ + setup_full_capture_of_logs(LOG_WARN); + + /* Test insertion and removal with a few different sizes */ + subtest_halfstream_insertremove(10); + subtest_halfstream_insertremove(100); + subtest_halfstream_insertremove(1000); +} + +static void +test_halfstream_wrap(void *arg) +{ + origin_circuit_t *circ = + helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0); + edge_connection_t *edgeconn; + entry_connection_t *entryconn; + + circ->cpath->state = CPATH_STATE_AWAITING_KEYS; + circ->cpath->deliver_window = CIRCWINDOW_START; + + entryconn = fake_entry_conn(circ, 23); + edgeconn = ENTRY_TO_EDGE_CONN(entryconn); + + (void)arg; + + /* Suppress the WARN message we generate in this test */ + setup_full_capture_of_logs(LOG_WARN); + MOCK(connection_mark_for_close_internal_, mock_mark_for_close); + + /* Verify that get_unique_stream_id_by_circ() can wrap uint16_t */ + circ->next_stream_id = 65530; + halfstream_insert(circ, edgeconn, NULL, 7, 0); + tt_int_op(circ->next_stream_id, OP_EQ, 2); + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 7); + + /* Insert full-1 */ + halfstream_insert(circ, edgeconn, NULL, + 65534-smartlist_len(circ->half_streams), 0); + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534); + + /* Verify that we can get_unique_stream_id_by_circ() successfully */ + edgeconn->stream_id = get_unique_stream_id_by_circ(circ); + tt_int_op(edgeconn->stream_id, OP_NE, 0); /* 0 is failure */ + + /* Insert an opened stream on the circ with that id */ + ENTRY_TO_CONN(entryconn)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn)->outbuf_flushlen = 0; + edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT; + circ->p_streams = edgeconn; + + /* Verify that get_unique_stream_id_by_circ() fails */ + tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */ + + /* eof the one opened stream. Verify it is now in half-closed */ + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534); + connection_edge_reached_eof(edgeconn); + tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65535); + + /* Verify get_unique_stream_id_by_circ() fails due to full half-closed */ + circ->p_streams = NULL; + tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */ + + done: + circuit_free_(TO_CIRCUIT(circ)); + connection_free_minimal(ENTRY_TO_CONN(entryconn)); + UNMOCK(connection_mark_for_close_internal_); +} + +static void +test_circbw_relay(void *arg) +{ + cell_t cell; + relay_header_t rh; + tor_addr_t addr; + edge_connection_t *edgeconn; + entry_connection_t *entryconn1=NULL; + origin_circuit_t *circ; + int delivered = 0; + int overhead = 0; + + (void)arg; + MOCK(connection_mark_unattached_ap_, mock_connection_mark_unattached_ap_); MOCK(connection_start_reading, mock_start_reading); MOCK(connection_mark_for_close_internal_, mock_mark_for_close); + MOCK(relay_send_command_from_edge_, mock_send_command); + MOCK(circuit_mark_for_close_, mock_mark_circ_for_close); - entryconn = entry_connection_new(CONN_TYPE_AP, AF_INET); - edgeconn = ENTRY_TO_EDGE_CONN(entryconn); - edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT; - edgeconn->deliver_window = 1000; circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0); - edgeconn->cpath_layer = circ->cpath; circ->cpath->state = CPATH_STATE_AWAITING_KEYS; - circ->cpath->deliver_window = 1000; + circ->cpath->deliver_window = CIRCWINDOW_START; + + entryconn1 = fake_entry_conn(circ, 1); + edgeconn = ENTRY_TO_EDGE_CONN(entryconn1); /* Stream id 0: Not counted */ PACK_CELL(0, RELAY_COMMAND_END, "Data1234"); @@ -197,7 +733,7 @@ test_circbw_relay(void *arg) /* Properly formatted resolved cell in correct state: counted */ edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT; - entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE; + entryconn1->socks_request->command = SOCKS_COMMAND_RESOLVE; edgeconn->on_circuit = TO_CIRCUIT(circ); PACK_CELL(1, RELAY_COMMAND_RESOLVED, "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); @@ -206,7 +742,7 @@ test_circbw_relay(void *arg) ASSERT_COUNTED_BW(); edgeconn->base_.state = AP_CONN_STATE_OPEN; - entryconn->socks_request->has_finished = 1; + entryconn1->socks_request->has_finished = 1; /* Connected cell after open: not counted */ PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234"); @@ -227,42 +763,43 @@ test_circbw_relay(void *arg) ASSERT_UNCOUNTED_BW(); /* Data cell on stream 0: not counted */ - PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234"); + PACK_CELL(0, RELAY_COMMAND_DATA, "Data1234"); connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Data cell on open connection: counted */ - ENTRY_TO_CONN(entryconn)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn1)->marked_for_close = 0; PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234"); connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Empty Data cell on open connection: not counted */ - ENTRY_TO_CONN(entryconn)->marked_for_close = 0; + ENTRY_TO_CONN(entryconn1)->marked_for_close = 0; PACK_CELL(1, RELAY_COMMAND_DATA, ""); connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme on valid stream: counted */ - ENTRY_TO_CONN(entryconn)->outbuf_flushlen = 0; + edgeconn->package_window -= STREAMWINDOW_INCREMENT; + ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0; PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Sendme on valid stream with full window: not counted */ - ENTRY_TO_CONN(entryconn)->outbuf_flushlen = 0; + ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0; PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); - edgeconn->package_window = 500; + edgeconn->package_window = STREAMWINDOW_START; connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme on unknown stream: not counted */ - ENTRY_TO_CONN(entryconn)->outbuf_flushlen = 0; + ENTRY_TO_CONN(entryconn1)->outbuf_flushlen = 0; PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, circ->cpath); @@ -281,18 +818,6 @@ test_circbw_relay(void *arg) circ->cpath); ASSERT_COUNTED_BW(); - /* End cell on non-closed connection: counted */ - PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, - circ->cpath); - ASSERT_COUNTED_BW(); - - /* End cell on connection that already got one: not counted */ - PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, - circ->cpath); - ASSERT_UNCOUNTED_BW(); - /* Invalid extended cell: not counted */ PACK_CELL(1, RELAY_COMMAND_EXTENDED2, "Data1234"); connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, @@ -318,12 +843,40 @@ test_circbw_relay(void *arg) circ->cpath); ASSERT_COUNTED_BW(); + /* End cell on non-closed connection: counted */ + PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + circ->cpath); + ASSERT_COUNTED_BW(); + + /* End cell on connection that already got one: not counted */ + PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); + connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + circ->cpath); + ASSERT_UNCOUNTED_BW(); + + /* Simulate closed stream on entryconn, then test: */ + if (!subtest_circbw_halfclosed(circ, 2)) + goto done; + + circ->base_.purpose = CIRCUIT_PURPOSE_PATH_BIAS_TESTING; + if (!subtest_circbw_halfclosed(circ, 6)) + goto done; + + /* Path bias: truncated */ + tt_int_op(circ->base_.marked_for_close, OP_EQ, 0); + PACK_CELL(0, RELAY_COMMAND_TRUNCATED, "Data1234"); + pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + tt_int_op(circ->base_.marked_for_close, OP_EQ, 1); + done: UNMOCK(connection_start_reading); UNMOCK(connection_mark_unattached_ap_); UNMOCK(connection_mark_for_close_internal_); + UNMOCK(relay_send_command_from_edge_); + UNMOCK(circuit_mark_for_close_); circuit_free_(TO_CIRCUIT(circ)); - connection_free_minimal(ENTRY_TO_CONN(entryconn)); + connection_free_minimal(ENTRY_TO_CONN(entryconn1)); } /* Tests for connection_edge_process_resolved_cell(). @@ -511,6 +1064,7 @@ test_relaycell_resolved(void *arg) struct testcase_t relaycell_tests[] = { { "resolved", test_relaycell_resolved, TT_FORK, NULL, NULL }, { "circbw", test_circbw_relay, TT_FORK, NULL, NULL }, + { "halfstream", test_halfstream_insertremove, TT_FORK, NULL, NULL }, + { "streamwrap", test_halfstream_wrap, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; - diff --git a/src/test/test_router.c b/src/test/test_router.c index 533135669f..921ec42904 100644 --- a/src/test/test_router.c +++ b/src/test/test_router.c @@ -9,7 +9,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "feature/hibernate/hibernate.h" #include "feature/nodelist/routerinfo_st.h" #include "feature/nodelist/routerlist.h" diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c index b62aea113e..f05401ba0d 100644 --- a/src/test/test_routerkeys.c +++ b/src/test/test_routerkeys.c @@ -11,6 +11,7 @@ #include "feature/relay/routerkeys.h" #include "lib/crypt_ops/crypto_cipher.h" #include "lib/crypt_ops/crypto_format.h" +#include "feature/keymgt/loadkey.h" #include "feature/nodelist/torcert.h" #include "test/test.h" diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c index e7c577cf66..1071a095fe 100644 --- a/src/test/test_routerlist.c +++ b/src/test/test_routerlist.c @@ -6,19 +6,21 @@ #include <time.h> #define CONNECTION_PRIVATE -#define DIRECTORY_PRIVATE +#define DIRCLIENT_PRIVATE #define DIRVOTE_PRIVATE #define ENTRYNODES_PRIVATE #define HIBERNATE_PRIVATE #define NETWORKSTATUS_PRIVATE #define ROUTERLIST_PRIVATE +#define NODE_SELECT_PRIVATE #define TOR_UNIT_TESTING #include "core/or/or.h" #include "app/config/config.h" #include "core/mainloop/connection.h" #include "feature/control/control.h" #include "lib/crypt_ops/crypto_rand.h" -#include "feature/dircache/directory.h" +#include "feature/dircommon/directory.h" +#include "feature/dirclient/dirclient.h" #include "feature/dirauth/dirvote.h" #include "feature/client/entrynodes.h" #include "feature/hibernate/hibernate.h" @@ -27,9 +29,12 @@ #include "feature/nodelist/nodelist.h" #include "core/or/policies.h" #include "feature/relay/router.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/node_select.h" #include "feature/nodelist/routerlist.h" #include "feature/nodelist/routerset.h" -#include "feature/nodelist/routerparse.h" +#include "feature/dirparse/authcert_parse.h" +#include "feature/dirparse/ns_parse.h" #include "feature/dirauth/shared_random.h" #include "app/config/statefile.h" diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c index 2017ef0050..86f9c0fa82 100644 --- a/src/test/test_routerset.c +++ b/src/test/test_routerset.c @@ -4,11 +4,11 @@ #define ROUTERSET_PRIVATE #include "core/or/or.h" -#include "feature/stats/geoip.h" -#include "feature/nodelist/routerset.h" -#include "feature/nodelist/routerparse.h" #include "core/or/policies.h" +#include "feature/dirparse/policy_parse.h" #include "feature/nodelist/nodelist.h" +#include "feature/nodelist/routerset.h" +#include "lib/geoip/geoip.h" #include "core/or/addr_policy_st.h" #include "core/or/extend_info_st.h" @@ -1496,6 +1496,7 @@ NS(test_main)(void *arg) int r; (void)arg; + memset(&NS(mock_node), 0, sizeof(NS(mock_node))); NS(mock_node).ri = NULL; NS(mock_node).rs = NULL; @@ -1529,6 +1530,7 @@ NS(test_main)(void *arg) strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); rs.nickname[sizeof(rs.nickname) - 1] = '\0'; + memset(&NS(mock_node), 0, sizeof(NS(mock_node))); NS(mock_node).ri = NULL; NS(mock_node).rs = &rs; @@ -1560,6 +1562,7 @@ NS(test_main)(void *arg) strmap_set_lc(set->names, nickname, (void *)1); ri.nickname = (char *)nickname; + memset(&mock_node, 0, sizeof(mock_node)); mock_node.ri = &ri; mock_node.rs = NULL; diff --git a/src/test/test_rust.sh b/src/test/test_rust.sh index 4afc84285f..00b3e88d37 100755 --- a/src/test/test_rust.sh +++ b/src/test/test_rust.sh @@ -5,11 +5,20 @@ set -e export LSAN_OPTIONS=suppressions=${abs_top_srcdir:-../../..}/src/test/rust_supp.txt +# When testing Cargo we pass a number of very specific linker flags down +# through Cargo. We do not, however, want these flags to affect things like +# build scripts, only the tests that we're compiling. To ensure this happens +# we unconditionally pass `--target` into Cargo, ensuring that `RUSTFLAGS` in +# the environment won't make their way into build scripts. +rustc_host=$(rustc -vV | grep host | sed 's/host: //') + for cargo_toml_dir in "${abs_top_srcdir:-../../..}"/src/rust/*; do if [ -e "${cargo_toml_dir}/Cargo.toml" ]; then cd "${abs_top_builddir:-../../..}/src/rust" && \ CARGO_TARGET_DIR="${abs_top_builddir:-../../..}/src/rust/target" \ "${CARGO:-cargo}" test ${CARGO_ONLINE-"--frozen"} \ + --features "test_linking_hack" \ + --target $rustc_host \ ${EXTRA_CARGO_OPTIONS} \ --manifest-path "${cargo_toml_dir}/Cargo.toml" || exitcode=1 fi diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c index 2043613641..433661f128 100644 --- a/src/test/test_shared_random.c +++ b/src/test/test_shared_random.c @@ -17,8 +17,9 @@ #include "feature/nodelist/networkstatus.h" #include "feature/relay/router.h" #include "feature/relay/routerkeys.h" -#include "feature/nodelist/routerlist.h" -#include "feature/nodelist/routerparse.h" +#include "feature/nodelist/authcert.h" +#include "feature/nodelist/dirlist.h" +#include "feature/dirparse/authcert_parse.h" #include "feature/hs_common/shared_random_client.h" #include "feature/dircommon/voting_schedule.h" diff --git a/src/test/test_status.c b/src/test/test_status.c index 15c406d2ff..3ceba77a84 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -21,7 +21,8 @@ #include "feature/stats/rephist.h" #include "core/or/relay.h" #include "feature/relay/router.h" -#include "core/mainloop/main.h" +#include "feature/relay/routermode.h" +#include "core/mainloop/mainloop.h" #include "feature/nodelist/nodelist.h" #include "app/config/statefile.h" #include "lib/tls/tortls.h" diff --git a/src/test/test_storagedir.c b/src/test/test_storagedir.c index 68cee418ad..76aae7e033 100644 --- a/src/test/test_storagedir.c +++ b/src/test/test_storagedir.c @@ -283,7 +283,7 @@ test_storagedir_save_labeled(void *arg) int r = storage_dir_save_labeled_to_file(d, labels, inp, 8192, &fname); tt_int_op(r, OP_EQ, 0); - size_t n; + size_t n = 0; saved = storage_dir_read(d, fname, 1, &n); tt_assert(memchr(saved, '\0', n)); tt_str_op((char*)saved, OP_EQ, expected); /* NUL guarantees strcmp works */ diff --git a/src/test/test_threads.c b/src/test/test_threads.c index f0a4dd2057..2bf5026061 100644 --- a/src/test/test_threads.c +++ b/src/test/test_threads.c @@ -234,25 +234,33 @@ test_threads_conditionvar(void *arg) if (timeout) { ti->tv = &msec100; } + +#define SPIN_UNTIL(condition,sleep_msec) \ + while (1) { \ + tor_mutex_acquire(ti->mutex); \ + if (condition) { \ + break; \ + } \ + tor_mutex_release(ti->mutex); \ + tor_sleep_msec(sleep_msec); \ + } + spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); spawn_func(cv_test_thr_fn_, ti); - tor_mutex_acquire(ti->mutex); + SPIN_UNTIL(ti->n_threads == 4, 10); + + time_t started_at = time(NULL); + ti->addend = 7; ti->shutdown = 1; tor_cond_signal_one(ti->cond); tor_mutex_release(ti->mutex); #define SPIN() \ - while (1) { \ - tor_mutex_acquire(ti->mutex); \ - if (ti->addend == 0) { \ - break; \ - } \ - tor_mutex_release(ti->mutex); \ - } + SPIN_UNTIL(ti->addend == 0, 0) SPIN(); @@ -279,8 +287,9 @@ test_threads_conditionvar(void *arg) if (!timeout) { tt_int_op(ti->n_shutdown, OP_EQ, 4); } else { - tor_sleep_msec(200); - tor_mutex_acquire(ti->mutex); + const int GIVE_UP_AFTER_SEC = 30; + SPIN_UNTIL((ti->n_timeouts == 2 || + time(NULL) >= started_at + GIVE_UP_AFTER_SEC), 10); tt_int_op(ti->n_shutdown, OP_EQ, 2); tt_int_op(ti->n_timeouts, OP_EQ, 2); tor_mutex_release(ti->mutex); @@ -301,4 +310,3 @@ struct testcase_t thread_tests[] = { &passthrough_setup, (void*)"tv" }, END_OF_TESTCASES }; - diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c index f4315364a2..79b52437f8 100644 --- a/src/test/test_tortls.c +++ b/src/test/test_tortls.c @@ -238,6 +238,7 @@ test_tortls_x509_cert_get_id_digests(void *ignored) cert->pkey_digests_set = 1; cert->pkey_digests = *d; res = tor_x509_cert_get_id_digests(cert); + tt_assert(res); tt_int_op(res->d[0][0], OP_EQ, 42); done: diff --git a/src/test/test_tortls_openssl.c b/src/test/test_tortls_openssl.c index 6086252882..abe1fb7889 100644 --- a/src/test/test_tortls_openssl.c +++ b/src/test/test_tortls_openssl.c @@ -1007,6 +1007,7 @@ test_tortls_try_to_extract_certs_from_tls(void *ignored) tt_assert(cert == c1); tt_assert(id_cert); X509_free(cert); /* decrease refcnt */ + X509_free(id_cert); /* decrease refcnt */ done: sk_X509_free(sess->cert_chain); @@ -1848,16 +1849,44 @@ fixed_tor_tls_create_certificate(crypto_pk_t *rsa, (void)cname; (void)cname_sign; (void)cert_lifetime; - return fixed_tor_tls_create_certificate_result[ + X509 *result = fixed_tor_tls_create_certificate_result[ fixed_tor_tls_create_certificate_result_index++]; + if (result) + return X509_dup(result); + else + return NULL; +} + +static void +fixed_tor_tls_create_certificate_results_free(void) +{ + unsigned i; + for (i = 0; i < ARRAY_LENGTH(fixed_tor_tls_create_certificate_result); ++i) { + X509 *cert = fixed_tor_tls_create_certificate_result[i]; + if (cert) + X509_free(cert); + fixed_tor_tls_create_certificate_result[i] = NULL; + } +} + +static void +fixed_tor_x509_cert_new_results_free(void) +{ + unsigned i; + for (i = 0; i < ARRAY_LENGTH(fixed_tor_x509_cert_new_result); ++i) { + tor_x509_cert_free(fixed_tor_x509_cert_new_result[i]); + } } static tor_x509_cert_t * fixed_tor_x509_cert_new(tor_x509_cert_impl_t *x509_cert) { (void) x509_cert; - return fixed_tor_x509_cert_new_result[ - fixed_tor_x509_cert_new_result_index++]; + tor_x509_cert_t **certp = + &fixed_tor_x509_cert_new_result[fixed_tor_x509_cert_new_result_index++]; + tor_x509_cert_t *cert = *certp; + *certp = NULL; + return cert; } static void @@ -1937,6 +1966,7 @@ test_tortls_context_new(void *ignored) fixed_tor_tls_create_certificate_result[2] = X509_new(); ret = tor_tls_context_new(NULL, 0, 0, 0); tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); fixed_crypto_pk_new_result_index = 0; fixed_crypto_pk_new_result[0] = pk7; @@ -1949,6 +1979,7 @@ test_tortls_context_new(void *ignored) fixed_tor_tls_create_certificate_result[2] = X509_new(); ret = tor_tls_context_new(NULL, 0, 0, 0); tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); fixed_crypto_pk_new_result_index = 0; fixed_crypto_pk_new_result[0] = pk9; @@ -1961,6 +1992,7 @@ test_tortls_context_new(void *ignored) fixed_tor_tls_create_certificate_result[2] = NULL; ret = tor_tls_context_new(NULL, 0, 0, 0); tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); MOCK(tor_x509_cert_new, fixed_tor_x509_cert_new); fixed_crypto_pk_new_result_index = 0; @@ -1978,6 +2010,7 @@ test_tortls_context_new(void *ignored) fixed_tor_x509_cert_new_result[2] = NULL; ret = tor_tls_context_new(NULL, 0, 0, 0); tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); fixed_crypto_pk_new_result_index = 0; fixed_crypto_pk_new_result[0] = pk13; @@ -1994,6 +2027,8 @@ test_tortls_context_new(void *ignored) fixed_tor_x509_cert_new_result[2] = NULL; ret = tor_tls_context_new(NULL, 0, 0, 0); tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); + fixed_tor_x509_cert_new_results_free(); fixed_crypto_pk_new_result_index = 0; fixed_crypto_pk_new_result[0] = pk15; @@ -2010,6 +2045,8 @@ test_tortls_context_new(void *ignored) fixed_tor_x509_cert_new_result[2] = NULL; ret = tor_tls_context_new(NULL, 0, 0, 0); tt_assert(!ret); + fixed_tor_tls_create_certificate_results_free(); + fixed_tor_x509_cert_new_results_free(); fixed_crypto_pk_new_result_index = 0; fixed_crypto_pk_new_result[0] = pk17; @@ -2028,6 +2065,8 @@ test_tortls_context_new(void *ignored) tt_assert(!ret); done: + fixed_tor_tls_create_certificate_results_free(); + fixed_tor_x509_cert_new_results_free(); UNMOCK(tor_x509_cert_new); UNMOCK(tor_tls_create_certificate); UNMOCK(crypto_pk_generate_key_with_bits); diff --git a/src/test/test_util.c b/src/test/test_util.c index b5a231dac6..1a71da2794 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -4013,6 +4013,53 @@ test_util_string_is_C_identifier(void *ptr) } static void +test_util_string_is_utf8(void *ptr) +{ + (void)ptr; + + tt_int_op(1, OP_EQ, string_is_utf8(NULL, 0)); + tt_int_op(1, OP_EQ, string_is_utf8("", 1)); + tt_int_op(1, OP_EQ, string_is_utf8("\uFEFF", 3)); + tt_int_op(1, OP_EQ, string_is_utf8("\uFFFE", 3)); + tt_int_op(1, OP_EQ, string_is_utf8("ascii\x7f\n", 7)); + tt_int_op(1, OP_EQ, string_is_utf8("Risqu\u00e9=1", 9)); + + // Validate exactly 'len' bytes. + tt_int_op(0, OP_EQ, string_is_utf8("\0\x80", 2)); + tt_int_op(0, OP_EQ, string_is_utf8("Risqu\u00e9=1", 6)); + + // Reject sequences with missing bytes. + tt_int_op(0, OP_EQ, string_is_utf8("\x80", 1)); + tt_int_op(0, OP_EQ, string_is_utf8("\xc2", 1)); + tt_int_op(0, OP_EQ, string_is_utf8("\xc2 ", 2)); + tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80", 2)); + tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80 ", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80 ", 4)); + + // Reject encodings that are overly long. + tt_int_op(0, OP_EQ, string_is_utf8("\xc1\xbf", 2)); + tt_int_op(1, OP_EQ, string_is_utf8("\xc2\x80", 2)); + tt_int_op(0, OP_EQ, string_is_utf8("\xe0\x9f\xbf", 3)); + tt_int_op(1, OP_EQ, string_is_utf8("\xe0\xa0\x80", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xf0\x8f\xbf\xbf", 4)); + tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x80\x80", 4)); + + // Reject UTF-16 surrogate halves. + tt_int_op(1, OP_EQ, string_is_utf8("\xed\x9f\xbf", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x80", 3)); + tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3)); + tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3)); + + // The maximum legal codepoint, 10FFFF. + tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4)); + tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4)); + + done: + ; +} + +static void test_util_asprintf(void *ptr) { #define LOREMIPSUM \ @@ -5761,6 +5808,18 @@ test_util_ipv4_validation(void *arg) } static void +test_util_ipv6_validation(void *arg) +{ + (void)arg; + + tt_assert(string_is_valid_ipv6_address("2a00:1450:401b:800::200e")); + tt_assert(!string_is_valid_ipv6_address("11:22::33:44:")); + + done: + return; +} + +static void test_util_writepid(void *arg) { (void) arg; @@ -6409,6 +6468,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(clamp_double_to_int64, 0), UTIL_TEST(find_str_at_start_of_line, 0), UTIL_TEST(string_is_C_identifier, 0), + UTIL_TEST(string_is_utf8, 0), UTIL_TEST(asprintf, 0), UTIL_TEST(listdir, 0), UTIL_TEST(parent_dir, 0), @@ -6450,6 +6510,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(hostname_validation, 0), UTIL_TEST(dest_validation_edgecase, 0), UTIL_TEST(ipv4_validation, 0), + UTIL_TEST(ipv6_validation, 0), UTIL_TEST(writepid, 0), UTIL_TEST(get_avail_disk_space, 0), UTIL_TEST(touch_file, 0), diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c index 9d48d92773..28fbd6fb9f 100644 --- a/src/test/test_workqueue.c +++ b/src/test/test_workqueue.c @@ -5,7 +5,7 @@ #include "core/or/or.h" #include "lib/thread/threads.h" -#include "core/crypto/onion.h" +#include "core/or/onion.h" #include "lib/evloop/workqueue.h" #include "lib/crypt_ops/crypto_curve25519.h" #include "lib/crypt_ops/crypto_rand.h" diff --git a/src/test/testing_common.c b/src/test/testing_common.c index 5d4c2f15af..c52683afca 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -8,7 +8,7 @@ * \brief Common pieces to implement unit tests. **/ -#define MAIN_PRIVATE +#define MAINLOOP_PRIVATE #include "orconfig.h" #include "core/or/or.h" #include "feature/control/control.h" @@ -16,11 +16,12 @@ #include "lib/crypt_ops/crypto_dh.h" #include "lib/crypt_ops/crypto_ed25519.h" #include "lib/crypt_ops/crypto_rand.h" +#include "feature/stats/predict_ports.h" #include "feature/stats/rephist.h" #include "lib/err/backtrace.h" #include "test/test.h" #include "core/or/channelpadding.h" -#include "core/mainloop/main.h" +#include "core/mainloop/mainloop.h" #include "lib/compress/compress.h" #include "lib/evloop/compat_libevent.h" #include "lib/crypt_ops/crypto_init.h" |