diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/bench.c | 16 | ||||
-rw-r--r-- | src/test/include.am | 6 | ||||
-rw-r--r-- | src/test/test-child.c | 2 | ||||
-rw-r--r-- | src/test/test-memwipe.c | 1 | ||||
-rw-r--r-- | src/test/test.c | 1 | ||||
-rw-r--r-- | src/test/test.h | 1 | ||||
-rw-r--r-- | src/test/test_addr.c | 4 | ||||
-rw-r--r-- | src/test/test_buffers.c | 22 | ||||
-rw-r--r-- | src/test/test_channeltls.c | 2 | ||||
-rw-r--r-- | src/test/test_config.c | 191 | ||||
-rw-r--r-- | src/test/test_containers.c | 16 | ||||
-rw-r--r-- | src/test/test_controller.c | 48 | ||||
-rw-r--r-- | src/test/test_crypto.c | 71 | ||||
-rw-r--r-- | src/test/test_dir.c | 424 | ||||
-rw-r--r-- | src/test/test_entryconn.c | 20 | ||||
-rw-r--r-- | src/test/test_entrynodes.c | 18 | ||||
-rw-r--r-- | src/test/test_hs.c | 210 | ||||
-rw-r--r-- | src/test/test_options.c | 152 | ||||
-rw-r--r-- | src/test/test_policy.c | 8 | ||||
-rw-r--r-- | src/test/test_protover.c | 195 | ||||
-rw-r--r-- | src/test/test_pt.c | 8 | ||||
-rw-r--r-- | src/test/test_routerlist.c | 68 | ||||
-rw-r--r-- | src/test/test_routerset.c | 28 | ||||
-rw-r--r-- | src/test/test_scheduler.c | 3 | ||||
-rw-r--r-- | src/test/test_shared_random.c | 12 | ||||
-rw-r--r-- | src/test/test_status.c | 2 | ||||
-rw-r--r-- | src/test/test_util.c | 103 |
27 files changed, 1493 insertions, 139 deletions
diff --git a/src/test/bench.c b/src/test/bench.c index f373019b95..30984fda70 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -90,7 +90,9 @@ bench_aes(void) uint64_t start, end; const int bytes_per_iter = (1<<24); reset_perftime(); - c = crypto_cipher_new(NULL); + char key[CIPHER_KEY_LEN]; + crypto_rand(key, sizeof(key)); + c = crypto_cipher_new(key); for (len = 1; len <= 8192; len *= 2) { int iters = bytes_per_iter / len; @@ -328,8 +330,9 @@ bench_cell_aes(void) char *b = tor_malloc(len+max_misalign); crypto_cipher_t *c; int i, misalign; - - c = crypto_cipher_new(NULL); + char key[CIPHER_KEY_LEN]; + crypto_rand(key, sizeof(key)); + c = crypto_cipher_new(key); reset_perftime(); for (misalign = 0; misalign <= max_misalign; ++misalign) { @@ -501,8 +504,11 @@ bench_cell_ops(void) or_circ->base_.purpose = CIRCUIT_PURPOSE_OR; /* Initialize crypto */ - or_circ->p_crypto = crypto_cipher_new(NULL); - or_circ->n_crypto = crypto_cipher_new(NULL); + char key1[CIPHER_KEY_LEN], key2[CIPHER_KEY_LEN]; + crypto_rand(key1, sizeof(key1)); + crypto_rand(key2, sizeof(key2)); + or_circ->p_crypto = crypto_cipher_new(key1); + or_circ->n_crypto = crypto_cipher_new(key2); or_circ->p_digest = crypto_digest_new(); or_circ->n_digest = crypto_digest_new(); diff --git a/src/test/include.am b/src/test/include.am index 17491df80e..4af48cfbc1 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -28,9 +28,10 @@ TESTS += src/test/test src/test/test-slow src/test/test-memwipe \ $(TESTSCRIPTS) # These flavors are run using automake's test-driver and test-network.sh -TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-min +TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-min single-onion # only run if we can ping6 ::1 (localhost) -TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-ipv6 +TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-ipv6 \ + single-onion-ipv6 # only run if we can find a stable (or simply another) version of tor TEST_CHUTNEY_FLAVORS_MIXED = mixed @@ -107,6 +108,7 @@ src_test_test_SOURCES = \ src/test/test_options.c \ src/test/test_policy.c \ src/test/test_procmon.c \ + src/test/test_protover.c \ src/test/test_pt.c \ src/test/test_pubsub.c \ src/test/test_relay.c \ diff --git a/src/test/test-child.c b/src/test/test-child.c index e2552a499d..fdf3ccec0a 100644 --- a/src/test/test-child.c +++ b/src/test/test-child.c @@ -1,8 +1,8 @@ /* Copyright (c) 2011-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include <stdio.h> #include "orconfig.h" +#include <stdio.h> #ifdef _WIN32 #define WINDOWS_LEAN_AND_MEAN #include <windows.h> diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c index 8187c45461..21882448c3 100644 --- a/src/test/test-memwipe.c +++ b/src/test/test-memwipe.c @@ -1,3 +1,4 @@ +#include "orconfig.h" #include <string.h> #include <stdio.h> #include <sys/types.h> diff --git a/src/test/test.c b/src/test/test.c index 2f10c7e90b..9a41b976b8 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1214,6 +1214,7 @@ struct testgroup_t testgroups[] = { { "options/", options_tests }, { "policy/" , policy_tests }, { "procmon/", procmon_tests }, + { "protover/", protover_tests }, { "pt/", pt_tests }, { "relay/" , relay_tests }, { "relaycell/", relaycell_tests }, diff --git a/src/test/test.h b/src/test/test.h index bbbc87cd16..b7c769fe0d 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -209,6 +209,7 @@ extern struct testcase_t oos_tests[]; extern struct testcase_t options_tests[]; extern struct testcase_t policy_tests[]; extern struct testcase_t procmon_tests[]; +extern struct testcase_t protover_tests[]; extern struct testcase_t pubsub_tests[]; extern struct testcase_t pt_tests[]; extern struct testcase_t relay_tests[]; diff --git a/src/test/test_addr.c b/src/test/test_addr.c index c8a9e6d384..49e248014f 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -85,8 +85,8 @@ test_addr_basic(void *arg) char *, "%s", \ { char *cp; \ cp = print_ = tor_malloc(64); \ - for (int ii_=0;i<16;++i) { \ - tor_snprintf(cp, 3,"%02x", (unsigned)value_->s6_addr[i]);\ + for (int ii_=0;ii_<16;++ii_) { \ + tor_snprintf(cp, 3,"%02x", (unsigned)value_->s6_addr[ii_]); \ cp += 2; \ if (ii_ != 15) *cp++ = ':'; \ } \ diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index 971dd1d889..3408da3aa9 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -744,6 +744,27 @@ test_buffers_tls_read_mocked(void *arg) buf_free(buf); } +static void +test_buffers_chunk_size(void *arg) +{ + (void)arg; + const int min = 256; + const int max = 65536; + tt_uint_op(preferred_chunk_size(3), OP_EQ, min); + tt_uint_op(preferred_chunk_size(25), OP_EQ, min); + tt_uint_op(preferred_chunk_size(0), OP_EQ, min); + tt_uint_op(preferred_chunk_size(256), OP_EQ, 512); + tt_uint_op(preferred_chunk_size(65400), OP_EQ, max); + /* Here, we're implicitly saying that the chunk header overhead is + * between 1 and 100 bytes. 24..48 would probably be more accurate. */ + tt_uint_op(preferred_chunk_size(65536), OP_GT, 65536); + tt_uint_op(preferred_chunk_size(65536), OP_LT, 65536+100); + tt_uint_op(preferred_chunk_size(165536), OP_GT, 165536); + tt_uint_op(preferred_chunk_size(165536), OP_LT, 165536+100); + done: + ; +} + struct testcase_t buffer_tests[] = { { "basic", test_buffers_basic, TT_FORK, NULL, NULL }, { "copy", test_buffer_copy, TT_FORK, NULL, NULL }, @@ -758,6 +779,7 @@ struct testcase_t buffer_tests[] = { NULL, NULL}, { "tls_read_mocked", test_buffers_tls_read_mocked, 0, NULL, NULL }, + { "chunk_size", test_buffers_chunk_size, 0, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c index 36ae4d16e2..fd98ee40fb 100644 --- a/src/test/test_channeltls.c +++ b/src/test/test_channeltls.c @@ -1,6 +1,8 @@ /* Copyright (c) 2014-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#include "orconfig.h" + #include <math.h> #define TOR_CHANNEL_INTERNAL_ diff --git a/src/test/test_config.c b/src/test/test_config.c index ee1686c65a..384bff410f 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -3710,6 +3710,144 @@ test_config_default_fallback_dirs(void *arg) clear_dir_servers(); } +static void +test_config_port_cfg_line_extract_addrport(void *arg) +{ + (void)arg; + int unixy = 0; + const char *rest = NULL; + char *a = NULL; + + tt_int_op(port_cfg_line_extract_addrport("", &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("hello", &a, &unixy, &rest), + OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "hello");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport(" flipperwalt gersplut", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(rest, OP_EQ, "gersplut"); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport(" flipperwalt \t gersplut", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(rest, OP_EQ, "gersplut"); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("flipperwalt \t gersplut", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(rest, OP_EQ, "gersplut"); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:flipperwalt \t gersplut", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(rest, OP_EQ, "gersplut"); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:lolol ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport(" unix:lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("foobar:lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "foobar:lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport(":lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, ":lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\"", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\" ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\" foo ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, "foo "); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lol ol\" foo ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lol ol");; + tt_str_op(rest, OP_EQ, "foo "); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lol\\\" ol\" foo ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lol\" ol");; + tt_str_op(rest, OP_EQ, "foo "); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lol\\\" ol foo ", + &a, &unixy, &rest), OP_EQ, -1); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lol\\0\" ol foo ", + &a, &unixy, &rest), OP_EQ, -1); + tor_free(a); + + done: + tor_free(a); +} + static config_line_t * mock_config_line(const char *key, const char *val) { @@ -4050,6 +4188,49 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); #endif + // Test success with quoted unix: address. + config_free_lines(config_port_valid); config_port_valid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar\" " + "NoDNSRequest NoIPv4Traffic"); + ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS", + CONN_TYPE_AP_LISTENER, NULL, 0, + CL_PORT_TAKES_HOSTNAMES); +#ifdef _WIN32 + tt_int_op(ret, OP_EQ, -1); +#else + tt_int_op(ret, OP_EQ, 0); + tt_int_op(smartlist_len(slout), OP_EQ, 1); + port_cfg = (port_cfg_t *)smartlist_get(slout, 0); + tt_int_op(port_cfg->entry_cfg.dns_request, OP_EQ, 0); + tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 0); + tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 0); + tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); +#endif + + // Test failure with broken quoted unix: address. + config_free_lines(config_port_valid); config_port_valid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar " + "NoDNSRequest NoIPv4Traffic"); + ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS", + CONN_TYPE_AP_LISTENER, NULL, 0, + CL_PORT_TAKES_HOSTNAMES); + tt_int_op(ret, OP_EQ, -1); + + // Test failure with empty quoted unix: address. + config_free_lines(config_port_valid); config_port_valid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_valid = mock_config_line("SOCKSPort", "unix:\"\" " + "NoDNSRequest NoIPv4Traffic"); + ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS", + CONN_TYPE_AP_LISTENER, NULL, 0, + CL_PORT_TAKES_HOSTNAMES); + tt_int_op(ret, OP_EQ, -1); + // Test success with OnionTrafficOnly (no DNS, no ipv4, no ipv6) config_free_lines(config_port_valid); config_port_valid = NULL; SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); @@ -4690,6 +4871,15 @@ test_config_parse_port_config__ports__server_options(void *data) 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, -1); + // Check for failure with empty unix: address. + config_free_lines(config_port_invalid); config_port_invalid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_invalid = mock_config_line("ORPort", "unix:\"\""); + ret = parse_port_config(slout, config_port_invalid, NULL, "ORPort", 0, NULL, + 0, CL_PORT_SERVER_OPTIONS); + tt_int_op(ret, OP_EQ, -1); + done: if (slout) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); @@ -4719,6 +4909,7 @@ struct testcase_t config_tests[] = { CONFIG_TEST(write_to_data_subdir, TT_FORK), CONFIG_TEST(fix_my_family, 0), CONFIG_TEST(directory_fetch, 0), + CONFIG_TEST(port_cfg_line_extract_addrport, 0), CONFIG_TEST(parse_port_config__listenaddress, 0), CONFIG_TEST(parse_port_config__ports__no_ports_given, 0), CONFIG_TEST(parse_port_config__ports__server_options, 0), diff --git a/src/test/test_containers.c b/src/test/test_containers.c index d8b82e0661..d7291a2ce2 100644 --- a/src/test/test_containers.c +++ b/src/test/test_containers.c @@ -501,13 +501,13 @@ test_container_smartlist_pos(void *arg) (void) arg; smartlist_t *sl = smartlist_new(); - smartlist_add(sl, tor_strdup("This")); - smartlist_add(sl, tor_strdup("is")); - smartlist_add(sl, tor_strdup("a")); - smartlist_add(sl, tor_strdup("test")); - smartlist_add(sl, tor_strdup("for")); - smartlist_add(sl, tor_strdup("a")); - smartlist_add(sl, tor_strdup("function")); + smartlist_add_strdup(sl, "This"); + smartlist_add_strdup(sl, "is"); + smartlist_add_strdup(sl, "a"); + smartlist_add_strdup(sl, "test"); + smartlist_add_strdup(sl, "for"); + smartlist_add_strdup(sl, "a"); + smartlist_add_strdup(sl, "function"); /* Test string_pos */ tt_int_op(smartlist_string_pos(NULL, "Fred"), ==, -1); @@ -830,7 +830,7 @@ test_container_strmap(void *arg) found_keys = smartlist_new(); while (!strmap_iter_done(iter)) { strmap_iter_get(iter,&k,&v); - smartlist_add(found_keys, tor_strdup(k)); + smartlist_add_strdup(found_keys, k); tt_ptr_op(v,OP_EQ, strmap_get(map, k)); if (!strcmp(k, "K2")) { diff --git a/src/test/test_controller.c b/src/test/test_controller.c index 0dea8473b9..f19c846144 100644 --- a/src/test/test_controller.c +++ b/src/test/test_controller.c @@ -137,6 +137,8 @@ test_rend_service_parse_port_config(void *arg) cfg = rend_service_parse_port_config("80,[2001:db8::1]:8080", sep, &err_msg); tt_assert(cfg); tt_assert(!err_msg); + rend_service_port_config_free(cfg); + cfg = NULL; /* XXX: Someone should add tests for AF_UNIX targets if supported. */ @@ -151,6 +153,52 @@ test_rend_service_parse_port_config(void *arg) cfg = rend_service_parse_port_config("90001", sep, &err_msg); tt_assert(!cfg); tt_assert(err_msg); + tor_free(err_msg); + + /* unix port */ + cfg = NULL; + + /* quoted unix port */ + tor_free(err_msg); + cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar\"", + " ", &err_msg); + tt_assert(cfg); + tt_assert(!err_msg); + rend_service_port_config_free(cfg); + cfg = NULL; + + /* quoted unix port */ + tor_free(err_msg); + cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar\"", + " ", &err_msg); + tt_assert(cfg); + tt_assert(!err_msg); + rend_service_port_config_free(cfg); + cfg = NULL; + + /* quoted unix port, missing end quote */ + cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar", + " ", &err_msg); + tt_assert(!cfg); + tt_str_op(err_msg, OP_EQ, "Couldn't process address <unix:\"/tmp/foo bar> " + "from hidden service configuration"); + tor_free(err_msg); + + /* bogus IP address */ + cfg = rend_service_parse_port_config("100 1.2.3.4.5:9000", + " ", &err_msg); + tt_assert(!cfg); + tt_str_op(err_msg, OP_EQ, "Unparseable address in hidden service port " + "configuration."); + tor_free(err_msg); + + /* bogus port port */ + cfg = rend_service_parse_port_config("100 99999", + " ", &err_msg); + tt_assert(!cfg); + tt_str_op(err_msg, OP_EQ, "Unparseable or out-of-range port \"99999\" " + "in hidden service port configuration."); + tor_free(err_msg); done: rend_service_port_config_free(cfg); diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index d83b93be58..64a46f7914 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -363,15 +363,15 @@ test_crypto_rng_engine(void *arg) ; } -/** Run unit tests for our AES functionality */ +/** Run unit tests for our AES128 functionality */ static void -test_crypto_aes(void *arg) +test_crypto_aes128(void *arg) { char *data1 = NULL, *data2 = NULL, *data3 = NULL; crypto_cipher_t *env1 = NULL, *env2 = NULL; int i, j; char *mem_op_hex_tmp=NULL; - + char key[CIPHER_KEY_LEN]; int use_evp = !strcmp(arg,"evp"); evaluate_evp_for_aes(use_evp); evaluate_ctr_for_aes(); @@ -387,9 +387,10 @@ test_crypto_aes(void *arg) memset(data2, 0, 1024); memset(data3, 0, 1024); - env1 = crypto_cipher_new(NULL); + crypto_rand(key, sizeof(key)); + env1 = crypto_cipher_new(key); tt_ptr_op(env1, OP_NE, NULL); - env2 = crypto_cipher_new(crypto_cipher_get_key(env1)); + env2 = crypto_cipher_new(key); tt_ptr_op(env2, OP_NE, NULL); /* Try encrypting 512 chars. */ @@ -420,7 +421,7 @@ test_crypto_aes(void *arg) env2 = NULL; memset(data3, 0, 1024); - env2 = crypto_cipher_new(crypto_cipher_get_key(env1)); + env2 = crypto_cipher_new(key); tt_ptr_op(env2, OP_NE, NULL); for (j = 0; j < 1024-16; j += 17) { crypto_cipher_encrypt(env2, data3+j, data1+j, 17); @@ -513,32 +514,61 @@ test_crypto_aes(void *arg) static void test_crypto_aes_ctr_testvec(void *arg) { - (void)arg; + const char *bitstr = arg; char *mem_op_hex_tmp=NULL; + crypto_cipher_t *c=NULL; /* from NIST SP800-38a, section F.5 */ - const char key16[] = "2b7e151628aed2a6abf7158809cf4f3c"; const char ctr16[] = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; const char plaintext16[] = "6bc1bee22e409f96e93d7e117393172a" "ae2d8a571e03ac9c9eb76fac45af8e51" "30c81c46a35ce411e5fbc1191a0a52ef" "f69f2445df4f9b17ad2b417be66c3710"; - const char ciphertext16[] = - "874d6191b620e3261bef6864990db6ce" - "9806f66b7970fdff8617187bb9fffdff" - "5ae4df3edbd5d35e5b4f09020db03eab" - "1e031dda2fbe03d1792170a0f3009cee"; + const char *ciphertext16; + const char *key16; + int bits; + + if (!strcmp(bitstr, "128")) { + ciphertext16 = /* section F.5.1 */ + "874d6191b620e3261bef6864990db6ce" + "9806f66b7970fdff8617187bb9fffdff" + "5ae4df3edbd5d35e5b4f09020db03eab" + "1e031dda2fbe03d1792170a0f3009cee"; + key16 = "2b7e151628aed2a6abf7158809cf4f3c"; + bits = 128; + } else if (!strcmp(bitstr, "192")) { + ciphertext16 = /* section F.5.3 */ + "1abc932417521ca24f2b0459fe7e6e0b" + "090339ec0aa6faefd5ccc2c6f4ce8e94" + "1e36b26bd1ebc670d1bd1d665620abf7" + "4f78a7f6d29809585a97daec58c6b050"; + key16 = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; + bits = 192; + } else if (!strcmp(bitstr, "256")) { + ciphertext16 = /* section F.5.5 */ + "601ec313775789a5b7a7f504bbf3d228" + "f443e3ca4d62b59aca84e990cacaf5c5" + "2b0930daa23de94ce87017ba2d84988d" + "dfc9c58db67aada613c2dd08457941a6"; + key16 = + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4"; + bits = 256; + } else { + tt_abort_msg("AES doesn't support this number of bits."); + } - char key[16]; + char key[32]; char iv[16]; char plaintext[16*4]; + memset(key, 0xf9, sizeof(key)); /* poison extra bytes */ base16_decode(key, sizeof(key), key16, strlen(key16)); base16_decode(iv, sizeof(iv), ctr16, strlen(ctr16)); base16_decode(plaintext, sizeof(plaintext), plaintext16, strlen(plaintext16)); - crypto_cipher_t *c = crypto_cipher_new_with_iv(key, iv); + c = crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv, bits); crypto_cipher_crypt_inplace(c, plaintext, sizeof(plaintext)); test_memeq_hex(plaintext, ciphertext16); @@ -2872,9 +2902,14 @@ struct testcase_t crypto_tests[] = { { "rng_strongest_broken", test_crypto_rng_strongest, TT_FORK, &passthrough_setup, (void*)"broken" }, { "openssl_version", test_crypto_openssl_version, TT_FORK, NULL, NULL }, - { "aes_AES", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"aes" }, - { "aes_EVP", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"evp" }, - { "aes_ctr_testvec", test_crypto_aes_ctr_testvec, 0, NULL, NULL }, + { "aes_AES", test_crypto_aes128, TT_FORK, &passthrough_setup, (void*)"aes" }, + { "aes_EVP", test_crypto_aes128, TT_FORK, &passthrough_setup, (void*)"evp" }, + { "aes128_ctr_testvec", test_crypto_aes_ctr_testvec, 0, + &passthrough_setup, (void*)"128" }, + { "aes192_ctr_testvec", test_crypto_aes_ctr_testvec, 0, + &passthrough_setup, (void*)"192" }, + { "aes256_ctr_testvec", test_crypto_aes_ctr_testvec, 0, + &passthrough_setup, (void*)"256" }, CRYPTO_LEGACY(sha), CRYPTO_LEGACY(pk), { "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL }, diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 4a6c5a9b5a..cf0b94c574 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -232,7 +232,6 @@ test_dir_formats(void *arg) "platform Tor "VERSION" on ", sizeof(buf2)); strlcat(buf2, get_uname(), sizeof(buf2)); strlcat(buf2, "\n" - "protocols Link 1 2 Circuit 1\n" "published 1970-01-01 00:00:00\n" "fingerprint ", sizeof(buf2)); tt_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1)); @@ -301,7 +300,6 @@ test_dir_formats(void *arg) strlcat(buf2, "platform Tor "VERSION" on ", sizeof(buf2)); strlcat(buf2, get_uname(), sizeof(buf2)); strlcat(buf2, "\n" - "protocols Link 1 2 Circuit 1\n" "published 1970-01-01 00:00:05\n" "fingerprint ", sizeof(buf2)); tt_assert(!crypto_pk_get_fingerprint(pk1, fingerprint, 1)); @@ -680,16 +678,16 @@ test_dir_parse_router_list(void *arg) routerinfo_t *ri = NULL; char d[DIGEST_LEN]; - smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL)); // ri 0 - smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS)); // bad ri 0 - smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL)); // ei 0 - smartlist_add(chunks, tor_strdup(EX_EI_BAD_SIG2)); // bad ei -- - smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));// bad ei 0 - smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG1)); // bad ri -- - smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED)); // bad ei 1 - smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL)); // ri 1 - smartlist_add(chunks, tor_strdup(EX_RI_BAD_FAMILY)); // bad ri 1 - smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL)); // ei 1 + smartlist_add_strdup(chunks, EX_RI_MINIMAL); // ri 0 + smartlist_add_strdup(chunks, EX_RI_BAD_PORTS); // bad ri 0 + smartlist_add_strdup(chunks, EX_EI_MAXIMAL); // ei 0 + smartlist_add_strdup(chunks, EX_EI_BAD_SIG2); // bad ei -- + smartlist_add_strdup(chunks, EX_EI_BAD_NICKNAME);// bad ei 0 + smartlist_add_strdup(chunks, EX_RI_BAD_SIG1); // bad ri -- + smartlist_add_strdup(chunks, EX_EI_BAD_PUBLISHED); // bad ei 1 + smartlist_add_strdup(chunks, EX_RI_MAXIMAL); // ri 1 + smartlist_add_strdup(chunks, EX_RI_BAD_FAMILY); // bad ri 1 + smartlist_add_strdup(chunks, EX_EI_MINIMAL); // ei 1 list = smartlist_join_strings(chunks, "", 0, NULL); @@ -814,19 +812,19 @@ test_dir_load_routers(void *arg) #define ADD(str) \ do { \ tt_int_op(0,OP_EQ,router_get_router_hash(str, strlen(str), buf)); \ - smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \ + smartlist_add_strdup(wanted, hex_str(buf, DIGEST_LEN)); \ } while (0) MOCK(router_get_dl_status_by_descriptor_digest, mock_router_get_dl_status); update_approx_time(1412510400); - smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL)); - smartlist_add(chunks, tor_strdup(EX_RI_BAD_FINGERPRINT)); - smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG2)); - smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL)); - smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS)); - smartlist_add(chunks, tor_strdup(EX_RI_BAD_TOKENS)); + smartlist_add_strdup(chunks, EX_RI_MINIMAL); + smartlist_add_strdup(chunks, EX_RI_BAD_FINGERPRINT); + smartlist_add_strdup(chunks, EX_RI_BAD_SIG2); + smartlist_add_strdup(chunks, EX_RI_MAXIMAL); + smartlist_add_strdup(chunks, EX_RI_BAD_PORTS); + smartlist_add_strdup(chunks, EX_RI_BAD_TOKENS); /* not ADDing MINIMIAL */ ADD(EX_RI_MAXIMAL); @@ -934,18 +932,18 @@ test_dir_load_extrainfo(void *arg) #define ADD(str) \ do { \ tt_int_op(0,OP_EQ,router_get_extrainfo_hash(str, strlen(str), buf)); \ - smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \ + smartlist_add_strdup(wanted, hex_str(buf, DIGEST_LEN)); \ } while (0) mock_ei_insert_list = smartlist_new(); MOCK(router_get_by_extrainfo_digest, mock_get_by_ei_desc_digest); MOCK(extrainfo_insert, mock_ei_insert); - smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL)); - smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME)); - smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL)); - smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED)); - smartlist_add(chunks, tor_strdup(EX_EI_BAD_TOKENS)); + smartlist_add_strdup(chunks, EX_EI_MINIMAL); + smartlist_add_strdup(chunks, EX_EI_BAD_NICKNAME); + smartlist_add_strdup(chunks, EX_EI_MAXIMAL); + smartlist_add_strdup(chunks, EX_EI_BAD_PUBLISHED); + smartlist_add_strdup(chunks, EX_EI_BAD_TOKENS); /* not ADDing MINIMIAL */ ADD(EX_EI_MAXIMAL); @@ -1876,6 +1874,249 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now) return; } +static void +test_dir_networkstatus_compute_bw_weights_v10(void *arg) +{ + (void) arg; + smartlist_t *chunks = smartlist_new(); + int64_t G, M, E, D, T, weight_scale; + int ret; + weight_scale = 10000; + + /* no case. one or more of the values is 0 */ + G = M = E = D = 0; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(smartlist_len(chunks), OP_EQ, 0); + + /* case 1 */ + /* XXX dir-spec not followed? See #20272. If it isn't closed, then this is + * testing current behavior, not spec. */ + G = E = 10; + M = D = 1; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_int_op(smartlist_len(chunks), OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=3333 " + "Wbe=3000 Wbg=3000 Wbm=10000 Wdb=10000 Web=10000 Wed=3333 Wee=7000 " + "Weg=3333 Wem=7000 Wgb=10000 Wgd=3333 Wgg=7000 Wgm=7000 Wmb=10000 " + "Wmd=3333 Wme=3000 Wmg=3000 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2a E scarce */ + M = 100; + G = 20; + E = D = 5; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 " + "Wem=10000 Wgb=10000 Wgd=0 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 Wme=0 " + "Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2a G scarce */ + M = 100; + E = 20; + G = D = 5; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=10000 Weg=0 Wem=10000 " + "Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 Wme=0 Wmg=0 " + "Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2b1 (Wgg=1, Wmd=Wgd) */ + M = 10; + E = 30; + G = 10; + D = 100; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=4000 " + "Wbe=0 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=2000 Wee=10000 Weg=2000 " + "Wem=10000 Wgb=10000 Wgd=4000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=4000 " + "Wme=0 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2b2 */ + M = 60; + E = 30; + G = 10; + D = 100; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=666 Wbe=0 " + "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=3666 Wee=10000 Weg=3666 " + "Wem=10000 Wgb=10000 Wgd=5668 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=666 " + "Wme=0 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 2b3 */ + /* XXX I can't get a combination of values that hits this case without error, + * so this just tests that it fails. See #20285. Also see #20284 as 2b3 does + * not follow dir-spec. */ + /* (E < T/3 && G < T/3) && (E+D>=G || G+D>=E) && (M > T/3) */ + M = 80; + E = 30; + G = 30; + D = 30; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 0); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 3a G scarce */ + M = 10; + E = 30; + G = 10; + D = 5; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 " + "Wbe=3333 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=6667 Weg=0 " + "Wem=6667 Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 " + "Wme=3333 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 3a E scarce */ + M = 10; + E = 10; + G = 30; + D = 5; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=3333 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 " + "Wem=10000 Wgb=10000 Wgd=0 Wgg=6667 Wgm=6667 Wmb=10000 Wmd=0 Wme=0 " + "Wmg=3333 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 3bg */ + M = 10; + E = 30; + G = 10; + D = 10; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 " + "Wbe=3334 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=6666 Weg=0 " + "Wem=6666 Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 " + "Wme=3334 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case 3be */ + M = 10; + E = 10; + G = 30; + D = 10; + T = G + M + E + D; + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_int_op(ret, OP_EQ, 1); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=3334 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 " + "Wem=10000 Wgb=10000 Wgd=0 Wgg=6666 Wgm=6666 Wmb=10000 Wmd=0 Wme=0 " + "Wmg=3334 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case from 21 Jul 2013 (3be) */ + G = 5483409; + M = 1455379; + E = 980834; + D = 3385803; + T = 11305425; + tt_i64_op(G+M+E+D, OP_EQ, T); + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=883 Wbe=0 " + "Wbg=3673 Wbm=10000 Wdb=10000 Web=10000 Wed=8233 Wee=10000 Weg=8233 " + "Wem=10000 Wgb=10000 Wgd=883 Wgg=6327 Wgm=6327 Wmb=10000 Wmd=883 Wme=0 " + "Wmg=3673 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case from 04 Oct 2016 (3a E scarce) */ + G=29322240; + M=4721546; + E=1522058; + D=9273571; + T=44839415; + tt_i64_op(G+M+E+D, OP_EQ, T); + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 " + "Wbg=4194 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 " + "Wem=10000 Wgb=10000 Wgd=0 Wgg=5806 Wgm=5806 Wmb=10000 Wmd=0 Wme=0 " + "Wmg=4194 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* case from 04 Sep 2013 (2b1) */ + G=3091352; + M=1838837; + E=2109300; + D=2469369; + T=9508858; + tt_i64_op(G+M+E+D, OP_EQ, T); + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=317 " + "Wbe=5938 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=9366 Wee=4061 " + "Weg=9366 Wem=4061 Wgb=10000 Wgd=317 Wgg=10000 Wgm=10000 Wmb=10000 " + "Wmd=317 Wme=5938 Wmg=0 Wmm=10000\n"); + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_clear(chunks); + + /* explicitly test initializing weights to 1*/ + G=1; + M=1; + E=1; + D=1; + T=4; + tt_i64_op(G+M+E+D, OP_EQ, T); + ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, + weight_scale); + tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=3333 " + "Wbe=0 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=3333 Wee=10000 Weg=3333 " + "Wem=10000 Wgb=10000 Wgd=3333 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=3333 " + "Wme=0 Wmg=0 Wmm=10000\n"); + + done: + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); +} + static authority_cert_t *mock_cert; static authority_cert_t * @@ -3255,17 +3496,83 @@ test_dir_http_handling(void *args) } static void -test_dir_purpose_needs_anonymity(void *arg) +test_dir_purpose_needs_anonymity_returns_true_by_default(void *arg) +{ + (void)arg; + + tor_capture_bugs_(1); + tt_int_op(1, ==, purpose_needs_anonymity(0, 0, NULL)); + tt_int_op(1, ==, smartlist_len(tor_get_captured_bug_log_())); + tor_end_capture_bugs_(); + done: ; +} + +static void +test_dir_purpose_needs_anonymity_returns_true_for_bridges(void *arg) +{ + (void)arg; + + tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE, NULL)); + tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE, + "foobar")); + tt_int_op(1, ==, purpose_needs_anonymity(DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2, + ROUTER_PURPOSE_BRIDGE, NULL)); + done: ; +} + +static void +test_dir_purpose_needs_anonymity_returns_false_for_own_bridge_desc(void *arg) { (void)arg; - tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE)); - tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_GENERAL)); - tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC, - ROUTER_PURPOSE_GENERAL)); + tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, + ROUTER_PURPOSE_BRIDGE, + "authority.z")); done: ; } static void +test_dir_purpose_needs_anonymity_returns_true_for_sensitive_purpose(void *arg) +{ + (void)arg; + + tt_int_op(1, ==, purpose_needs_anonymity( + DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2, + ROUTER_PURPOSE_GENERAL, NULL)); + tt_int_op(1, ==, purpose_needs_anonymity( + DIR_PURPOSE_UPLOAD_RENDDESC_V2, 0, NULL)); + tt_int_op(1, ==, purpose_needs_anonymity( + DIR_PURPOSE_FETCH_RENDDESC_V2, 0, NULL)); + done: ; +} + +static void +test_dir_purpose_needs_anonymity_ret_false_for_non_sensitive_conn(void *arg) +{ + (void)arg; + + tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_DIR, + ROUTER_PURPOSE_GENERAL, NULL)); + tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_VOTE, 0, NULL)); + tt_int_op(0, ==, + purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_SIGNATURES, 0, NULL)); + tt_int_op(0, ==, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL)); + tt_int_op(0, ==, purpose_needs_anonymity( + DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL)); + tt_int_op(0, ==, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_CONSENSUS, 0, NULL)); + tt_int_op(0, ==, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0, NULL)); + tt_int_op(0, ==, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, 0, NULL)); + tt_int_op(0, ==, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_EXTRAINFO, 0, NULL)); + tt_int_op(0, ==, + purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC, 0, NULL)); + done: ; +} + +static void test_dir_fetch_type(void *arg) { (void)arg; @@ -5144,9 +5451,9 @@ listdir_mock(const char *dname) (void)dname; l = smartlist_new(); - smartlist_add(l, tor_strdup("foo")); - smartlist_add(l, tor_strdup("bar")); - smartlist_add(l, tor_strdup("baz")); + smartlist_add_strdup(l, "foo"); + smartlist_add_strdup(l, "bar"); + smartlist_add_strdup(l, "baz"); return l; } @@ -5390,6 +5697,49 @@ test_dir_find_dl_schedule(void* data) mock_options = NULL; } +static void +test_dir_assumed_flags(void *arg) +{ + (void)arg; + smartlist_t *tokens = smartlist_new(); + memarea_t *area = memarea_new(); + routerstatus_t *rs = NULL; + + /* First, we should always assume that the Running flag is set, even + * when it isn't listed, since the consensus method is always + * higher than 4. */ + const char *str1 = + "r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 " + "192.168.0.1 9001 0\n" + "m thisoneislongerbecauseitisa256bitmddigest33\n" + "s Fast Guard Stable\n"; + + const char *cp = str1; + rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL, + 23, FLAV_MICRODESC); + tt_assert(rs); + tt_assert(rs->is_flagged_running); + tt_assert(! rs->is_valid); + tt_assert(! rs->is_exit); + tt_assert(rs->is_fast); + routerstatus_free(rs); + + /* With method 24 or later, we can assume "valid" is set. */ + cp = str1; + rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL, + 24, FLAV_MICRODESC); + tt_assert(rs); + tt_assert(rs->is_flagged_running); + tt_assert(rs->is_valid); + tt_assert(! rs->is_exit); + tt_assert(rs->is_fast); + + done: + smartlist_free(tokens); + memarea_drop_all(area); + routerstatus_free(rs); +} + #define DIR_LEGACY(name) \ { #name, test_dir_ ## name , TT_FORK, NULL, NULL } @@ -5423,7 +5773,11 @@ struct testcase_t dir_tests[] = { DIR(fmt_control_ns, 0), DIR(dirserv_set_routerstatus_testing, 0), DIR(http_handling, 0), - DIR(purpose_needs_anonymity, 0), + DIR(purpose_needs_anonymity_returns_true_for_bridges, 0), + DIR(purpose_needs_anonymity_returns_false_for_own_bridge_desc, 0), + DIR(purpose_needs_anonymity_returns_true_by_default, 0), + DIR(purpose_needs_anonymity_returns_true_for_sensitive_purpose, 0), + DIR(purpose_needs_anonymity_ret_false_for_non_sensitive_conn, 0), DIR(fetch_type, 0), DIR(packages, 0), DIR(download_status_schedule, 0), @@ -5443,6 +5797,8 @@ struct testcase_t dir_tests[] = { DIR_ARG(find_dl_schedule, TT_FORK, "ba"), DIR_ARG(find_dl_schedule, TT_FORK, "cf"), DIR_ARG(find_dl_schedule, TT_FORK, "ca"), + DIR(assumed_flags, 0), + DIR(networkstatus_compute_bw_weights_v10, 0), END_OF_TESTCASES }; diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c index 9580a1fd3f..50848cfec2 100644 --- a/src/test/test_entryconn.c +++ b/src/test/test_entryconn.c @@ -100,7 +100,7 @@ test_entryconn_rewrite_automap_ipv4(void *arg) ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET); get_options_mutable()->AutomapHostsOnResolve = 1; - smartlist_add(get_options_mutable()->AutomapHostsSuffixes, tor_strdup(".")); + smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, "."); parse_virtual_addr_network("127.202.0.0/16", AF_INET, 0, &msg); /* Automap this on resolve. */ @@ -173,7 +173,7 @@ test_entryconn_rewrite_automap_ipv6(void *arg) ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET6); get_options_mutable()->AutomapHostsOnResolve = 1; - smartlist_add(get_options_mutable()->AutomapHostsSuffixes, tor_strdup(".")); + smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, "."); parse_virtual_addr_network("FE80::/32", AF_INET6, 0, &msg); /* Automap this on resolve. */ @@ -489,8 +489,8 @@ test_entryconn_rewrite_automap_exit(void *arg) get_options_mutable()->AutomapHostsOnResolve = 1; get_options_mutable()->AllowDotExit = 1; - smartlist_add(get_options_mutable()->AutomapHostsSuffixes, - tor_strdup(".EXIT")); + smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, + ".EXIT"); parse_virtual_addr_network("127.1.0.0/16", AF_INET, 0, &msg); /* Automap this on resolve. */ @@ -574,8 +574,8 @@ test_entryconn_rewrite_mapaddress_automap_onion(void *arg) get_options_mutable()->AutomapHostsOnResolve = 1; get_options_mutable()->AllowDotExit = 1; - smartlist_add(get_options_mutable()->AutomapHostsSuffixes, - tor_strdup(".onion")); + smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, + ".onion"); parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg); config_line_append(&get_options_mutable()->AddressMap, "MapAddress", "foo.onion abcdefghijklmnop.onion"); @@ -709,8 +709,8 @@ test_entryconn_rewrite_mapaddress_automap_onion2(void *arg) { char *msg = NULL; get_options_mutable()->AutomapHostsOnResolve = 1; - smartlist_add(get_options_mutable()->AutomapHostsSuffixes, - tor_strdup(".onion")); + smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, + ".onion"); parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg); config_line_append(&get_options_mutable()->AddressMap, "MapAddress", "irc.example.com abcdefghijklmnop.onion"); @@ -736,8 +736,8 @@ test_entryconn_rewrite_mapaddress_automap_onion4(void *arg) { char *msg = NULL; get_options_mutable()->AutomapHostsOnResolve = 1; - smartlist_add(get_options_mutable()->AutomapHostsSuffixes, - tor_strdup(".onion")); + smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, + ".onion"); parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg); test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 0, 1); diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index b1c3accfab..8e4f4061c6 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -254,7 +254,9 @@ populate_live_entry_guards_test_helper(int num_needed) { smartlist_t *our_nodelist = NULL; smartlist_t *live_entry_guards = smartlist_new(); - const smartlist_t *all_entry_guards = get_entry_guards(); + guard_selection_t *gs = get_guard_selection_info(); + const smartlist_t *all_entry_guards = + get_entry_guards_for_guard_selection(gs); or_options_t *options = get_options_mutable(); int retval; @@ -271,7 +273,7 @@ populate_live_entry_guards_test_helper(int num_needed) SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { const node_t *node_tmp; - node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); + node_tmp = add_an_entry_guard(gs, node, 0, 1, 0, 0); tt_assert(node_tmp); } SMARTLIST_FOREACH_END(node); @@ -582,7 +584,9 @@ static void test_entry_guards_set_from_config(void *arg) { or_options_t *options = get_options_mutable(); - const smartlist_t *all_entry_guards = get_entry_guards(); + guard_selection_t *gs = get_guard_selection_info(); + const smartlist_t *all_entry_guards = + get_entry_guards_for_guard_selection(gs); const char *entrynodes_str = "test003r"; const node_t *chosen_entry = NULL; int retval; @@ -597,7 +601,7 @@ test_entry_guards_set_from_config(void *arg) tt_int_op(retval, OP_GE, 0); /* Read nodes from EntryNodes */ - entry_guards_set_from_config(options); + entry_guards_set_from_config(gs, options); /* Test that only one guard was added. */ tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 1); @@ -689,7 +693,9 @@ static void test_entry_is_live(void *arg) { smartlist_t *our_nodelist = NULL; - const smartlist_t *all_entry_guards = get_entry_guards(); + guard_selection_t *gs = get_guard_selection_info(); + const smartlist_t *all_entry_guards = + get_entry_guards_for_guard_selection(gs); const node_t *test_node = NULL; const entry_guard_t *test_entry = NULL; const char *msg; @@ -706,7 +712,7 @@ test_entry_is_live(void *arg) SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { const node_t *node_tmp; - node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); + node_tmp = add_an_entry_guard(gs, node, 0, 1, 0, 0); tt_assert(node_tmp); tt_int_op(node->is_stable, OP_EQ, 0); diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 1daa1552e9..fd5ab15643 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -8,12 +8,14 @@ #define CONTROL_PRIVATE #define CIRCUITBUILD_PRIVATE +#define RENDSERVICE_PRIVATE #include "or.h" #include "test.h" #include "control.h" #include "config.h" #include "rendcommon.h" +#include "rendservice.h" #include "routerset.h" #include "circuitbuild.h" #include "test_helpers.h" @@ -496,6 +498,212 @@ test_hs_auth_cookies(void *arg) return; } +static int mock_get_options_calls = 0; +static or_options_t *mock_options = NULL; + +static void +reset_options(or_options_t *options, int *get_options_calls) +{ + memset(options, 0, sizeof(or_options_t)); + options->TestingTorNetwork = 1; + + *get_options_calls = 0; +} + +static const or_options_t * +mock_get_options(void) +{ + ++mock_get_options_calls; + tor_assert(mock_options); + return mock_options; +} + +/* Test that single onion poisoning works. */ +static void +test_single_onion_poisoning(void *arg) +{ + or_options_t opt; + mock_options = &opt; + reset_options(mock_options, &mock_get_options_calls); + MOCK(get_options, mock_get_options); + + int ret = -1; + mock_options->DataDirectory = tor_strdup(get_fname("test_data_dir")); + rend_service_t *service_1 = tor_malloc_zero(sizeof(rend_service_t)); + char *dir1 = tor_strdup(get_fname("test_hs_dir1")); + rend_service_t *service_2 = tor_malloc_zero(sizeof(rend_service_t)); + char *dir2 = tor_strdup(get_fname("test_hs_dir2")); + smartlist_t *services = smartlist_new(); + + (void) arg; + + /* No services, no problem! */ + mock_options->HiddenServiceSingleHopMode = 0; + mock_options->HiddenServiceNonAnonymousMode = 0; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Either way, no problem. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Create directories for both services */ + +#ifdef _WIN32 + ret = mkdir(mock_options->DataDirectory); + tt_assert(ret == 0); + ret = mkdir(dir1); + tt_assert(ret == 0); + ret = mkdir(dir2); +#else + ret = mkdir(mock_options->DataDirectory, 0700); + tt_assert(ret == 0); + ret = mkdir(dir1, 0700); + tt_assert(ret == 0); + ret = mkdir(dir2, 0700); +#endif + tt_assert(ret == 0); + + service_1->directory = dir1; + service_2->directory = dir2; + dir1 = dir2 = NULL; + smartlist_add(services, service_1); + /* But don't add the second service yet. */ + + /* Service directories, but no previous keys, no problem! */ + mock_options->HiddenServiceSingleHopMode = 0; + mock_options->HiddenServiceNonAnonymousMode = 0; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Either way, no problem. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Poison! Poison! Poison! + * This can only be done in HiddenServiceSingleHopMode. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_poison_new_single_onion_dirs(services); + tt_assert(ret == 0); + /* Poisoning twice is a no-op. */ + ret = rend_service_poison_new_single_onion_dirs(services); + tt_assert(ret == 0); + + /* Poisoned service directories, but no previous keys, no problem! */ + mock_options->HiddenServiceSingleHopMode = 0; + mock_options->HiddenServiceNonAnonymousMode = 0; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Either way, no problem. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Now add some keys, and we'll have a problem. */ + ret = rend_service_load_all_keys(services); + tt_assert(ret == 0); + + /* Poisoned service directories with previous keys are not allowed. */ + mock_options->HiddenServiceSingleHopMode = 0; + mock_options->HiddenServiceNonAnonymousMode = 0; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret < 0); + + /* But they are allowed if we're in non-anonymous mode. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Re-poisoning directories with existing keys is a no-op, because + * directories with existing keys are ignored. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_poison_new_single_onion_dirs(services); + tt_assert(ret == 0); + /* And it keeps the poison. */ + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Now add the second service: it has no key and no poison file */ + smartlist_add(services, service_2); + + /* A new service, and an existing poisoned service. Not ok. */ + mock_options->HiddenServiceSingleHopMode = 0; + mock_options->HiddenServiceNonAnonymousMode = 0; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret < 0); + + /* But ok to add in non-anonymous mode. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Now remove the poisoning from the first service, and we have the opposite + * problem. */ + char *poison_path = rend_service_sos_poison_path(service_1); + ret = unlink(poison_path); + tor_free(poison_path); + tt_assert(ret == 0); + + /* Unpoisoned service directories with previous keys are ok, as are empty + * directories. */ + mock_options->HiddenServiceSingleHopMode = 0; + mock_options->HiddenServiceNonAnonymousMode = 0; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* But the existing unpoisoned key is not ok in non-anonymous mode, even if + * there is an empty service. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret < 0); + + /* Poisoning directories with existing keys is a no-op, because directories + * with existing keys are ignored. But the new directory should poison. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_poison_new_single_onion_dirs(services); + tt_assert(ret == 0); + /* And the old directory remains unpoisoned. */ + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret < 0); + + /* And the new directory should be ignored, because it has no key. */ + mock_options->HiddenServiceSingleHopMode = 0; + mock_options->HiddenServiceNonAnonymousMode = 0; + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret == 0); + + /* Re-poisoning directories without existing keys is a no-op. */ + mock_options->HiddenServiceSingleHopMode = 1; + mock_options->HiddenServiceNonAnonymousMode = 1; + ret = rend_service_poison_new_single_onion_dirs(services); + tt_assert(ret == 0); + /* And the old directory remains unpoisoned. */ + ret = rend_service_list_verify_single_onion_poison(services, mock_options); + tt_assert(ret < 0); + + done: + /* TODO: should we delete the directories here? */ + rend_service_free(service_1); + rend_service_free(service_2); + smartlist_free(services); + UNMOCK(get_options); + tor_free(mock_options->DataDirectory); + tor_free(dir1); + tor_free(dir2); +} + struct testcase_t hs_tests[] = { { "hs_rend_data", test_hs_rend_data, TT_FORK, NULL, NULL }, @@ -508,6 +716,8 @@ struct testcase_t hs_tests[] = { NULL, NULL }, { "hs_auth_cookies", test_hs_auth_cookies, TT_FORK, NULL, NULL }, + { "single_onion_poisoning", test_single_onion_poisoning, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_options.c b/src/test/test_options.c index 0451b93738..0eada98cb2 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -1078,7 +1078,7 @@ test_options_validate__transproxy(void *ignored) tt_int_op(ret, OP_EQ, -1); tt_assert(!msg); #endif -#if defined(__FreeBSD_kernel__) || defined( DARWIN ) +#if defined(__FreeBSD_kernel__) || defined( DARWIN ) || defined(__NetBSD__) tdata = get_options_test_data("TransProxyType ipfw\n" "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); @@ -2750,6 +2750,155 @@ test_options_validate__rend(void *ignored) } static void +test_options_validate__single_onion(void *ignored) +{ + (void)ignored; + int ret; + char *msg; + options_test_data_t *tdata = NULL; + setup_capture_of_logs(LOG_WARN); + + /* Test that HiddenServiceSingleHopMode must come with + * HiddenServiceNonAnonymousMode */ + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "SOCKSPort 0\n" + "HiddenServiceSingleHopMode 1\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any " + "server anonymity. It must be used with " + "HiddenServiceNonAnonymousMode set to 1."); + tor_free(msg); + free_options_test_data(tdata); + + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "SOCKSPort 0\n" + "HiddenServiceSingleHopMode 1\n" + "HiddenServiceNonAnonymousMode 0\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any " + "server anonymity. It must be used with " + "HiddenServiceNonAnonymousMode set to 1."); + tor_free(msg); + free_options_test_data(tdata); + + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "SOCKSPort 0\n" + "HiddenServiceSingleHopMode 1\n" + "HiddenServiceNonAnonymousMode 1\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + free_options_test_data(tdata); + + /* Test that SOCKSPort must come with Tor2webMode if + * HiddenServiceSingleHopMode is 1 */ + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "SOCKSPort 5000\n" + "HiddenServiceSingleHopMode 1\n" + "HiddenServiceNonAnonymousMode 1\n" + "Tor2webMode 0\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode is incompatible with " + "using Tor as an anonymous client. Please set " + "Socks/Trans/NATD/DNSPort to 0, or HiddenServiceNonAnonymousMode " + "to 0, or use the non-anonymous Tor2webMode."); + tor_free(msg); + free_options_test_data(tdata); + + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "SOCKSPort 0\n" + "HiddenServiceSingleHopMode 1\n" + "HiddenServiceNonAnonymousMode 1\n" + "Tor2webMode 0\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + free_options_test_data(tdata); + + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "SOCKSPort 5000\n" + "HiddenServiceSingleHopMode 0\n" + "Tor2webMode 0\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + free_options_test_data(tdata); + + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "SOCKSPort 5000\n" + "HiddenServiceSingleHopMode 1\n" + "HiddenServiceNonAnonymousMode 1\n" + "Tor2webMode 1\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + free_options_test_data(tdata); + + /* Test that a hidden service can't be run with Tor2web + * Use HiddenServiceNonAnonymousMode instead of Tor2webMode, because + * Tor2webMode requires a compilation #define */ + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "HiddenServiceNonAnonymousMode 1\n" + "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" + "HiddenServicePort 80 127.0.0.1:8080\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any " + "server anonymity. It must be used with " + "HiddenServiceSingleHopMode set to 1."); + tor_free(msg); + free_options_test_data(tdata); + + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "HiddenServiceNonAnonymousMode 1\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any " + "server anonymity. It must be used with " + "HiddenServiceSingleHopMode set to 1."); + tor_free(msg); + free_options_test_data(tdata); + + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" + "HiddenServicePort 80 127.0.0.1:8080\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + free_options_test_data(tdata); + + tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + "HiddenServiceNonAnonymousMode 1\n" + "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" + "HiddenServicePort 80 127.0.0.1:8080\n" + "HiddenServiceSingleHopMode 1\n" + "SOCKSPort 0\n" + ); + ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + + done: + policies_free_all(); + teardown_capture_of_logs(); + free_options_test_data(tdata); + tor_free(msg); +} + +static void test_options_validate__accounting(void *ignored) { (void)ignored; @@ -4371,6 +4520,7 @@ struct testcase_t options_tests[] = { LOCAL_VALIDATE_TEST(port_forwarding), LOCAL_VALIDATE_TEST(tor2web), LOCAL_VALIDATE_TEST(rend), + LOCAL_VALIDATE_TEST(single_onion), LOCAL_VALIDATE_TEST(accounting), LOCAL_VALIDATE_TEST(proxy), LOCAL_VALIDATE_TEST(control), diff --git a/src/test/test_policy.c b/src/test/test_policy.c index 0d4a3b104f..b89de01b7b 100644 --- a/src/test/test_policy.c +++ b/src/test/test_policy.c @@ -525,10 +525,10 @@ test_policies_general(void *arg) { char *policy_strng = NULL; smartlist_t *chunks = smartlist_new(); - smartlist_add(chunks, tor_strdup("accept ")); + smartlist_add_strdup(chunks, "accept "); for (i=1; i<10000; ++i) smartlist_add_asprintf(chunks, "%d,", i); - smartlist_add(chunks, tor_strdup("20000")); + smartlist_add_strdup(chunks, "20000"); policy_strng = smartlist_join_strings(chunks, "", 0, NULL); SMARTLIST_FOREACH(chunks, char *, ch, tor_free(ch)); smartlist_free(chunks); @@ -542,9 +542,9 @@ test_policies_general(void *arg) for (i=1; i<2000; i+=2) { char buf[POLICY_BUF_LEN]; tor_snprintf(buf, sizeof(buf), "reject *:%d", i); - smartlist_add(sm, tor_strdup(buf)); + smartlist_add_strdup(sm, buf); } - smartlist_add(sm, tor_strdup("accept *:*")); + smartlist_add_strdup(sm, "accept *:*"); policy_str = smartlist_join_strings(sm, ",", 0, NULL); test_policy_summary_helper( policy_str, "accept 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44," diff --git a/src/test/test_protover.c b/src/test/test_protover.c new file mode 100644 index 0000000000..f00955d1b4 --- /dev/null +++ b/src/test/test_protover.c @@ -0,0 +1,195 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define PROTOVER_PRIVATE + +#include "orconfig.h" +#include "test.h" + +#include "protover.h" + +static void +test_protover_parse(void *arg) +{ + (void) arg; + char *re_encoded = NULL; + + const char *orig = "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900"; + smartlist_t *elts = parse_protocol_list(orig); + + tt_assert(elts); + tt_int_op(smartlist_len(elts), OP_EQ, 4); + + const proto_entry_t *e; + const proto_range_t *r; + e = smartlist_get(elts, 0); + tt_str_op(e->name, OP_EQ, "Foo"); + tt_int_op(smartlist_len(e->ranges), OP_EQ, 2); + { + r = smartlist_get(e->ranges, 0); + tt_int_op(r->low, OP_EQ, 1); + tt_int_op(r->high, OP_EQ, 1); + + r = smartlist_get(e->ranges, 1); + tt_int_op(r->low, OP_EQ, 3); + tt_int_op(r->high, OP_EQ, 3); + } + + e = smartlist_get(elts, 1); + tt_str_op(e->name, OP_EQ, "Bar"); + tt_int_op(smartlist_len(e->ranges), OP_EQ, 1); + { + r = smartlist_get(e->ranges, 0); + tt_int_op(r->low, OP_EQ, 3); + tt_int_op(r->high, OP_EQ, 3); + } + + e = smartlist_get(elts, 2); + tt_str_op(e->name, OP_EQ, "Baz"); + tt_int_op(smartlist_len(e->ranges), OP_EQ, 0); + + e = smartlist_get(elts, 3); + tt_str_op(e->name, OP_EQ, "Quux"); + tt_int_op(smartlist_len(e->ranges), OP_EQ, 4); + { + r = smartlist_get(e->ranges, 0); + tt_int_op(r->low, OP_EQ, 9); + tt_int_op(r->high, OP_EQ, 12); + + r = smartlist_get(e->ranges, 1); + tt_int_op(r->low, OP_EQ, 14); + tt_int_op(r->high, OP_EQ, 14); + + r = smartlist_get(e->ranges, 2); + tt_int_op(r->low, OP_EQ, 15); + tt_int_op(r->high, OP_EQ, 16); + + r = smartlist_get(e->ranges, 3); + tt_int_op(r->low, OP_EQ, 900); + tt_int_op(r->high, OP_EQ, 900); + } + + re_encoded = encode_protocol_list(elts); + tt_assert(re_encoded); + tt_str_op(re_encoded, OP_EQ, orig); + + done: + if (elts) + SMARTLIST_FOREACH(elts, proto_entry_t *, ent, proto_entry_free(ent)); + smartlist_free(elts); + tor_free(re_encoded); +} + +static void +test_protover_parse_fail(void *arg) +{ + (void)arg; + smartlist_t *elts; + + /* random junk */ + elts = parse_protocol_list("!!3@*"); + tt_assert(elts == NULL); + + /* Missing equals sign in an entry */ + elts = parse_protocol_list("Link=4 Haprauxymatyve Desc=9"); + tt_assert(elts == NULL); + + /* Missing word. */ + elts = parse_protocol_list("Link=4 =3 Desc=9"); + tt_assert(elts == NULL); + + /* Broken numbers */ + elts = parse_protocol_list("Link=fred"); + tt_assert(elts == NULL); + elts = parse_protocol_list("Link=1,fred"); + tt_assert(elts == NULL); + elts = parse_protocol_list("Link=1,fred,3"); + tt_assert(elts == NULL); + + /* Broken range */ + elts = parse_protocol_list("Link=1,9-8,3"); + tt_assert(elts == NULL); + + done: + ; +} + +static void +test_protover_vote(void *arg) +{ + (void) arg; + + smartlist_t *lst = smartlist_new(); + char *result = protover_compute_vote(lst, 1); + + tt_str_op(result, OP_EQ, ""); + tor_free(result); + + smartlist_add(lst, (void*) "Foo=1-10,500 Bar=1,3-7,8"); + result = protover_compute_vote(lst, 1); + tt_str_op(result, OP_EQ, "Bar=1,3-8 Foo=1-10,500"); + tor_free(result); + + smartlist_add(lst, (void*) "Quux=123-456,78 Bar=2-6,8 Foo=9"); + result = protover_compute_vote(lst, 1); + tt_str_op(result, OP_EQ, "Bar=1-8 Foo=1-10,500 Quux=78,123-456"); + tor_free(result); + + result = protover_compute_vote(lst, 2); + tt_str_op(result, OP_EQ, "Bar=3-6,8 Foo=9"); + tor_free(result); + + done: + tor_free(result); + smartlist_free(lst); +} + +static void +test_protover_all_supported(void *arg) +{ + (void)arg; + char *msg = NULL; + + tt_assert(protover_all_supported(NULL, &msg)); + tt_assert(msg == NULL); + + tt_assert(protover_all_supported("", &msg)); + tt_assert(msg == NULL); + + // Some things that we do support + tt_assert(protover_all_supported("Link=3-4", &msg)); + tt_assert(msg == NULL); + tt_assert(protover_all_supported("Link=3-4 Desc=2", &msg)); + tt_assert(msg == NULL); + + // Some things we don't support + tt_assert(! protover_all_supported("Wombat=9", &msg)); + tt_str_op(msg, OP_EQ, "Wombat=9"); + tor_free(msg); + tt_assert(! protover_all_supported("Link=999", &msg)); + tt_str_op(msg, OP_EQ, "Link=999"); + tor_free(msg); + + // Mix of things we support and things we don't + tt_assert(! protover_all_supported("Link=3-4 Wombat=9", &msg)); + tt_str_op(msg, OP_EQ, "Wombat=9"); + tor_free(msg); + tt_assert(! protover_all_supported("Link=3-999", &msg)); + tt_str_op(msg, OP_EQ, "Link=3-999"); + tor_free(msg); + + done: + tor_free(msg); +} + +#define PV_TEST(name, flags) \ + { #name, test_protover_ ##name, (flags), NULL, NULL } + +struct testcase_t protover_tests[] = { + PV_TEST(parse, 0), + PV_TEST(parse_fail, 0), + PV_TEST(vote, 0), + PV_TEST(all_supported, 0), + END_OF_TESTCASES +}; + diff --git a/src/test/test_pt.c b/src/test/test_pt.c index e5cdc5f3cd..f93019f1c4 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -155,9 +155,9 @@ test_pt_get_transport_options(void *arg) opt_str = get_transport_options_for_server_proxy(mp); tt_ptr_op(opt_str, OP_EQ, NULL); - smartlist_add(mp->transports_to_launch, tor_strdup("gruyere")); - smartlist_add(mp->transports_to_launch, tor_strdup("roquefort")); - smartlist_add(mp->transports_to_launch, tor_strdup("stnectaire")); + smartlist_add_strdup(mp->transports_to_launch, "gruyere"); + smartlist_add_strdup(mp->transports_to_launch, "roquefort"); + smartlist_add_strdup(mp->transports_to_launch, "stnectaire"); tt_assert(options); @@ -305,7 +305,7 @@ tor_get_lines_from_handle_replacement(STDIN_HANDLE *handle, smartlist_add_asprintf(retval_sl, "SMETHOD mock%d 127.0.0.1:555%d", times_called, times_called); } else { - smartlist_add(retval_sl, tor_strdup("SMETHODS DONE")); + smartlist_add_strdup(retval_sl, "SMETHODS DONE"); } return retval_sl; diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c index 088bd257c3..af5c121ce2 100644 --- a/src/test/test_routerlist.c +++ b/src/test/test_routerlist.c @@ -15,6 +15,7 @@ #include "container.h" #include "directory.h" #include "dirvote.h" +#include "entrynodes.h" #include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" @@ -203,6 +204,53 @@ mock_usable_consensus_flavor(void) return mock_usable_consensus_flavor_value; } +static smartlist_t *mock_is_guard_list = NULL; + +static int +mock_is_node_used_as_guard(const node_t *n) +{ + if (mock_is_guard_list) { + SMARTLIST_FOREACH_BEGIN(mock_is_guard_list, node_t *, e) { + if (e == n) return 1; + } SMARTLIST_FOREACH_END(e); + } + + return 0; +} + +static void +mark_node_used_as_guard(node_t *n) +{ + if (!n) return; + + if (!mock_is_guard_list) { + mock_is_guard_list = smartlist_new(); + } + + if (!mock_is_node_used_as_guard(n)) { + smartlist_add(mock_is_guard_list, n); + } +} + +static void +mark_node_unused_as_guard(node_t *n) +{ + if (!n) return; + + if (!mock_is_guard_list) return; + + smartlist_remove(mock_is_guard_list, n); +} + +static void +clear_mock_guard_list(void) +{ + if (mock_is_guard_list) { + smartlist_free(mock_is_guard_list); + mock_is_guard_list = NULL; + } +} + static void test_router_pick_directory_server_impl(void *arg) { @@ -223,6 +271,7 @@ test_router_pick_directory_server_impl(void *arg) (void)arg; MOCK(usable_consensus_flavor, mock_usable_consensus_flavor); + MOCK(is_node_used_as_guard, mock_is_node_used_as_guard); /* With no consensus, we must be bootstrapping, regardless of time or flavor */ @@ -336,28 +385,28 @@ test_router_pick_directory_server_impl(void *arg) node_router3->is_valid = 1; flags |= PDS_FOR_GUARD; - node_router1->using_as_guard = 1; - node_router2->using_as_guard = 1; - node_router3->using_as_guard = 1; + mark_node_used_as_guard(node_router1); + mark_node_used_as_guard(node_router2); + mark_node_used_as_guard(node_router3); rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs == NULL); - node_router1->using_as_guard = 0; + mark_node_unused_as_guard(node_router1); rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); rs = NULL; - node_router2->using_as_guard = 0; - node_router3->using_as_guard = 0; + mark_node_unused_as_guard(node_router2); + mark_node_unused_as_guard(node_router3); /* One not valid, one guard. This should leave one remaining */ node_router1->is_valid = 0; - node_router2->using_as_guard = 1; + mark_node_used_as_guard(node_router2); rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN)); rs = NULL; node_router1->is_valid = 1; - node_router2->using_as_guard = 0; + mark_node_unused_as_guard(node_router2); /* Manipulate overloaded */ @@ -420,6 +469,9 @@ test_router_pick_directory_server_impl(void *arg) done: UNMOCK(usable_consensus_flavor); + UNMOCK(is_node_used_as_guard); + clear_mock_guard_list(); + if (router1_id) tor_free(router1_id); if (router2_id) diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c index 1b526d430b..7efd042ed5 100644 --- a/src/test/test_routerset.c +++ b/src/test/test_routerset.c @@ -623,7 +623,7 @@ NS(test_main)(void *arg) (void)arg; tgt = routerset_new(); - smartlist_add(src->list, tor_strdup("{xx}")); + smartlist_add_strdup(src->list, "{xx}"); routerset_union(tgt, src); tt_int_op(smartlist_len(tgt->list), OP_NE, 0); @@ -745,7 +745,7 @@ NS(test_main)(void *arg) tt_int_op(is_empty, OP_NE, 0); set = routerset_new(); - smartlist_add(set->list, tor_strdup("{xx}")); + smartlist_add_strdup(set->list, "{xx}"); is_empty = routerset_is_empty(set); routerset_free(set); set = NULL; @@ -1616,7 +1616,7 @@ NS(test_main)(void *arg) NS_MOCK(node_get_by_nickname); NS(mock_nickname) = "foo"; - smartlist_add(set->list, tor_strdup(NS(mock_nickname))); + smartlist_add_strdup(set->list, NS(mock_nickname)); routerset_get_all_nodes(out, set, NULL, 0); out_len = smartlist_len(out); @@ -1667,7 +1667,7 @@ NS(test_main)(void *arg) NS(mock_node).is_running = 0; NS(mock_nickname) = "foo"; - smartlist_add(set->list, tor_strdup(NS(mock_nickname))); + smartlist_add_strdup(set->list, NS(mock_nickname)); routerset_get_all_nodes(out, set, NULL, 1); out_len = smartlist_len(out); @@ -1766,7 +1766,7 @@ NS(test_main)(void *arg) NS_MOCK(nodelist_get_list); - smartlist_add(set->country_names, tor_strdup("{xx}")); + smartlist_add_strdup(set->country_names, "{xx}"); NS(mock_smartlist) = smartlist_new(); routerset_get_all_nodes(out, set, NULL, 1); @@ -1813,7 +1813,7 @@ NS(test_main)(void *arg) NS_MOCK(nodelist_get_list); - smartlist_add(set->country_names, tor_strdup("{xx}")); + smartlist_add_strdup(set->country_names, "{xx}"); NS(mock_smartlist) = smartlist_new(); NS(mock_node).is_running = 0; smartlist_add(NS(mock_smartlist), (void *)&NS(mock_node)); @@ -1985,7 +1985,7 @@ NS(test_main)(void *arg) int r; (void)arg; - smartlist_add(b->list, tor_strdup("{xx}")); + smartlist_add_strdup(b->list, "{xx}"); r = routerset_equal(a, b); routerset_free(a); routerset_free(b); @@ -2010,9 +2010,9 @@ NS(test_main)(void *arg) int r; (void)arg; - smartlist_add(a->list, tor_strdup("{aa}")); - smartlist_add(b->list, tor_strdup("{b1}")); - smartlist_add(b->list, tor_strdup("{b2}")); + smartlist_add_strdup(a->list, "{aa}"); + smartlist_add_strdup(b->list, "{b1}"); + smartlist_add_strdup(b->list, "{b2}"); r = routerset_equal(a, b); routerset_free(a); routerset_free(b); @@ -2037,8 +2037,8 @@ NS(test_main)(void *arg) int r; (void)arg; - smartlist_add(a->list, tor_strdup("foo")); - smartlist_add(b->list, tor_strdup("bar")); + smartlist_add_strdup(a->list, "foo"); + smartlist_add_strdup(b->list, "bar"); r = routerset_equal(a, b); routerset_free(a); routerset_free(b); @@ -2063,8 +2063,8 @@ NS(test_main)(void *arg) int r; (void)arg; - smartlist_add(a->list, tor_strdup("foo")); - smartlist_add(b->list, tor_strdup("foo")); + smartlist_add_strdup(a->list, "foo"); + smartlist_add_strdup(b->list, "foo"); r = routerset_equal(a, b); routerset_free(a); routerset_free(b); diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c index 2e0736f99b..05ea8e86e8 100644 --- a/src/test/test_scheduler.c +++ b/src/test/test_scheduler.c @@ -1,10 +1,9 @@ /* Copyright (c) 2014-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ -#include <math.h> - #include "orconfig.h" +#include <math.h> #include <event2/event.h> #define TOR_CHANNEL_INTERNAL_ diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c index 056f199b94..d511f163e3 100644 --- a/src/test/test_shared_random.c +++ b/src/test/test_shared_random.c @@ -348,12 +348,12 @@ test_sr_commit(void *arg) /* We'll build a list of values from our commit that our parsing function * takes from a vote line and see if we can parse it correctly. */ { - smartlist_add(args, tor_strdup("1")); - smartlist_add(args, - tor_strdup(crypto_digest_algorithm_get_name(our_commit->alg))); - smartlist_add(args, tor_strdup(sr_commit_get_rsa_fpr(our_commit))); - smartlist_add(args, tor_strdup(our_commit->encoded_commit)); - smartlist_add(args, tor_strdup(our_commit->encoded_reveal)); + smartlist_add_strdup(args, "1"); + smartlist_add_strdup(args, + crypto_digest_algorithm_get_name(our_commit->alg)); + smartlist_add_strdup(args, sr_commit_get_rsa_fpr(our_commit)); + smartlist_add_strdup(args, our_commit->encoded_commit); + smartlist_add_strdup(args, our_commit->encoded_reveal); parsed_commit = sr_parse_commit(args); tt_assert(parsed_commit); /* That parsed commit should be _EXACTLY_ like our original commit (we diff --git a/src/test/test_status.c b/src/test/test_status.c index b4438aabe9..a3b1a2af87 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -3,6 +3,8 @@ #define LOG_PRIVATE #define REPHIST_PRIVATE +#include "orconfig.h" + #include <float.h> #include <math.h> diff --git a/src/test/test_util.c b/src/test/test_util.c index 224ec7bd55..7276c0cbfc 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -877,9 +877,15 @@ test_util_time(void *arg) t_res = INT64_MIN; CAPTURE(); tor_gmtime_r(&t_res, &b_time); - CHECK_TIMEGM_WARNING("Rounding up to "); - tt_assert(b_time.tm_year == (1970-1900) || - b_time.tm_year == (1-1900)); + if (! (b_time.tm_year == (1970-1900) || + b_time.tm_year == (1-1900))) { + tt_int_op(b_time.tm_year, OP_EQ, 1970-1900); + } + if (b_time.tm_year != 1970-1900) { + CHECK_TIMEGM_WARNING("Rounding up to "); + } else { + teardown_capture_of_logs(); + } } #endif @@ -1636,6 +1642,35 @@ test_util_config_line_escaped_content(void *arg) tor_free(v); } +static void +test_util_config_line_crlf(void *arg) +{ + char *k=NULL, *v=NULL; + const char *err = NULL; + (void)arg; + const char *str = + "Hello world\r\n" + "Hello \"nice big world\"\r\n"; + + str = parse_config_line_from_str_verbose(str, &k, &v, &err); + tt_assert(str); + tt_str_op(k,OP_EQ,"Hello"); + tt_str_op(v,OP_EQ,"world"); + tt_assert(!err); + tor_free(k); tor_free(v); + + str = parse_config_line_from_str_verbose(str, &k, &v, &err); + tt_assert(str); + tt_str_op(k,OP_EQ,"Hello"); + tt_str_op(v,OP_EQ,"nice big world"); + tt_assert(!err); + tor_free(k); tor_free(v); + tt_str_op(str,OP_EQ, ""); + + done: + tor_free(k); tor_free(v); +} + #ifndef _WIN32 static void test_util_expand_filename(void *arg) @@ -5068,26 +5103,62 @@ test_util_socket(void *arg) tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1); #endif - tor_close_socket(fd1); - tor_close_socket(fd2); + tor_assert(tor_close_socket == tor_close_socket__real); + + /* we use close_socket__real here so that coverity can tell that we are + * really closing these sockets. */ + tor_close_socket__real(fd1); + tor_close_socket__real(fd2); fd1 = fd2 = TOR_INVALID_SOCKET; tt_int_op(get_n_open_sockets(), OP_EQ, n + 2); - tor_close_socket(fd3); - tor_close_socket(fd4); + tor_close_socket__real(fd3); + tor_close_socket__real(fd4); fd3 = fd4 = TOR_INVALID_SOCKET; tt_int_op(get_n_open_sockets(), OP_EQ, n); done: if (SOCKET_OK(fd1)) - tor_close_socket(fd1); + tor_close_socket__real(fd1); if (SOCKET_OK(fd2)) - tor_close_socket(fd2); + tor_close_socket__real(fd2); if (SOCKET_OK(fd3)) - tor_close_socket(fd3); + tor_close_socket__real(fd3); if (SOCKET_OK(fd4)) - tor_close_socket(fd4); + tor_close_socket__real(fd4); } +#if 0 +static int +is_there_a_localhost(int family) +{ + tor_socket_t s; + s = tor_open_socket(family, SOCK_STREAM, IPPROTO_TCP); + tor_assert(SOCKET_OK(s)); + + int result = 0; + if (family == AF_INET) { + struct sockaddr_in s_in; + memset(&s_in, 0, sizeof(s_in)); + s_in.sin_family = AF_INET; + s_in.sin_addr.s_addr = htonl(0x7f000001); + s_in.sin_port = 0; + + if (bind(s, (void*)&s_in, sizeof(s_in)) == 0) { + result = 1; + } + } else if (family == AF_INET6) { + struct sockaddr_in6 sin6; + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_addr.s6_addr[15] = 1; + sin6.sin6_port = 0; + } + tor_close_socket(s); + + return result; +} +#endif + /* Test for socketpair and ersatz_socketpair(). We test them both, since * the latter is a tolerably good way to exersize tor_accept_socket(). */ static void @@ -5102,15 +5173,18 @@ test_util_socketpair(void *arg) int socketpair_result = 0; socketpair_result = tor_socketpair_fn(family, SOCK_STREAM, 0, fds); - /* If there is no 127.0.0.1 or ::1, tor_ersatz_socketpair will and must fail. + +#ifdef __FreeBSD__ + /* If there is no 127.0.0.1, tor_ersatz_socketpair will and must fail. * Otherwise, we risk exposing a socketpair on a routable IP address. (Some * BSD jails use a routable address for localhost. Fortunately, they have * the real AF_UNIX socketpair.) */ - if (ersatz && ERRNO_IS_EPROTO(-socketpair_result)) { + if (ersatz && socketpair_result < 0) { /* In my testing, an IPv6-only FreeBSD jail without ::1 returned EINVAL. * Assume we're on a machine without 127.0.0.1 or ::1 and give up now. */ - goto done; + tt_skip(); } +#endif tt_int_op(0, OP_EQ, socketpair_result); tt_assert(SOCKET_OK(fds[0])); @@ -5561,6 +5635,7 @@ struct testcase_t util_tests[] = { UTIL_LEGACY(config_line_quotes), UTIL_LEGACY(config_line_comment_character), UTIL_LEGACY(config_line_escaped_content), + UTIL_LEGACY(config_line_crlf), UTIL_LEGACY_NO_WIN(expand_filename), UTIL_LEGACY(escape_string_socks), UTIL_LEGACY(string_is_key_value), |