diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/bench.c | 10 | ||||
-rwxr-xr-x | src/test/bt_test.py | 4 | ||||
-rw-r--r-- | src/test/include.am | 58 | ||||
-rwxr-xr-x | src/test/ntor_ref.py | 2 | ||||
-rw-r--r-- | src/test/test-memwipe.c | 207 | ||||
-rwxr-xr-x | src/test/test-network.sh | 2 | ||||
-rw-r--r-- | src/test/test.c | 4 | ||||
-rw-r--r-- | src/test/test_address.c | 192 | ||||
-rw-r--r-- | src/test/test_bt.sh.in | 9 | ||||
-rw-r--r-- | src/test/test_bt_cl.c | 2 | ||||
-rw-r--r-- | src/test/test_buffers.c | 55 | ||||
-rwxr-xr-x | src/test/test_cmdline_args.py | 311 | ||||
-rw-r--r-- | src/test/test_config.c | 1771 | ||||
-rw-r--r-- | src/test/test_controller.c | 163 | ||||
-rw-r--r-- | src/test/test_controller_events.c | 99 | ||||
-rw-r--r-- | src/test/test_crypto.c | 100 | ||||
-rw-r--r-- | src/test/test_dir.c | 12 | ||||
-rw-r--r-- | src/test/test_entrynodes.c | 3 | ||||
-rw-r--r-- | src/test/test_hs.c | 257 | ||||
-rw-r--r-- | src/test/test_ntor.sh.in | 9 | ||||
-rw-r--r-- | src/test/test_status.c | 14 | ||||
-rw-r--r-- | src/test/test_util.c | 51 | ||||
-rw-r--r-- | src/test/test_util_slow.c | 2 | ||||
-rw-r--r-- | src/test/test_workqueue.c | 6 | ||||
-rw-r--r-- | src/test/test_zero_length_keys.sh.in | 10 | ||||
-rw-r--r-- | src/test/testing_common.c | 11 | ||||
-rwxr-xr-x | src/test/zero_length_keys.sh | 22 |
27 files changed, 2974 insertions, 412 deletions
diff --git a/src/test/bench.c b/src/test/bench.c index 5cbc072700..bc2b1f04d8 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -19,11 +19,9 @@ const char tor_git_revision[] = ""; #include "relay.h" #include <openssl/opensslv.h> #include <openssl/evp.h> -#ifndef OPENSSL_NO_EC #include <openssl/ec.h> #include <openssl/ecdh.h> #include <openssl/obj_mac.h> -#endif #include "config.h" #include "crypto_curve25519.h" @@ -502,9 +500,6 @@ bench_dh(void) " %f millisec each.\n", NANOCOUNT(start, end, iters)/1e6); } -#if (!defined(OPENSSL_NO_EC) \ - && OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0)) -#define HAVE_EC_BENCHMARKS static void bench_ecdh_impl(int nid, const char *name) { @@ -554,7 +549,6 @@ bench_ecdh_p224(void) { bench_ecdh_impl(NID_secp224r1, "P-224"); } -#endif typedef void (*bench_fn)(void); @@ -577,10 +571,8 @@ static struct benchmark_t benchmarks[] = { ENT(cell_aes), ENT(cell_ops), ENT(dh), -#ifdef HAVE_EC_BENCHMARKS ENT(ecdh_p256), ENT(ecdh_p224), -#endif {NULL,NULL,0} }; @@ -625,7 +617,7 @@ main(int argc, const char **argv) reset_perftime(); - crypto_seed_rng(1); + crypto_seed_rng(); crypto_init_siphash_key(); options = options_new(); init_logging(1); diff --git a/src/test/bt_test.py b/src/test/bt_test.py index 0afe797a6d..e694361703 100755 --- a/src/test/bt_test.py +++ b/src/test/bt_test.py @@ -36,7 +36,7 @@ LINES = sys.stdin.readlines() for I in range(len(LINES)): if matches(LINES[I:], FUNCNAMES): print("OK") - break + sys.exit(0) else: print("BAD") - + sys.exit(1) diff --git a/src/test/include.am b/src/test/include.am index 2a0c5437ad..0ef556a9bf 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -1,10 +1,32 @@ -TESTS += src/test/test src/test/test-slow + +TESTSCRIPTS = src/test/test_zero_length_keys.sh + +if USEPYTHON +TESTSCRIPTS += src/test/test_ntor.sh src/test/test_bt.sh +endif + +TESTS += src/test/test src/test/test-slow src/test/test-memwipe \ + $(TESTSCRIPTS) + +### This is a lovely feature, but it requires automake >= 1.12, and Tor +### doesn't require that yet. Below is a kludge to work around. +### +# TEST_EXTENSIONS = .sh +# SH_LOG_COMPILER = $(SHELL) + +check-am: set-test-permissions + +.PHONY: set-test-permissions +set-test-permissions: $(TESTSCRIPTS) + $(AM_V_at)chmod u+x $(TESTSCRIPTS) + noinst_PROGRAMS+= src/test/bench if UNITTESTS_ENABLED noinst_PROGRAMS+= \ src/test/test \ src/test/test-slow \ + src/test/test-memwipe \ src/test/test-child \ src/test/test_workqueue endif @@ -36,6 +58,7 @@ src_test_test_SOURCES = \ src/test/test_circuitmux.c \ src/test/test_config.c \ src/test/test_containers.c \ + src/test/test_controller.c \ src/test/test_controller_events.c \ src/test/test_crypto.c \ src/test/test_data.c \ @@ -77,10 +100,13 @@ src_test_test_slow_SOURCES = \ src/test/testing_common.c \ src/ext/tinytest.c +src_test_test_memwipe_SOURCES = \ + src/test/test-memwipe.c + src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) -src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS) +src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) src_test_bench_SOURCES = \ src/test/bench.c @@ -93,7 +119,7 @@ src_test_test_workqueue_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ src_test_test_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \ - src/common/libor-crypto-testing.a $(LIBDONNA) \ + src/common/libor-crypto-testing.a $(LIBDONNA) src/common/libor.a \ src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ @@ -104,6 +130,11 @@ src_test_test_slow_CFLAGS = $(src_test_test_CFLAGS) src_test_test_slow_LDADD = $(src_test_test_LDADD) src_test_test_slow_LDFLAGS = $(src_test_test_LDFLAGS) +src_test_test_memwipe_CPPFLAGS = $(src_test_test_CPPFLAGS) +src_test_test_memwipe_CFLAGS = $(src_test_test_CFLAGS) +src_test_test_memwipe_LDADD = $(src_test_test_LDADD) +src_test_test_memwipe_LDFLAGS = $(src_test_test_LDFLAGS) + src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ @@ -141,13 +172,6 @@ src_test_test_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ src_test_test_ntor_cl_AM_CPPFLAGS = \ -I"$(top_srcdir)/src/or" -NTOR_TEST_DEPS=src/test/test-ntor-cl - -if COVERAGE_ENABLED -CMDLINE_TEST_TOR = ./src/or/tor-cov -else -CMDLINE_TEST_TOR = ./src/or/tor -endif noinst_PROGRAMS += src/test/test-bt-cl src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c @@ -155,22 +179,10 @@ src_test_test_bt_cl_LDADD = src/common/libor-testing.a \ @TOR_LIB_MATH@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) -src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) - - -check-local: $(NTOR_TEST_DEPS) $(CMDLINE_TEST_TOR) -if USEPYTHON - $(PYTHON) $(top_srcdir)/src/test/test_cmdline_args.py $(CMDLINE_TEST_TOR) "${top_srcdir}" - $(PYTHON) $(top_srcdir)/src/test/ntor_ref.py test-tor - $(PYTHON) $(top_srcdir)/src/test/ntor_ref.py self-test - ./src/test/test-bt-cl assert | $(PYTHON) $(top_srcdir)/src/test/bt_test.py - ./src/test/test-bt-cl crash | $(PYTHON) $(top_srcdir)/src/test/bt_test.py -endif - $(top_srcdir)/src/test/zero_length_keys.sh +src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) EXTRA_DIST += \ src/test/bt_test.py \ src/test/ntor_ref.py \ src/test/slownacl_curve25519.py \ - src/test/test_cmdline_args.py \ src/test/zero_length_keys.sh diff --git a/src/test/ntor_ref.py b/src/test/ntor_ref.py index e37637d92a..767da57a9c 100755 --- a/src/test/ntor_ref.py +++ b/src/test/ntor_ref.py @@ -283,7 +283,7 @@ def client_part2(seckey_x, msg, node_id, pubkey_B, keyBytes=72): my_auth = H_mac(auth_input) badness = my_auth != their_auth - badness = bad_result(yx) + bad_result(bx) + badness |= bad_result(yx) + bad_result(bx) if badness: return None diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c new file mode 100644 index 0000000000..cd3900e277 --- /dev/null +++ b/src/test/test-memwipe.c @@ -0,0 +1,207 @@ +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <stdlib.h> + +#include "crypto.h" +#include "compat.h" + +#undef MIN +#define MIN(a,b) ( ((a)<(b)) ? (a) : (b) ) + +static unsigned fill_a_buffer_memset(void) __attribute__((noinline)); +static unsigned fill_a_buffer_memwipe(void) __attribute__((noinline)); +static unsigned fill_a_buffer_nothing(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_memset(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_memwipe(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_nothing(void) __attribute__((noinline)); +static unsigned check_a_buffer(void) __attribute__((noinline)); + +const char *s = NULL; + +#define FILL_BUFFER_IMPL() \ + unsigned int i; \ + unsigned sum = 0; \ + \ + /* Fill up a 1k buffer with a recognizable pattern. */ \ + for (i = 0; i < 2048; i += strlen(s)) { \ + memcpy(buf+i, s, MIN(strlen(s), 2048-i)); \ + } \ + \ + /* Use the buffer as input to a computation so the above can't get */ \ + /* optimized away. */ \ + for (i = 0; i < 2048; ++i) { \ + sum += (unsigned char)buf[i]; \ + } + +static unsigned +fill_a_buffer_memset(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + memset(buf, 0, sizeof(buf)); + return sum; +} + +static unsigned +fill_a_buffer_memwipe(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + memwipe(buf, 0, sizeof(buf)); + return sum; +} + +static unsigned +fill_a_buffer_nothing(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + return sum; +} + +static INLINE int +vmemeq(volatile char *a, const char *b, size_t n) +{ + while (n--) { + if (*a++ != *b++) + return 0; + } + return 1; +} + +static unsigned +check_a_buffer(void) +{ + unsigned int i; + volatile char buf[1024]; + unsigned sum = 0; + + /* See if this buffer has the string in it. + + YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM AN UNINITIALIZED + BUFFER. + + If you know a better way to figure out whether the compiler eliminated + the memset/memwipe calls or not, please let me know. + */ + for (i = 0; i < sizeof(buf); ++i) { + if (vmemeq(buf+i, s, strlen(s))) + ++sum; + } + + return sum; +} + +static char *heap_buf = NULL; + +static unsigned +fill_heap_buffer_memset(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + memset(buf, 0, 2048); + free(buf); + return sum; +} + +static unsigned +fill_heap_buffer_memwipe(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + memwipe(buf, 0, 2048); + free(buf); + return sum; +} + +static unsigned +fill_heap_buffer_nothing(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + free(buf); + return sum; +} + +static unsigned +check_heap_buffer(void) +{ + unsigned int i; + unsigned sum = 0; + volatile char *buf = heap_buf; + + /* See if this buffer has the string in it. + + YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM A FREED BUFFER. + + If you know a better way to figure out whether the compiler eliminated + the memset/memwipe calls or not, please let me know. + */ + for (i = 0; i < sizeof(buf); ++i) { + if (vmemeq(buf+i, s, strlen(s))) + ++sum; + } + + return sum; +} + +static struct testcase { + const char *name; + /* this spacing satisfies make check-spaces */ + unsigned + (*fill_fn)(void); + unsigned + (*check_fn)(void); +} testcases[] = { + { "nil", fill_a_buffer_nothing, check_a_buffer }, + { "nil-heap", fill_heap_buffer_nothing, check_heap_buffer }, + { "memset", fill_a_buffer_memset, check_a_buffer }, + { "memset-heap", fill_heap_buffer_memset, check_heap_buffer }, + { "memwipe", fill_a_buffer_memwipe, check_a_buffer }, + { "memwipe-heap", fill_heap_buffer_memwipe, check_heap_buffer }, + { NULL, NULL, NULL } +}; + +int +main(int argc, char **argv) +{ + unsigned x, x2; + int i; + int working = 1; + unsigned found[6]; + (void) argc; (void) argv; + + s = "squamous haberdasher gallimaufry"; + + memset(found, 0, sizeof(found)); + + for (i = 0; testcases[i].name; ++i) { + x = testcases[i].fill_fn(); + found[i] = testcases[i].check_fn(); + + x2 = fill_a_buffer_nothing(); + + if (x != x2) { + working = 0; + } + } + + if (!working || !found[0] || !found[1]) { + printf("It appears that this test case may not give you reliable " + "information. Sorry.\n"); + } + + if (!found[2] && !found[3]) { + printf("It appears that memset is good enough on this platform. Good.\n"); + } + + if (found[4] || found[5]) { + printf("ERROR: memwipe does not wipe data!\n"); + return 1; + } else { + printf("OKAY: memwipe seems to work.\n"); + return 0; + } +} + diff --git a/src/test/test-network.sh b/src/test/test-network.sh index be57cafb7f..ccfb5df424 100755 --- a/src/test/test-network.sh +++ b/src/test/test-network.sh @@ -13,7 +13,7 @@ do export TOR_DIR="$2" shift ;; - --flavo?r|--network-flavo?r) + --flavor|--flavour|--network-flavor|--network-flavour) export NETWORK_FLAVOUR="$2" shift ;; diff --git a/src/test/test.c b/src/test/test.c index dee5c001eb..7ad849f49e 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1127,6 +1127,7 @@ extern struct testcase_t circuitlist_tests[]; extern struct testcase_t circuitmux_tests[]; extern struct testcase_t config_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 dir_tests[]; @@ -1173,7 +1174,8 @@ struct testgroup_t testgroups[] = { { "circuitmux/", circuitmux_tests }, { "config/", config_tests }, { "container/", container_tests }, - { "control/", controller_event_tests }, + { "control/", controller_tests }, + { "control/event/", controller_event_tests }, { "crypto/", crypto_tests }, { "dir/", dir_tests }, { "dir/md/", microdesc_tests }, diff --git a/src/test/test_address.c b/src/test/test_address.c index 424a6352b0..d13d678f3d 100644 --- a/src/test/test_address.c +++ b/src/test/test_address.c @@ -130,8 +130,8 @@ test_address_ifaddrs_to_smartlist(void *arg) ipv6_sockaddr = tor_malloc(sizeof(struct sockaddr_in6)); ipv6_sockaddr->sin6_family = AF_INET6; ipv6_sockaddr->sin6_port = 0; - inet_pton(AF_INET6, "2001:db8:8714:3a90::12", - &(ipv6_sockaddr->sin6_addr)); + tor_inet_pton(AF_INET6, "2001:db8:8714:3a90::12", + &(ipv6_sockaddr->sin6_addr)); ifa = tor_malloc(sizeof(struct ifaddrs)); ifa_ipv4 = tor_malloc(sizeof(struct ifaddrs)); @@ -222,7 +222,7 @@ test_address_get_if_addrs_ifaddrs(void *arg) (void)arg; - results = get_interface_addresses_ifaddrs(0); + results = get_interface_addresses_ifaddrs(LOG_ERR); tt_int_op(smartlist_len(results),>=,1); tt_assert(smartlist_contains_localhost_tor_addr(results)); @@ -245,7 +245,7 @@ test_address_get_if_addrs_win32(void *arg) (void)arg; - results = get_interface_addresses_win32(0); + results = get_interface_addresses_win32(LOG_ERR); tt_int_op(smartlist_len(results),>=,1); tt_assert(smartlist_contains_localhost_tor_addr(results)); @@ -452,10 +452,194 @@ test_address_get_if_addrs_ioctl(void *arg) #endif +#define FAKE_SOCKET_FD (42) + +static tor_socket_t +fake_open_socket(int domain, int type, int protocol) +{ + (void)domain; + (void)type; + (void)protocol; + + return FAKE_SOCKET_FD; +} + +static int last_connected_socket_fd = 0; + +static int connect_retval = 0; + +static tor_socket_t +pretend_to_connect(tor_socket_t socket, const struct sockaddr *address, + socklen_t address_len) +{ + (void)address; + (void)address_len; + + last_connected_socket_fd = socket; + + return connect_retval; +} + +static struct sockaddr *mock_addr = NULL; + +static int +fake_getsockname(tor_socket_t socket, struct sockaddr *address, + socklen_t *address_len) +{ + socklen_t bytes_to_copy = 0; + (void) socket; + + if (!mock_addr) + return -1; + + if (mock_addr->sa_family == AF_INET) { + bytes_to_copy = sizeof(struct sockaddr_in); + } else if (mock_addr->sa_family == AF_INET6) { + bytes_to_copy = sizeof(struct sockaddr_in6); + } else { + return -1; + } + + if (*address_len < bytes_to_copy) { + return -1; + } + + memcpy(address,mock_addr,bytes_to_copy); + *address_len = bytes_to_copy; + + return 0; +} + +static void +test_address_udp_socket_trick_whitebox(void *arg) +{ + int hack_retval; + tor_addr_t *addr_from_hack = tor_malloc_zero(sizeof(tor_addr_t)); + struct sockaddr_in6 *mock_addr6; + struct sockaddr_in6 *ipv6_to_check = + tor_malloc_zero(sizeof(struct sockaddr_in6)); + + (void)arg; + + MOCK(tor_open_socket,fake_open_socket); + MOCK(tor_connect_socket,pretend_to_connect); + MOCK(tor_getsockname,fake_getsockname); + + mock_addr = tor_malloc_zero(sizeof(struct sockaddr_storage)); + sockaddr_in_from_string("23.32.246.118",(struct sockaddr_in *)mock_addr); + + hack_retval = + get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET, addr_from_hack); + + tt_int_op(hack_retval,==,0); + tt_assert(tor_addr_eq_ipv4h(addr_from_hack, 0x1720f676)); + + /* Now, lets do an IPv6 case. */ + memset(mock_addr,0,sizeof(struct sockaddr_storage)); + + mock_addr6 = (struct sockaddr_in6 *)mock_addr; + mock_addr6->sin6_family = AF_INET6; + mock_addr6->sin6_port = 0; + tor_inet_pton(AF_INET6,"2001:cdba::3257:9652",&(mock_addr6->sin6_addr)); + + hack_retval = + get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET6, addr_from_hack); + + tt_int_op(hack_retval,==,0); + + tor_addr_to_sockaddr(addr_from_hack,0,(struct sockaddr *)ipv6_to_check, + sizeof(struct sockaddr_in6)); + + tt_assert(sockaddr_in6_are_equal(mock_addr6,ipv6_to_check)); + + UNMOCK(tor_open_socket); + UNMOCK(tor_connect_socket); + UNMOCK(tor_getsockname); + + done: + tor_free(ipv6_to_check); + tor_free(mock_addr); + tor_free(addr_from_hack); + return; +} + +static void +test_address_udp_socket_trick_blackbox(void *arg) +{ + /* We want get_interface_address6_via_udp_socket_hack() to yield + * the same valid address that get_interface_address6() returns. + * If the latter is unable to find a valid address, we want + * _hack() to fail and return-1. + * + * Furthermore, we want _hack() never to crash, even if + * get_interface_addresses_raw() is returning NULL. + */ + + tor_addr_t addr4; + tor_addr_t addr4_to_check; + tor_addr_t addr6; + tor_addr_t addr6_to_check; + int retval, retval_reference; + + (void)arg; + +#if 0 + retval_reference = get_interface_address6(LOG_DEBUG,AF_INET,&addr4); + retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET, + &addr4_to_check); + + tt_int_op(retval,==,retval_reference); + tt_assert( (retval == -1 && retval_reference == -1) || + (tor_addr_compare(&addr4,&addr4_to_check,CMP_EXACT) == 0) ); + + retval_reference = get_interface_address6(LOG_DEBUG,AF_INET6,&addr6); + retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET6, + &addr6_to_check); + + tt_int_op(retval,==,retval_reference); + tt_assert( (retval == -1 && retval_reference == -1) || + (tor_addr_compare(&addr6,&addr6_to_check,CMP_EXACT) == 0) ); + +#else + /* Both of the blackbox test cases fail horribly if: + * * The host has no external addreses. + * * There are multiple interfaces with either AF_INET or AF_INET6. + * * The last address isn't the one associated with the default route. + * + * The tests SHOULD be re-enabled when #12377 is fixed correctly, but till + * then this fails a lot, in situations we expect failures due to knowing + * about the code being broken. + */ + + (void)addr4_to_check; + (void)addr6_to_check; + (void)addr6; + (void) retval_reference; +#endif + + /* When family is neither AF_INET nor AF_INET6, we want _hack to + * fail and return -1. + */ + + retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET+AF_INET6,&addr4); + + tt_assert(retval == -1); + + done: + return; +} + #define ADDRESS_TEST(name, flags) \ { #name, test_address_ ## name, flags, NULL, NULL } struct testcase_t address_tests[] = { + ADDRESS_TEST(udp_socket_trick_whitebox, TT_FORK), + ADDRESS_TEST(udp_socket_trick_blackbox, TT_FORK), #ifdef HAVE_IFADDRS_TO_SMARTLIST ADDRESS_TEST(get_if_addrs_ifaddrs, TT_FORK), ADDRESS_TEST(ifaddrs_to_smartlist, 0), diff --git a/src/test/test_bt.sh.in b/src/test/test_bt.sh.in new file mode 100644 index 0000000000..ca8be965d4 --- /dev/null +++ b/src/test/test_bt.sh.in @@ -0,0 +1,9 @@ +#!@SHELL@ +# Test backtrace functionality. + +exitcode=0 + +@builddir@/src/test/test-bt-cl assert | @PYTHON@ @abs_top_srcdir@/src/test/bt_test.py || exitcode=1 +@builddir@/src/test/test-bt-cl crash | @PYTHON@ @abs_top_srcdir@/src/test/bt_test.py || exitcode=1 + +exit ${exitcode} diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c index 0fa0cd5c0a..01c621eb0e 100644 --- a/src/test/test_bt_cl.c +++ b/src/test/test_bt_cl.c @@ -5,6 +5,8 @@ #include <stdio.h> #include <stdlib.h> +/* To prevent 'assert' from going away. */ +#undef TOR_COVERAGE #include "or.h" #include "util.h" #include "backtrace.h" diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c index 0ede8081d8..22ee6aa8e3 100644 --- a/src/test/test_buffers.c +++ b/src/test/test_buffers.c @@ -698,6 +698,59 @@ test_buffers_zlib_fin_at_chunk_end(void *arg) tor_free(msg); } +const uint8_t *tls_read_ptr; +int n_remaining; +int next_reply_val[16]; + +static int +mock_tls_read(tor_tls_t *tls, char *cp, size_t len) +{ + (void)tls; + int rv = next_reply_val[0]; + if (rv > 0) { + int max = rv > (int)len ? (int)len : rv; + if (max > n_remaining) + max = n_remaining; + memcpy(cp, tls_read_ptr, max); + rv = max; + n_remaining -= max; + tls_read_ptr += max; + } + + memmove(next_reply_val, next_reply_val + 1, 15*sizeof(int)); + return rv; +} + +static void +test_buffers_tls_read_mocked(void *arg) +{ + uint8_t *mem; + buf_t *buf; + (void)arg; + + mem = tor_malloc(64*1024); + crypto_rand((char*)mem, 64*1024); + tls_read_ptr = mem; + n_remaining = 64*1024; + + MOCK(tor_tls_read, mock_tls_read); + + buf = buf_new(); + + next_reply_val[0] = 1024; + tt_int_op(128, ==, read_to_buf_tls(NULL, 128, buf)); + + next_reply_val[0] = 5000; + next_reply_val[1] = 5000; + tt_int_op(6000, ==, read_to_buf_tls(NULL, 6000, buf)); + + + done: + UNMOCK(tor_tls_read); + tor_free(mem); + buf_free(buf); +} + struct testcase_t buffer_tests[] = { { "basic", test_buffers_basic, TT_FORK, NULL, NULL }, { "copy", test_buffer_copy, TT_FORK, NULL, NULL }, @@ -710,6 +763,8 @@ struct testcase_t buffer_tests[] = { { "zlib_fin_with_nil", test_buffers_zlib_fin_with_nil, TT_FORK, NULL, NULL }, { "zlib_fin_at_chunk_end", test_buffers_zlib_fin_at_chunk_end, TT_FORK, NULL, NULL}, + { "tls_read_mocked", test_buffers_tls_read_mocked, 0, + NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_cmdline_args.py b/src/test/test_cmdline_args.py deleted file mode 100755 index 57641974db..0000000000 --- a/src/test/test_cmdline_args.py +++ /dev/null @@ -1,311 +0,0 @@ -#!/usr/bin/python - -import binascii -import hashlib -import os -import re -import shutil -import subprocess -import sys -import tempfile -import unittest - -TOR = "./src/or/tor" -TOP_SRCDIR = "." - -if len(sys.argv) > 1: - TOR = sys.argv[1] - del sys.argv[1] - -if len(sys.argv) > 1: - TOP_SRCDIR = sys.argv[1] - del sys.argv[1] - -class UnexpectedSuccess(Exception): - pass - -class UnexpectedFailure(Exception): - pass - -if sys.version < '3': - def b2s(b): - return b - def s2b(s): - return s - def NamedTemporaryFile(): - return tempfile.NamedTemporaryFile(delete=False) -else: - def b2s(b): - return str(b, 'ascii') - def s2b(s): - return s.encode('ascii') - def NamedTemporaryFile(): - return tempfile.NamedTemporaryFile(mode="w",delete=False,encoding="ascii") - -def contents(fn): - f = open(fn) - try: - return f.read() - finally: - f.close() - -def run_tor(args, failure=False, stdin=None): - kwargs = {} - if stdin != None: - kwargs['stdin'] = subprocess.PIPE - p = subprocess.Popen([TOR] + args, stdout=subprocess.PIPE, **kwargs) - output, _ = p.communicate(input=stdin) - result = p.poll() - if result and not failure: - raise UnexpectedFailure() - elif not result and failure: - raise UnexpectedSuccess() - return b2s(output.replace('\r\n','\n')) - -def spaceify_fp(fp): - for i in range(0, len(fp), 4): - yield fp[i:i+4] - -def lines(s): - out = s.splitlines() - if out and out[-1] == '': - del out[-1] - return out - -def strip_log_junk(line): - m = re.match(r'([^\[]+\[[a-z]*\] *)(.*)', line) - if not m: - return ""+line - return m.group(2).strip() - -def randstring(entropy_bytes): - s = os.urandom(entropy_bytes) - return b2s(binascii.b2a_hex(s)) - -def findLineContaining(lines, s): - for ln in lines: - if s in ln: - return True - return False - -class CmdlineTests(unittest.TestCase): - - def test_version(self): - out = run_tor(["--version"]) - self.assertTrue(out.startswith("Tor version ")) - self.assertEqual(len(lines(out)), 1) - - def test_quiet(self): - out = run_tor(["--quiet", "--quumblebluffin", "1"], failure=True) - self.assertEqual(out, "") - - def test_help(self): - out = run_tor(["--help"], failure=False) - out2 = run_tor(["-h"], failure=False) - self.assertTrue(out.startswith("Copyright (c) 2001")) - self.assertTrue(out.endswith( - "tor -f <torrc> [args]\n" - "See man page for options, or https://www.torproject.org/ for documentation.\n")) - self.assertTrue(out == out2) - - def test_hush(self): - torrc = NamedTemporaryFile() - torrc.close() - try: - out = run_tor(["--hush", "-f", torrc.name, - "--quumblebluffin", "1"], failure=True) - finally: - os.unlink(torrc.name) - self.assertEqual(len(lines(out)), 2) - ln = [ strip_log_junk(l) for l in lines(out) ] - self.assertEqual(ln[0], "Failed to parse/validate config: Unknown option 'quumblebluffin'. Failing.") - self.assertEqual(ln[1], "Reading config failed--see warnings above.") - - def test_missing_argument(self): - out = run_tor(["--hush", "--hash-password"], failure=True) - self.assertEqual(len(lines(out)), 2) - ln = [ strip_log_junk(l) for l in lines(out) ] - self.assertEqual(ln[0], "Command-line option '--hash-password' with no value. Failing.") - - def test_hash_password(self): - out = run_tor(["--hash-password", "woodwose"]) - result = lines(out)[-1] - self.assertEqual(result[:3], "16:") - self.assertEqual(len(result), 61) - r = binascii.a2b_hex(result[3:]) - self.assertEqual(len(r), 29) - - salt, how, hashed = r[:8], r[8], r[9:] - self.assertEqual(len(hashed), 20) - if type(how) == type("A"): - how = ord(how) - - count = (16 + (how & 15)) << ((how >> 4) + 6) - stuff = salt + s2b("woodwose") - repetitions = count // len(stuff) + 1 - inp = stuff * repetitions - inp = inp[:count] - - self.assertEqual(hashlib.sha1(inp).digest(), hashed) - - def test_digests(self): - main_c = os.path.join(TOP_SRCDIR, "src", "or", "main.c") - - if os.stat(TOR).st_mtime < os.stat(main_c).st_mtime: - self.skipTest(TOR+" not up to date") - out = run_tor(["--digests"]) - main_line = [ l for l in lines(out) if l.endswith("/main.c") or l.endswith(" main.c") ] - digest, name = main_line[0].split() - f = open(main_c, 'rb') - actual = hashlib.sha1(f.read()).hexdigest() - f.close() - self.assertEqual(digest, actual) - - def test_dump_options(self): - default_torrc = NamedTemporaryFile() - torrc = NamedTemporaryFile() - torrc.write("SocksPort 9999") - torrc.close() - default_torrc.write("SafeLogging 0") - default_torrc.close() - out_sh = out_nb = out_fl = None - opts = [ "-f", torrc.name, - "--defaults-torrc", default_torrc.name ] - try: - out_sh = run_tor(["--dump-config", "short"]+opts) - out_nb = run_tor(["--dump-config", "non-builtin"]+opts) - out_fl = run_tor(["--dump-config", "full"]+opts) - out_nr = run_tor(["--dump-config", "bliznert"]+opts, - failure=True) - - out_verif = run_tor(["--verify-config"]+opts) - finally: - os.unlink(torrc.name) - os.unlink(default_torrc.name) - - self.assertEqual(len(lines(out_sh)), 2) - self.assertTrue(lines(out_sh)[0].startswith("DataDirectory ")) - self.assertEqual(lines(out_sh)[1:], - [ "SocksPort 9999" ]) - - self.assertEqual(len(lines(out_nb)), 2) - self.assertEqual(lines(out_nb), - [ "SafeLogging 0", - "SocksPort 9999" ]) - - out_fl = lines(out_fl) - self.assertTrue(len(out_fl) > 100) - self.assertTrue("SocksPort 9999" in out_fl) - self.assertTrue("SafeLogging 0" in out_fl) - self.assertTrue("ClientOnly 0" in out_fl) - - self.assertTrue(out_verif.endswith("Configuration was valid\n")) - - def test_list_fingerprint(self): - tmpdir = tempfile.mkdtemp(prefix='ttca_') - torrc = NamedTemporaryFile() - torrc.write("ORPort 9999\n") - torrc.write("DataDirectory %s\n"%tmpdir) - torrc.write("Nickname tippi") - torrc.close() - opts = ["-f", torrc.name] - try: - out = run_tor(["--list-fingerprint"]+opts) - fp = contents(os.path.join(tmpdir, "fingerprint")) - finally: - os.unlink(torrc.name) - shutil.rmtree(tmpdir) - - out = lines(out) - lastlog = strip_log_junk(out[-2]) - lastline = out[-1] - fp = fp.strip() - nn_fp = fp.split()[0] - space_fp = " ".join(spaceify_fp(fp.split()[1])) - self.assertEqual(lastlog, - "Your Tor server's identity key fingerprint is '%s'"%fp) - self.assertEqual(lastline, "tippi %s"%space_fp) - self.assertEqual(nn_fp, "tippi") - - def test_list_options(self): - out = lines(run_tor(["--list-torrc-options"])) - self.assertTrue(len(out)>100) - self.assertTrue(out[0] <= 'AccountingMax') - self.assertTrue("UseBridges" in out) - self.assertTrue("SocksPort" in out) - - def test_cmdline_args(self): - default_torrc = NamedTemporaryFile() - torrc = NamedTemporaryFile() - contents = ("SocksPort 9999\n" - "SocksPort 9998\n" - "ORPort 9000\n" - "ORPort 9001\n" - "Nickname eleventeen\n" - "ControlPort 9500\n") - torrc.write(contents) - default_torrc.write("") - default_torrc.close() - torrc.close() - out_sh = out_nb = out_fl = None - - opts_stdin = [ "-f", "-", - "--defaults-torrc", default_torrc.name, - "--dump-config", "short" ] - opts = [ "-f", torrc.name, - "--defaults-torrc", default_torrc.name, - "--dump-config", "short" ] - try: - out_0 = run_tor(opts_stdin,stdin=contents) - out_1 = run_tor(opts) - out_2 = run_tor(opts+["+ORPort", "9003", - "SocksPort", "9090", - "/ControlPort", - "/TransPort", - "+ExtORPort", "9005"]) - finally: - os.unlink(torrc.name) - os.unlink(default_torrc.name) - - out_0 = [ l for l in lines(out_0) if not l.startswith("DataDir") ] - out_1 = [ l for l in lines(out_1) if not l.startswith("DataDir") ] - out_2 = [ l for l in lines(out_2) if not l.startswith("DataDir") ] - - self.assertEqual(out_0, - ["ControlPort 9500", - "Nickname eleventeen", - "ORPort 9000", - "ORPort 9001", - "SocksPort 9999", - "SocksPort 9998"]) - - self.assertEqual(out_1, - ["ControlPort 9500", - "Nickname eleventeen", - "ORPort 9000", - "ORPort 9001", - "SocksPort 9999", - "SocksPort 9998"]) - - self.assertEqual(out_2, - ["ExtORPort 9005", - "Nickname eleventeen", - "ORPort 9000", - "ORPort 9001", - "ORPort 9003", - "SocksPort 9090"]) - - def test_missing_torrc(self): - fname = "nonexistent_file_"+randstring(8) - out = run_tor(["-f", fname, "--verify-config"], failure=True) - ln = [ strip_log_junk(l) for l in lines(out) ] - self.assertTrue("Unable to open configuration file" in ln[-2]) - self.assertTrue("Reading config failed" in ln[-1]) - - out = run_tor(["-f", fname, "--verify-config", "--ignore-missing-torrc"]) - ln = [ strip_log_junk(l) for l in lines(out) ] - self.assertTrue(findLineContaining(ln, ", using reasonable defaults")) - self.assertTrue("Configuration was valid" in ln[-1]) - -if __name__ == '__main__': - unittest.main() diff --git a/src/test/test_config.c b/src/test/test_config.c index 0444062722..28e9fa0f32 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -17,6 +17,7 @@ #include "address.h" #include "entrynodes.h" #include "transports.h" +#include "routerlist.h" static void test_config_addressmap(void *arg) @@ -1036,7 +1037,7 @@ static int n_get_interface_address6_failure = 0; /** * This mock function is meant to replace get_interface_addres6(). - * It will pretent to fail by return -1. + * It will pretend to fail by return -1. * <b>n_get_interface_address6_failure</b> is incremented by one * every time this function is called and <b>last_address6_family</b> * is assigned the value of <b>family</b> argument. @@ -1405,7 +1406,7 @@ test_config_resolve_my_address(void *arg) /* CASE 12: * Suppose the following happens: - * 1. options->Address is NULL AND options->DirAuthorities is 1. + * 1. options->Address is NULL AND options->DirAuthorities is non-NULL * 2. tor_gethostname() succeeds in getting hostname of a machine ... * 3. ... which is successfully parsed by tor_inet_aton() ... * 4. into IPv4 address that tor_addr_is_inernal() considers to be @@ -1443,10 +1444,1776 @@ test_config_resolve_my_address(void *arg) UNMOCK(tor_gethostname); } +static int n_add_default_fallback_dir_servers_known_default = 0; + +/** + * This mock function is meant to replace add_default_fallback_dir_servers(). + * It will parse and add one known default fallback dir server, + * which has a dir_port of 99. + * <b>n_add_default_fallback_dir_servers_known_default</b> is incremented by + * one every time this function is called. + */ +static void +add_default_fallback_dir_servers_known_default(void) +{ + int i; + const char *fallback[] = { + "127.0.0.1:60099 orport=9009 " + "id=0923456789012345678901234567890123456789", + NULL + }; + for (i=0; fallback[i]; i++) { + if (parse_dir_fallback_line(fallback[i], 0)<0) { + log_err(LD_BUG, "Couldn't parse internal FallbackDir line %s", + fallback[i]); + } + } + n_add_default_fallback_dir_servers_known_default++; +} + +static void +test_config_adding_dir_servers(void *arg) +{ + (void)arg; + + /* allocate options */ + or_options_t *options = tor_malloc(sizeof(or_options_t)); + + /* Allocate and populate configuration lines: + * + * Use the same format as the hard-coded directories in + * add_default_trusted_dir_authorities(). + * Zeroing the structure has the same effect as initialising to: + * { NULL, NULL, NULL, CONFIG_LINE_NORMAL, 0}; + */ + config_line_t *test_dir_authority = tor_malloc(sizeof(config_line_t)); + memset(test_dir_authority, 0, sizeof(config_line_t)); + test_dir_authority->key = tor_strdup("DirAuthority"); + test_dir_authority->value = tor_strdup( + "D0 orport=9000 " + "v3ident=0023456789012345678901234567890123456789 " + "127.0.0.1:60090 0123 4567 8901 2345 6789 0123 4567 8901 2345 6789" + ); + + config_line_t *test_alt_bridge_authority = tor_malloc(sizeof(config_line_t)); + memset(test_alt_bridge_authority, 0, sizeof(config_line_t)); + test_alt_bridge_authority->key = tor_strdup("AlternateBridgeAuthority"); + test_alt_bridge_authority->value = tor_strdup( + "B1 orport=9001 bridge " + "127.0.0.1:60091 1123 4567 8901 2345 6789 0123 4567 8901 2345 6789" + ); + + config_line_t *test_alt_dir_authority = tor_malloc(sizeof(config_line_t)); + memset(test_alt_dir_authority, 0, sizeof(config_line_t)); + test_alt_dir_authority->key = tor_strdup("AlternateDirAuthority"); + test_alt_dir_authority->value = tor_strdup( + "A2 orport=9002 " + "v3ident=0223456789012345678901234567890123456789 " + "127.0.0.1:60092 2123 4567 8901 2345 6789 0123 4567 8901 2345 6789" + ); + + /* Use the format specified in the manual page */ + config_line_t *test_fallback_directory = tor_malloc(sizeof(config_line_t)); + memset(test_fallback_directory, 0, sizeof(config_line_t)); + test_fallback_directory->key = tor_strdup("FallbackDir"); + test_fallback_directory->value = tor_strdup( + "127.0.0.1:60093 orport=9003 id=0323456789012345678901234567890123456789" + ); + + /* We need to know if add_default_fallback_dir_servers is called, + * so we use a version of add_default_fallback_dir_servers that adds + * one known default fallback directory. + * There doesn't appear to be any need to test it unmocked. */ + MOCK(add_default_fallback_dir_servers, + add_default_fallback_dir_servers_known_default); + + /* There are 16 different cases, covering each combination of set/NULL for: + * DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority & + * FallbackDir. + * But validate_dir_servers() ensures that: + * "You cannot set both DirAuthority and Alternate*Authority." + * This reduces the number of cases to 10. + * + * Let's count these cases using binary, with 1 meaning set & 0 meaning NULL + * So 1001 or case 9 is: + * DirAuthorities set, + * AlternateBridgeAuthority NULL, + * AlternateDirAuthority NULL + * FallbackDir set + * The valid cases are cases 0-9 counting using this method, as every case + * greater than or equal to 10 = 1010 is invalid. + * + * After #15642 - Disable default fallback dirs when any custom dirs set + * + * 1. Outcome: Use Set Directory Authorities + * - No Default Authorities + * - Use AlternateBridgeAuthority, AlternateDirAuthority, and FallbackDir + * if they are set + * Cases expected to yield this outcome: + * 8 & 9 (the 2 valid cases where DirAuthorities is set) + * 6 & 7 (the 2 cases where DirAuthorities is NULL, and + * AlternateBridgeAuthority and AlternateDirAuthority are both set) + * + * 2. Outcome: Use Set Bridge Authority + * - Use Default Non-Bridge Directory Authorities + * - Use FallbackDir if it is set, otherwise use default FallbackDir + * Cases expected to yield this outcome: + * 4 & 5 (the 2 cases where DirAuthorities is NULL, + * AlternateBridgeAuthority is set, and + * AlternateDirAuthority is NULL) + * + * 3. Outcome: Use Set Alternate Directory Authority + * - Use Default Bridge Authorities + * - Use FallbackDir if it is set, otherwise No Default Fallback Directories + * Cases expected to yield this outcome: + * 2 & 3 (the 2 cases where DirAuthorities and AlternateBridgeAuthority + * are both NULL, but AlternateDirAuthority is set) + * + * 4. Outcome: Use Set Custom Fallback Directory + * - Use Default Bridge & Directory Authorities + * Cases expected to yield this outcome: + * 1 (DirAuthorities, AlternateBridgeAuthority and AlternateDirAuthority + * are all NULL, but FallbackDir is set) + * + * 5. Outcome: Use All Defaults + * - Use Default Bridge & Directory Authorities, and + * Default Fallback Directories + * Cases expected to yield this outcome: + * 0 (DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority + * and FallbackDir are all NULL) + * + * Before #15642 but after #13163 - Stop using default authorities when both + * Alternate Dir and Bridge Authority are set + * (#13163 was committed in 0.2.6 as c1dd43d823c7) + * + * The behaviour is different in the following cases + * where FallbackDir is NULL: + * 2, 6, 8 + * + * In these cases, the Default Fallback Directories are applied, even when + * DirAuthorities or AlternateDirAuthority are set. + * + * However, as the list of default fallback directories is currently empty, + * this change doesn't modify any user-visible behaviour. + */ + + /* + * Find out how many default Bridge, Non-Bridge and Fallback Directories + * are hard-coded into this build. + * This code makes some assumptions about the implementation. + * If they are wrong, one or more of cases 0-5 could fail. + */ + int n_default_alt_bridge_authority = 0; + int n_default_alt_dir_authority = 0; + int n_default_fallback_dir = 0; +#define n_default_authorities ((n_default_alt_bridge_authority) \ + + (n_default_alt_dir_authority)) + + /* Pre-Count Number of Authorities of Each Type + * Use 0000: No Directory Authorities or Fallback Directories Set + */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0000 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + + /* Count Bridge Authorities */ + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if it's a bridge auth */ + n_default_alt_bridge_authority += + ((ds->is_authority && (ds->type & BRIDGE_DIRINFO)) ? + 1 : 0) + ); + /* If we have no default bridge authority, something has gone wrong */ + tt_assert(n_default_alt_bridge_authority >= 1); + + /* Count v3 Authorities */ + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment found counter if it's a v3 auth */ + n_default_alt_dir_authority += + ((ds->is_authority && (ds->type & V3_DIRINFO)) ? + 1 : 0) + ); + /* If we have no default authorities, something has gone really wrong */ + tt_assert(n_default_alt_dir_authority >= 1); + + /* Calculate Fallback Directory Count */ + n_default_fallback_dir = (smartlist_len(fallback_servers) - + n_default_alt_bridge_authority - + n_default_alt_dir_authority); + /* If we have a negative count, something has gone really wrong */ + tt_assert(n_default_fallback_dir >= 0); + } + } + + /* + * 1. Outcome: Use Set Directory Authorities + * - No Default Authorities + * - Use AlternateBridgeAuthority, AlternateDirAuthority, and FallbackDir + * if they are set + * Cases expected to yield this outcome: + * 8 & 9 (the 2 valid cases where DirAuthorities is set) + * 6 & 7 (the 2 cases where DirAuthorities is NULL, and + * AlternateBridgeAuthority and AlternateDirAuthority are both set) + */ + + /* Case 9: 1001 - DirAuthorities Set, AlternateBridgeAuthority Not Set, + AlternateDirAuthority Not Set, FallbackDir Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 1001 */ + options->DirAuthorities = test_dir_authority; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* D0, (No B1), (No A2) */ + tt_assert(smartlist_len(dir_servers) == 1); + + /* DirAuthority - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 1); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* D0, (No B1), (No A2), Custom Fallback */ + tt_assert(smartlist_len(fallback_servers) == 2); + + /* DirAuthority - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 1); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + } + } + + /* Case 8: 1000 - DirAuthorities Set, Others Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 1000 */ + options->DirAuthorities = test_dir_authority; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* D0, (No B1), (No A2) */ + tt_assert(smartlist_len(dir_servers) == 1); + + /* DirAuthority - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 1); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* D0, (No B1), (No A2), (No Fallback) */ + tt_assert(smartlist_len(fallback_servers) == 1); + + /* DirAuthority - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 1); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + } + } + + /* Case 7: 0111 - DirAuthorities Not Set, Others Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0111 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = test_alt_bridge_authority; + options->AlternateDirAuthority = test_alt_dir_authority; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), B1, A2 */ + tt_assert(smartlist_len(dir_servers) == 2); + + /* (No DirAuthority) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), B1, A2, Custom Fallback */ + tt_assert(smartlist_len(fallback_servers) == 3); + + /* (No DirAuthority) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + } + } + + /* Case 6: 0110 - DirAuthorities Not Set, AlternateBridgeAuthority & + AlternateDirAuthority Set, FallbackDir Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0110 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = test_alt_bridge_authority; + options->AlternateDirAuthority = test_alt_dir_authority; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), B1, A2 */ + tt_assert(smartlist_len(dir_servers) == 2); + + /* (No DirAuthority) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), B1, A2, (No Fallback) */ + tt_assert(smartlist_len(fallback_servers) == 2); + + /* (No DirAuthority) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + } + } + + /* + 2. Outcome: Use Set Bridge Authority + - Use Default Non-Bridge Directory Authorities + - Use FallbackDir if it is set, otherwise use default FallbackDir + Cases expected to yield this outcome: + 4 & 5 (the 2 cases where DirAuthorities is NULL, + AlternateBridgeAuthority is set, and + AlternateDirAuthority is NULL) + */ + + /* Case 5: 0101 - DirAuthorities Not Set, AlternateBridgeAuthority Set, + AlternateDirAuthority Not Set, FallbackDir Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0101 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = test_alt_bridge_authority; + options->AlternateDirAuthority = NULL; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities */ + tt_assert(smartlist_len(dir_servers) == 1 + n_default_alt_dir_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* There's no easy way of checking that we have included all the + * default v3 non-Bridge directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities, + * Custom Fallback */ + tt_assert(smartlist_len(fallback_servers) == + 2 + n_default_alt_dir_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + + /* There's no easy way of checking that we have included all the + * default v3 non-Bridge directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + } + + /* Case 4: 0100 - DirAuthorities Not Set, AlternateBridgeAuthority Set, + AlternateDirAuthority & FallbackDir Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0100 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = test_alt_bridge_authority; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities */ + tt_assert(smartlist_len(dir_servers) == 1 + n_default_alt_dir_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* There's no easy way of checking that we have included all the + * default v3 non-Bridge directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), B1, (No A2), Default v3 Non-Bridge Authorities, + * Default Fallback */ + tt_assert(smartlist_len(fallback_servers) == + 2 + n_default_alt_dir_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* AlternateBridgeAuthority - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 1); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* Default FallbackDir - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 1); + + /* There's no easy way of checking that we have included all the + * default v3 non-Bridge directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + } + + /* + 3. Outcome: Use Set Alternate Directory Authority + - Use Default Bridge Authorities + - Use FallbackDir if it is set, otherwise No Default Fallback Directories + Cases expected to yield this outcome: + 2 & 3 (the 2 cases where DirAuthorities and AlternateBridgeAuthority + are both NULL, but AlternateDirAuthority is set) + */ + + /* Case 3: 0011 - DirAuthorities & AlternateBridgeAuthority Not Set, + AlternateDirAuthority & FallbackDir Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0011 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = test_alt_dir_authority; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, A2 */ + tt_assert(smartlist_len(dir_servers) == + 1 + n_default_alt_bridge_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* There's no easy way of checking that we have included all the + * default Bridge authorities (except for hard-coding tonga's details), + * so let's assume that if the total count above is correct, + * we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, A2, + * Custom Fallback Directory, (No Default Fallback Directories) */ + tt_assert(smartlist_len(fallback_servers) == + 2 + n_default_alt_bridge_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge authorities (except for hard-coding tonga's details), + * so let's assume that if the total count above is correct, + * we have the right ones. + */ + } + } + + /* Case 2: 0010 - DirAuthorities & AlternateBridgeAuthority Not Set, + AlternateDirAuthority Set, FallbackDir Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0010 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = test_alt_dir_authority; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, A2, + * No Default or Custom Fallback Directories */ + tt_assert(smartlist_len(dir_servers) == + 1 + n_default_alt_bridge_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* There's no easy way of checking that we have included all the + * default Bridge authorities (except for hard-coding tonga's details), + * so let's assume that if the total count above is correct, + * we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, A2, + * No Custom or Default Fallback Directories */ + tt_assert(smartlist_len(fallback_servers) == + 1 + n_default_alt_bridge_authority); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* AlternateDirAuthority - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 1); + + /* (No Custom FallbackDir) - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge authorities (except for hard-coding tonga's details), + * so let's assume that if the total count above is correct, + * we have the right ones. + */ + } + } + + /* + 4. Outcome: Use Set Custom Fallback Directory + - Use Default Bridge & Directory Authorities + Cases expected to yield this outcome: + 1 (DirAuthorities, AlternateBridgeAuthority and AlternateDirAuthority + are all NULL, but FallbackDir is set) + */ + + /* Case 1: 0001 - DirAuthorities, AlternateBridgeAuthority + & AlternateDirAuthority Not Set, FallbackDir Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0001 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = test_fallback_directory; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must not have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 0); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, + * (No A2), Default v3 Directory Authorities */ + tt_assert(smartlist_len(dir_servers) == n_default_authorities); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge & V3 Directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, + * (No A2), Default v3 Directory Authorities, + * Custom Fallback Directory, (No Default Fallback Directories) */ + tt_assert(smartlist_len(fallback_servers) == + 1 + n_default_authorities); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 1); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge & V3 Directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + } + + /* + 5. Outcome: Use All Defaults + - Use Default Bridge & Directory Authorities, Default Fallback Directories + Cases expected to yield this outcome: + 0 (DirAuthorities, AlternateBridgeAuthority, AlternateDirAuthority + and FallbackDir are all NULL) + */ + + /* Case 0: 0000 - All Not Set */ + { + /* clear fallback dirs counter */ + n_add_default_fallback_dir_servers_known_default = 0; + + /* clear options*/ + memset(options, 0, sizeof(or_options_t)); + + /* clear any previous dir servers: + consider_adding_dir_servers() should do this anyway */ + clear_dir_servers(); + + /* assign options: 0001 */ + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + + /* parse options - ensure we always update by passing NULL old_options */ + consider_adding_dir_servers(options, NULL); + + /* check outcome */ + + /* we must have added the default fallback dirs */ + tt_assert(n_add_default_fallback_dir_servers_known_default == 1); + + { + /* trusted_dir_servers */ + const smartlist_t *dir_servers = router_get_trusted_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, + * (No A2), Default v3 Directory Authorities */ + tt_assert(smartlist_len(dir_servers) == n_default_authorities); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(dir_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* There's no easy way of checking that we have included all the + * default Bridge & V3 Directory authorities, so let's assume that + * if the total count above is correct, we have the right ones. + */ + } + + { + /* fallback_dir_servers */ + const smartlist_t *fallback_servers = router_get_fallback_dir_servers(); + /* (No D0), (No B1), Default Bridge Authorities, + * (No A2), Default v3 Directory Authorities, + * (No Custom Fallback Directory), Default Fallback Directories */ + tt_assert(smartlist_len(fallback_servers) == + n_default_authorities + n_default_fallback_dir); + + /* (No DirAuthorities) - D0 - dir_port: 60090 */ + int found_D0 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_D0 += + (ds->dir_port == 60090 ? + 1 : 0) + ); + tt_assert(found_D0 == 0); + + /* (No AlternateBridgeAuthority) - B1 - dir_port: 60091 */ + int found_B1 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_B1 += + (ds->dir_port == 60091 ? + 1 : 0) + ); + tt_assert(found_B1 == 0); + + /* (No AlternateDirAuthority) - A2 - dir_port: 60092 */ + int found_A2 = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_A2 += + (ds->dir_port == 60092 ? + 1 : 0) + ); + tt_assert(found_A2 == 0); + + /* Custom FallbackDir - No Nickname - dir_port: 60093 */ + int found_non_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_non_default_fallback += + (ds->dir_port == 60093 ? + 1 : 0) + ); + tt_assert(found_non_default_fallback == 0); + + /* (No Default FallbackDir) - No Nickname - dir_port: 60099 */ + int found_default_fallback = 0; + SMARTLIST_FOREACH(fallback_servers, + dir_server_t *, + ds, + /* increment the found counter if dir_port matches */ + found_default_fallback += + (ds->dir_port == 60099 ? + 1 : 0) + ); + tt_assert(found_default_fallback == 1); + + /* There's no easy way of checking that we have included all the + * default Bridge & V3 Directory authorities, and the default + * Fallback Directories, so let's assume that if the total count + * above is correct, we have the right ones. + */ + } + } + + done: + clear_dir_servers(); + + tor_free(test_dir_authority->key); + tor_free(test_dir_authority->value); + tor_free(test_dir_authority); + + tor_free(test_alt_dir_authority->key); + tor_free(test_alt_dir_authority->value); + tor_free(test_alt_dir_authority); + + tor_free(test_alt_bridge_authority->key); + tor_free(test_alt_bridge_authority->value); + tor_free(test_alt_bridge_authority); + + tor_free(test_fallback_directory->key); + tor_free(test_fallback_directory->value); + tor_free(test_fallback_directory); + + options->DirAuthorities = NULL; + options->AlternateBridgeAuthority = NULL; + options->AlternateDirAuthority = NULL; + options->FallbackDir = NULL; + or_options_free(options); + + UNMOCK(add_default_fallback_dir_servers); +} + #define CONFIG_TEST(name, flags) \ { #name, test_config_ ## name, flags, NULL, NULL } struct testcase_t config_tests[] = { + CONFIG_TEST(adding_dir_servers, TT_FORK), CONFIG_TEST(resolve_my_address, TT_FORK), CONFIG_TEST(addressmap, 0), CONFIG_TEST(parse_bridge_line, 0), diff --git a/src/test/test_controller.c b/src/test/test_controller.c new file mode 100644 index 0000000000..b40825bb5d --- /dev/null +++ b/src/test/test_controller.c @@ -0,0 +1,163 @@ +/* Copyright (c) 2015, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define CONTROL_PRIVATE +#include "or.h" +#include "control.h" +#include "rendservice.h" +#include "test.h" + +static void +test_add_onion_helper_keyarg(void *arg) +{ + crypto_pk_t *pk = NULL; + crypto_pk_t *pk2 = NULL; + const char *key_new_alg = NULL; + char *key_new_blob = NULL; + char *err_msg = NULL; + char *encoded = NULL; + char *arg_str = NULL; + + (void) arg; + + /* Test explicit RSA1024 key generation. */ + pk = add_onion_helper_keyarg("NEW:RSA1024", 0, &key_new_alg, &key_new_blob, + &err_msg); + tt_assert(pk); + tt_str_op(key_new_alg, OP_EQ, "RSA1024"); + tt_assert(key_new_blob); + tt_assert(!err_msg); + + /* Test "BEST" key generation (Assumes BEST = RSA1024). */ + crypto_pk_free(pk); + tor_free(key_new_blob); + pk = add_onion_helper_keyarg("NEW:BEST", 0, &key_new_alg, &key_new_blob, + &err_msg); + tt_assert(pk); + tt_str_op(key_new_alg, OP_EQ, "RSA1024"); + tt_assert(key_new_blob); + tt_assert(!err_msg); + + /* Test discarding the private key. */ + crypto_pk_free(pk); + tor_free(key_new_blob); + pk = add_onion_helper_keyarg("NEW:BEST", 1, &key_new_alg, &key_new_blob, + &err_msg); + tt_assert(pk); + tt_assert(!key_new_alg); + tt_assert(!key_new_blob); + tt_assert(!err_msg); + + /* Test generating a invalid key type. */ + crypto_pk_free(pk); + pk = add_onion_helper_keyarg("NEW:RSA512", 0, &key_new_alg, &key_new_blob, + &err_msg); + tt_assert(!pk); + tt_assert(!key_new_alg); + tt_assert(!key_new_blob); + tt_assert(err_msg); + + /* Test loading a RSA1024 key. */ + tor_free(err_msg); + pk = pk_generate(0); + tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk, &encoded)); + tor_asprintf(&arg_str, "RSA1024:%s", encoded); + pk2 = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, + &err_msg); + tt_assert(pk2); + tt_assert(!key_new_alg); + tt_assert(!key_new_blob); + tt_assert(!err_msg); + tt_assert(crypto_pk_cmp_keys(pk, pk2) == 0); + + /* Test loading a invalid key type. */ + tor_free(arg_str); + crypto_pk_free(pk); pk = NULL; + tor_asprintf(&arg_str, "RSA512:%s", encoded); + pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, + &err_msg); + tt_assert(!pk); + tt_assert(!key_new_alg); + tt_assert(!key_new_blob); + tt_assert(err_msg); + + /* Test loading a invalid key. */ + tor_free(arg_str); + crypto_pk_free(pk); pk = NULL; + tor_free(err_msg); + encoded[strlen(encoded)/2] = '\0'; + tor_asprintf(&arg_str, "RSA1024:%s", encoded); + pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, + &err_msg); + tt_assert(!pk); + tt_assert(!key_new_alg); + tt_assert(!key_new_blob); + tt_assert(err_msg); + + done: + crypto_pk_free(pk); + crypto_pk_free(pk2); + tor_free(key_new_blob); + tor_free(err_msg); + tor_free(encoded); + tor_free(arg_str); +} + +static void +test_rend_service_parse_port_config(void *arg) +{ + const char *sep = ","; + rend_service_port_config_t *cfg = NULL; + char *err_msg = NULL; + + (void)arg; + + /* Test "VIRTPORT" only. */ + cfg = rend_service_parse_port_config("80", sep, &err_msg); + tt_assert(cfg); + tt_assert(!err_msg); + + /* Test "VIRTPORT,TARGET" (Target is port). */ + rend_service_port_config_free(cfg); + cfg = rend_service_parse_port_config("80,8080", sep, &err_msg); + tt_assert(cfg); + tt_assert(!err_msg); + + /* Test "VIRTPORT,TARGET" (Target is IPv4:port). */ + rend_service_port_config_free(cfg); + cfg = rend_service_parse_port_config("80,192.0.2.1:8080", sep, &err_msg); + tt_assert(cfg); + tt_assert(!err_msg); + + /* Test "VIRTPORT,TARGET" (Target is IPv6:port). */ + rend_service_port_config_free(cfg); + cfg = rend_service_parse_port_config("80,[2001:db8::1]:8080", sep, &err_msg); + tt_assert(cfg); + tt_assert(!err_msg); + + /* XXX: Someone should add tests for AF_UNIX targets if supported. */ + + /* Test empty config. */ + rend_service_port_config_free(cfg); + cfg = rend_service_parse_port_config("", sep, &err_msg); + tt_assert(!cfg); + tt_assert(err_msg); + + /* Test invalid port. */ + tor_free(err_msg); + cfg = rend_service_parse_port_config("90001", sep, &err_msg); + tt_assert(!cfg); + tt_assert(err_msg); + + done: + rend_service_port_config_free(cfg); + tor_free(err_msg); +} + +struct testcase_t controller_tests[] = { + { "add_onion_helper_keyarg", test_add_onion_helper_keyarg, 0, NULL, NULL }, + { "rend_service_parse_port_config", test_rend_service_parse_port_config, 0, + NULL, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c index e36314da45..bd91aecd94 100644 --- a/src/test/test_controller_events.c +++ b/src/test/test_controller_events.c @@ -293,6 +293,104 @@ test_cntev_format_cell_stats(void *arg) tor_free(n_chan); } +static void +test_cntev_event_mask(void *arg) +{ + unsigned int test_event, selected_event; + (void)arg; + + /* Check that nothing is interesting when no events are set */ + control_testing_set_global_event_mask(EVENT_MASK_NONE_); + + /* Check that nothing is interesting between EVENT_MIN_ and EVENT_MAX_ */ + for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++) + tt_assert(!control_event_is_interesting(test_event)); + + /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_ + * This will break if control_event_is_interesting() checks its arguments */ + for (test_event = 0; test_event < EVENT_MIN_; test_event++) + tt_assert(!control_event_is_interesting(test_event)); + for (test_event = EVENT_MAX_ + 1; + test_event < EVENT_CAPACITY_; + test_event++) + tt_assert(!control_event_is_interesting(test_event)); + + /* Check that all valid events are interesting when all events are set */ + control_testing_set_global_event_mask(EVENT_MASK_ALL_); + + /* Check that everything is interesting between EVENT_MIN_ and EVENT_MAX_ */ + for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++) + tt_assert(control_event_is_interesting(test_event)); + + /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_ + * This will break if control_event_is_interesting() checks its arguments */ + for (test_event = 0; test_event < EVENT_MIN_; test_event++) + tt_assert(!control_event_is_interesting(test_event)); + for (test_event = EVENT_MAX_ + 1; + test_event < EVENT_CAPACITY_; + test_event++) + tt_assert(!control_event_is_interesting(test_event)); + + /* Check that only that event is interesting when a single event is set */ + for (selected_event = EVENT_MIN_; + selected_event <= EVENT_MAX_; + selected_event++) { + control_testing_set_global_event_mask(EVENT_MASK_(selected_event)); + + /* Check that only this event is interesting + * between EVENT_MIN_ and EVENT_MAX_ */ + for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++) { + if (test_event == selected_event) { + tt_assert(control_event_is_interesting(test_event)); + } else { + tt_assert(!control_event_is_interesting(test_event)); + } + } + + /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_ + * This will break if control_event_is_interesting checks its arguments */ + for (test_event = 0; test_event < EVENT_MIN_; test_event++) + tt_assert(!control_event_is_interesting(test_event)); + for (test_event = EVENT_MAX_ + 1; + test_event < EVENT_CAPACITY_; + test_event++) + tt_assert(!control_event_is_interesting(test_event)); + } + + /* Check that only that event is not-interesting + * when a single event is un-set */ + for (selected_event = EVENT_MIN_; + selected_event <= EVENT_MAX_; + selected_event++) { + control_testing_set_global_event_mask( + EVENT_MASK_ALL_ + & ~(EVENT_MASK_(selected_event)) + ); + + /* Check that only this event is not-interesting + * between EVENT_MIN_ and EVENT_MAX_ */ + for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++) { + if (test_event == selected_event) { + tt_assert(!control_event_is_interesting(test_event)); + } else { + tt_assert(control_event_is_interesting(test_event)); + } + } + + /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_ + * This will break if control_event_is_interesting checks its arguments */ + for (test_event = 0; test_event < EVENT_MIN_; test_event++) + tt_assert(!control_event_is_interesting(test_event)); + for (test_event = EVENT_MAX_ + 1; + test_event < EVENT_CAPACITY_; + test_event++) + tt_assert(!control_event_is_interesting(test_event)); + } + + done: + ; +} + #define TEST(name, flags) \ { #name, test_cntev_ ## name, flags, 0, NULL } @@ -302,6 +400,7 @@ struct testcase_t controller_event_tests[] = { TEST(sum_up_cell_stats, 0), TEST(append_cell_stats, 0), TEST(format_cell_stats, 0), + TEST(event_mask, 0), END_OF_TESTCASES }; diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 15ba14b3bf..6cba850f30 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -14,6 +14,8 @@ #include "crypto_ed25519.h" #include "ed25519_vectors.inc" +#include <openssl/evp.h> + extern const char AUTHORITY_SIGNKEY_3[]; extern const char AUTHORITY_SIGNKEY_A_DIGEST[]; extern const char AUTHORITY_SIGNKEY_A_DIGEST256[]; @@ -72,7 +74,7 @@ test_crypto_rng(void *arg) /* Try out RNG. */ (void)arg; - tt_assert(! crypto_seed_rng(0)); + tt_assert(! crypto_seed_rng()); crypto_rand(data1, 100); crypto_rand(data2, 100); tt_mem_op(data1,OP_NE, data2,100); @@ -105,6 +107,30 @@ test_crypto_rng(void *arg) ; } +static void +test_crypto_rng_range(void *arg) +{ + int got_smallest = 0, got_largest = 0; + int i; + + (void)arg; + for (i = 0; i < 1000; ++i) { + int x = crypto_rand_int_range(5,9); + tt_int_op(x, OP_GE, 5); + tt_int_op(x, OP_LT, 9); + if (x == 5) + got_smallest = 1; + if (x == 8) + got_largest = 1; + } + + /* These fail with probability 1/10^603. */ + tt_assert(got_smallest); + tt_assert(got_largest); + done: + ; +} + /** Run unit tests for our AES functionality */ static void test_crypto_aes(void *arg) @@ -571,6 +597,42 @@ test_crypto_pk_fingerprints(void *arg) tor_free(mem_op_hex_tmp); } +static void +test_crypto_pk_base64(void *arg) +{ + crypto_pk_t *pk1 = NULL; + crypto_pk_t *pk2 = NULL; + char *encoded = NULL; + + (void)arg; + + /* Test Base64 encoding a key. */ + pk1 = pk_generate(0); + tt_assert(pk1); + tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk1, &encoded)); + tt_assert(encoded); + + /* Test decoding a valid key. */ + pk2 = crypto_pk_base64_decode(encoded, strlen(encoded)); + tt_assert(pk2); + tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + crypto_pk_free(pk2); + + /* Test decoding a invalid key (not Base64). */ + static const char *invalid_b64 = "The key is in another castle!"; + pk2 = crypto_pk_base64_decode(invalid_b64, strlen(invalid_b64)); + tt_assert(!pk2); + + /* Test decoding a truncated Base64 blob. */ + pk2 = crypto_pk_base64_decode(encoded, strlen(encoded)/2); + tt_assert(!pk2); + + done: + crypto_pk_free(pk1); + crypto_pk_free(pk2); + tor_free(encoded); +} + /** Sanity check for crypto pk digests */ static void test_crypto_digests(void *arg) @@ -601,6 +663,22 @@ test_crypto_digests(void *arg) crypto_pk_free(k); } +/** Encode src into dest with OpenSSL's EVP Encode interface, returning the + * length of the encoded data in bytes. + */ +static int +base64_encode_evp(char *dest, char *src, size_t srclen) +{ + const unsigned char *s = (unsigned char*)src; + EVP_ENCODE_CTX ctx; + int len, ret; + + EVP_EncodeInit(&ctx); + EVP_EncodeUpdate(&ctx, (unsigned char *)dest, &len, s, (int)srclen); + EVP_EncodeFinal(&ctx, (unsigned char *)(dest + len), &ret); + return ret+ len; +} + /** Run unit tests for misc crypto formatting functionality (base64, base32, * fingerprints, etc) */ static void @@ -618,7 +696,7 @@ test_crypto_formats(void *arg) /* Base64 tests */ memset(data1, 6, 1024); for (idx = 0; idx < 10; ++idx) { - i = base64_encode(data2, 1024, data1, idx); + i = base64_encode(data2, 1024, data1, idx, 0); tt_int_op(i, OP_GE, 0); tt_int_op(i, OP_EQ, strlen(data2)); j = base64_decode(data3, 1024, data2, i); @@ -637,7 +715,7 @@ test_crypto_formats(void *arg) strlcpy(data1, "Test string that contains 35 chars.", 1024); strlcat(data1, " 2nd string that contains 35 chars.", 1024); - i = base64_encode(data2, 1024, data1, 71); + i = base64_encode(data2, 1024, data1, 71, 0); tt_int_op(i, OP_GE, 0); j = base64_decode(data3, 1024, data2, i); tt_int_op(j,OP_EQ, 71); @@ -656,6 +734,20 @@ test_crypto_formats(void *arg) tt_assert(digest_from_base64(data3, "###") < 0); + for (i = 0; i < 256; i++) { + /* Test the multiline format Base64 encoder with 0 .. 256 bytes of + * output against OpenSSL. + */ + const size_t enclen = base64_encode_size(i, BASE64_ENCODE_MULTILINE); + data1[i] = i; + j = base64_encode(data2, 1024, data1, i, BASE64_ENCODE_MULTILINE); + tt_int_op(j, OP_EQ, enclen); + j = base64_encode_evp(data3, data1, i); + tt_int_op(j, OP_EQ, enclen); + tt_mem_op(data2, OP_EQ, data3, enclen); + tt_int_op(j, OP_EQ, strlen(data2)); + } + /* Encoding SHA256 */ crypto_rand(data2, DIGEST256_LEN); memset(data2, 100, 1024); @@ -1623,11 +1715,13 @@ test_crypto_siphash(void *arg) struct testcase_t crypto_tests[] = { CRYPTO_LEGACY(formats), CRYPTO_LEGACY(rng), + { "rng_range", test_crypto_rng_range, 0, NULL, NULL }, { "aes_AES", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"aes" }, { "aes_EVP", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"evp" }, CRYPTO_LEGACY(sha), CRYPTO_LEGACY(pk), { "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL }, + { "pk_base64", test_crypto_pk_base64, TT_FORK, NULL, NULL }, CRYPTO_LEGACY(digests), CRYPTO_LEGACY(dh), { "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &passthrough_setup, diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 5f68c34b39..3e9e955b2b 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -148,7 +148,8 @@ test_dir_formats(void *arg) char cert_buf[256]; base64_encode(cert_buf, sizeof(cert_buf), (const char*)r2->signing_key_cert->encoded, - r2->signing_key_cert->encoded_len); + r2->signing_key_cert->encoded_len, + BASE64_ENCODE_MULTILINE); r2->platform = tor_strdup(platform); r2->cache_info.published_on = 5; r2->or_port = 9005; @@ -249,7 +250,8 @@ test_dir_formats(void *arg) pk1, &rsa_cc_len); tt_assert(rsa_cc); - base64_encode(cert_buf, sizeof(cert_buf), (char*)rsa_cc, rsa_cc_len); + base64_encode(cert_buf, sizeof(cert_buf), (char*)rsa_cc, rsa_cc_len, + BASE64_ENCODE_MULTILINE); strlcat(buf2, "onion-key-crosscert\n" "-----BEGIN CROSSCERT-----\n", sizeof(buf2)); strlcat(buf2, cert_buf, sizeof(buf2)); @@ -262,7 +264,8 @@ test_dir_formats(void *arg) &ntor_cc_sign); tt_assert(ntor_cc); base64_encode(cert_buf, sizeof(cert_buf), - (char*)ntor_cc->encoded, ntor_cc->encoded_len); + (char*)ntor_cc->encoded, ntor_cc->encoded_len, + BASE64_ENCODE_MULTILINE); tor_snprintf(buf2+strlen(buf2), sizeof(buf2)-strlen(buf2), "ntor-onion-key-crosscert %d\n" "-----BEGIN ED25519 CERT-----\n" @@ -272,7 +275,8 @@ test_dir_formats(void *arg) strlcat(buf2, "hidden-service-dir\n", sizeof(buf2)); strlcat(buf2, "ntor-onion-key ", sizeof(buf2)); base64_encode(cert_buf, sizeof(cert_buf), - (const char*)r2_onion_keypair.pubkey.public_key, 32); + (const char*)r2_onion_keypair.pubkey.public_key, 32, + BASE64_ENCODE_MULTILINE); strlcat(buf2, cert_buf, sizeof(buf2)); strlcat(buf2, "accept *:80\nreject 18.0.0.0/8:24\n", sizeof(buf2)); strlcat(buf2, "router-sig-ed25519 ", sizeof(buf2)); diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index 17cb9d9329..0011d3698a 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -162,9 +162,6 @@ populate_live_entry_guards_test_helper(int num_needed) False, all guards should have made_contact enabled. */ tt_int_op(entry->made_contact, OP_EQ, 1); - /* Since we don't have a routerstatus, all of the entry guards are - not directory servers. */ - tt_int_op(entry->is_dir_cache, OP_EQ, 0); } SMARTLIST_FOREACH_END(entry); /* First, try to get some fast guards. This should fail. */ diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 67ef646aab..dd49cd3e35 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -13,6 +13,7 @@ #include "test.h" #include "control.h" #include "config.h" +#include "rendcommon.h" #include "routerset.h" #include "circuitbuild.h" #include "test_helpers.h" @@ -28,6 +29,68 @@ #define STR_HSDIR_NONE_EXIST_LONGNAME \ "$BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +/* DuckDuckGo descriptor as an example. */ +static const char *hs_desc_content = "\ +rendezvous-service-descriptor g5ojobzupf275beh5ra72uyhb3dkpxwg\r\n\ +version 2\r\n\ +permanent-key\r\n\ +-----BEGIN RSA PUBLIC KEY-----\r\n\ +MIGJAoGBAJ/SzzgrXPxTlFrKVhXh3buCWv2QfcNgncUpDpKouLn3AtPH5Ocys0jE\r\n\ +aZSKdvaiQ62md2gOwj4x61cFNdi05tdQjS+2thHKEm/KsB9BGLSLBNJYY356bupg\r\n\ +I5gQozM65ENelfxYlysBjJ52xSDBd8C4f/p9umdzaaaCmzXG/nhzAgMBAAE=\r\n\ +-----END RSA PUBLIC KEY-----\r\n\ +secret-id-part anmjoxxwiupreyajjt5yasimfmwcnxlf\r\n\ +publication-time 2015-03-11 19:00:00\r\n\ +protocol-versions 2,3\r\n\ +introduction-points\r\n\ +-----BEGIN MESSAGE-----\r\n\ +aW50cm9kdWN0aW9uLXBvaW50IDd1bnd4cmg2dG5kNGh6eWt1Z3EzaGZzdHduc2ll\r\n\ +cmhyCmlwLWFkZHJlc3MgMTg4LjEzOC4xMjEuMTE4Cm9uaW9uLXBvcnQgOTAwMQpv\r\n\ +bmlvbi1rZXkKLS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JR0pBb0dC\r\n\ +QUxGRVVyeVpDbk9ROEhURmV5cDVjMTRObWVqL1BhekFLTTBxRENTNElKUWh0Y3g1\r\n\ +NXpRSFdOVWIKQ2hHZ0JqR1RjV3ZGRnA0N3FkdGF6WUZhVXE2c0lQKzVqeWZ5b0Q4\r\n\ +UmJ1bzBwQmFWclJjMmNhYUptWWM0RDh6Vgpuby9sZnhzOVVaQnZ1cWY4eHIrMDB2\r\n\ +S0JJNmFSMlA2OE1WeDhrMExqcUpUU2RKOE9idm9yQWdNQkFBRT0KLS0tLS1FTkQg\r\n\ +UlNBIFBVQkxJQyBLRVktLS0tLQpzZXJ2aWNlLWtleQotLS0tLUJFR0lOIFJTQSBQ\r\n\ +VUJMSUMgS0VZLS0tLS0KTUlHSkFvR0JBTnJHb0ozeTlHNXQzN2F2ekI1cTlwN1hG\r\n\ +VUplRUVYMUNOaExnWmJXWGJhVk5OcXpoZFhyL0xTUQppM1Z6dW5OaUs3cndUVnE2\r\n\ +K2QyZ1lRckhMMmIvMXBBY3ZKWjJiNSs0bTRRc0NibFpjRENXTktRbHJnRWN5WXRJ\r\n\ +CkdscXJTbFFEaXA0ZnNrUFMvNDVkWTI0QmJsQ3NGU1k3RzVLVkxJck4zZFpGbmJr\r\n\ +NEZIS1hBZ01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCmludHJv\r\n\ +ZHVjdGlvbi1wb2ludCBiNGM3enlxNXNheGZzN2prNXFibG1wN3I1b3pwdHRvagpp\r\n\ +cC1hZGRyZXNzIDEwOS4xNjkuNDUuMjI2Cm9uaW9uLXBvcnQgOTAwMQpvbmlvbi1r\r\n\ +ZXkKLS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JR0pBb0dCQU8xSXpw\r\n\ +WFFUTUY3RXZUb1NEUXpzVnZiRVFRQUQrcGZ6NzczMVRXZzVaUEJZY1EyUkRaeVp4\r\n\ +OEQKNUVQSU1FeUE1RE83cGd0ak5LaXJvYXJGMC8yempjMkRXTUlSaXZyU29YUWVZ\r\n\ +ZXlMM1pzKzFIajJhMDlCdkYxZAp6MEswblRFdVhoNVR5V3lyMHdsbGI1SFBnTlI0\r\n\ +MS9oYkprZzkwZitPVCtIeGhKL1duUml2QWdNQkFBRT0KLS0tLS1FTkQgUlNBIFBV\r\n\ +QkxJQyBLRVktLS0tLQpzZXJ2aWNlLWtleQotLS0tLUJFR0lOIFJTQSBQVUJMSUMg\r\n\ +S0VZLS0tLS0KTUlHSkFvR0JBSzNWZEJ2ajFtQllLL3JrcHNwcm9Ub0llNUtHVmth\r\n\ +QkxvMW1tK1I2YUVJek1VZFE1SjkwNGtyRwpCd3k5NC8rV0lGNFpGYXh5Z2phejl1\r\n\ +N2pKY1k3ZGJhd1pFeG1hYXFCRlRwL2h2ZG9rcHQ4a1ByRVk4OTJPRHJ1CmJORUox\r\n\ +N1FPSmVMTVZZZk5Kcjl4TWZCQ3JQai8zOGh2RUdrbWVRNmRVWElvbVFNaUJGOVRB\r\n\ +Z01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCmludHJvZHVjdGlv\r\n\ +bi1wb2ludCBhdjVtcWl0Y2Q3cjJkandsYmN0c2Jlc2R3eGt0ZWtvegppcC1hZGRy\r\n\ +ZXNzIDE0NC43Ni44LjczCm9uaW9uLXBvcnQgNDQzCm9uaW9uLWtleQotLS0tLUJF\r\n\ +R0lOIFJTQSBQVUJMSUMgS0VZLS0tLS0KTUlHSkFvR0JBTzVweVZzQmpZQmNmMXBE\r\n\ +dklHUlpmWXUzQ05nNldka0ZLMGlvdTBXTGZtejZRVDN0NWhzd3cyVwpjejlHMXhx\r\n\ +MmN0Nkd6VWkrNnVkTDlITTRVOUdHTi9BbW8wRG9GV1hKWHpBQkFXd2YyMVdsd1lW\r\n\ +eFJQMHRydi9WCkN6UDkzcHc5OG5vSmdGUGRUZ05iMjdKYmVUZENLVFBrTEtscXFt\r\n\ +b3NveUN2RitRa25vUS9BZ01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0t\r\n\ +LS0tCnNlcnZpY2Uta2V5Ci0tLS0tQkVHSU4gUlNBIFBVQkxJQyBLRVktLS0tLQpN\r\n\ +SUdKQW9HQkFMVjNKSmtWN3lTNU9jc1lHMHNFYzFQOTVRclFRR3ZzbGJ6Wi9zRGxl\r\n\ +RlpKYXFSOUYvYjRUVERNClNGcFMxcU1GbldkZDgxVmRGMEdYRmN2WVpLamRJdHU2\r\n\ +SndBaTRJeEhxeXZtdTRKdUxrcXNaTEFLaXRLVkx4eGsKeERlMjlDNzRWMmJrOTRJ\r\n\ +MEgybTNKS2tzTHVwc3VxWWRVUmhOVXN0SElKZmgyZmNIalF0bEFnTUJBQUU9Ci0t\r\n\ +LS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0KCg==\r\n\ +-----END MESSAGE-----\r\n\ +signature\r\n\ +-----BEGIN SIGNATURE-----\r\n\ +d4OuCE5OLAOnRB6cQN6WyMEmg/BHem144Vec+eYgeWoKwx3MxXFplUjFxgnMlmwN\r\n\ +PcftsZf2ztN0sbNCtPgDL3d0PqvxY3iHTQAI8EbaGq/IAJUZ8U4y963dD5+Bn6JQ\r\n\ +myE3ctmh0vy5+QxSiRjmQBkuEpCyks7LvWvHYrhnmcg=\r\n\ +-----END SIGNATURE-----"; + /* Helper global variable for hidden service descriptor event test. * It's used as a pointer to dynamically created message buffer in * send_control_event_string_replacement function, which mocks @@ -69,10 +132,13 @@ static void test_hs_desc_event(void *arg) { #define STR_HS_ADDR "ajhb7kljbiru65qo" - #define STR_HS_ID "b3oeducbhjmbqmgw2i3jtz4fekkrinwj" + #define STR_HS_CONTENT_DESC_ID "g5ojobzupf275beh5ra72uyhb3dkpxwg" + #define STR_DESC_ID_BASE32 "hba3gmcgpfivzfhx5rtfqkfdhv65yrj3" + int ret; rend_data_t rend_query; const char *expected_msg; + char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; (void) arg; MOCK(send_control_event_string, @@ -81,31 +147,48 @@ test_hs_desc_event(void *arg) node_describe_longname_by_id_replacement); /* setup rend_query struct */ + memset(&rend_query, 0, sizeof(rend_query)); strncpy(rend_query.onion_address, STR_HS_ADDR, REND_SERVICE_ID_LEN_BASE32+1); - rend_query.auth_type = 0; + rend_query.auth_type = REND_NO_AUTH; + rend_query.hsdirs_fp = smartlist_new(); + smartlist_add(rend_query.hsdirs_fp, tor_memdup(HSDIR_EXIST_ID, + DIGEST_LEN)); + + /* Compute descriptor ID for replica 0, should be STR_DESC_ID_BASE32. */ + ret = rend_compute_v2_desc_id(rend_query.descriptor_id[0], + rend_query.onion_address, + NULL, 0, 0); + tt_int_op(ret, ==, 0); + base32_encode(desc_id_base32, sizeof(desc_id_base32), + rend_query.descriptor_id[0], DIGEST_LEN); + /* Make sure rend_compute_v2_desc_id works properly. */ + tt_mem_op(desc_id_base32, OP_EQ, STR_DESC_ID_BASE32, + sizeof(desc_id_base32)); /* test request event */ control_event_hs_descriptor_requested(&rend_query, HSDIR_EXIST_ID, - STR_HS_ID); + STR_DESC_ID_BASE32); expected_msg = "650 HS_DESC REQUESTED "STR_HS_ADDR" NO_AUTH "\ - STR_HSDIR_EXIST_LONGNAME" "STR_HS_ID"\r\n"; + STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32 "\r\n"; tt_assert(received_msg); tt_str_op(received_msg,OP_EQ, expected_msg); tor_free(received_msg); /* test received event */ - rend_query.auth_type = 1; - control_event_hs_descriptor_received(&rend_query, HSDIR_EXIST_ID); + rend_query.auth_type = REND_BASIC_AUTH; + control_event_hs_descriptor_received(rend_query.onion_address, + &rend_query, HSDIR_EXIST_ID); expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\ - STR_HSDIR_EXIST_LONGNAME"\r\n"; + STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32"\r\n"; tt_assert(received_msg); tt_str_op(received_msg,OP_EQ, expected_msg); tor_free(received_msg); /* test failed event */ - rend_query.auth_type = 2; - control_event_hs_descriptor_failed(&rend_query, HSDIR_NONE_EXIST_ID, + rend_query.auth_type = REND_STEALTH_AUTH; + control_event_hs_descriptor_failed(&rend_query, + HSDIR_NONE_EXIST_ID, "QUERY_REJECTED"); expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "\ STR_HSDIR_NONE_EXIST_LONGNAME" REASON=QUERY_REJECTED\r\n"; @@ -115,14 +198,31 @@ test_hs_desc_event(void *arg) /* test invalid auth type */ rend_query.auth_type = 999; - control_event_hs_descriptor_failed(&rend_query, HSDIR_EXIST_ID, + control_event_hs_descriptor_failed(&rend_query, + HSDIR_EXIST_ID, "QUERY_REJECTED"); expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\ - STR_HSDIR_EXIST_LONGNAME" REASON=QUERY_REJECTED\r\n"; + STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32\ + " REASON=QUERY_REJECTED\r\n"; tt_assert(received_msg); tt_str_op(received_msg,OP_EQ, expected_msg); tor_free(received_msg); + /* test valid content. */ + char *exp_msg; + control_event_hs_descriptor_content(rend_query.onion_address, STR_HS_CONTENT_DESC_ID, + HSDIR_EXIST_ID, hs_desc_content); + tor_asprintf(&exp_msg, "650+HS_DESC_CONTENT " STR_HS_ADDR " "\ + STR_HS_CONTENT_DESC_ID " " STR_HSDIR_EXIST_LONGNAME\ + "\r\n%s\r\n.\r\n650 OK\r\n", hs_desc_content); + + tt_assert(received_msg); + tt_str_op(received_msg, OP_EQ, exp_msg); + tor_free(received_msg); + tor_free(exp_msg); + SMARTLIST_FOREACH(rend_query.hsdirs_fp, char *, d, tor_free(d)); + smartlist_free(rend_query.hsdirs_fp); + done: UNMOCK(send_control_event_string); UNMOCK(node_describe_longname_by_id); @@ -198,7 +298,142 @@ test_pick_bad_tor2web_rendezvous_node(void *arg) routerset_free(options->Tor2webRendezvousPoints); } +/* Make sure rend_data_t is valid at creation, destruction and when + * duplicated. */ +static void +test_hs_rend_data(void *arg) +{ + int rep; + rend_data_t *client; + /* Binary format of a descriptor ID. */ + char desc_id[DIGEST_LEN]; + char client_cookie[REND_DESC_COOKIE_LEN]; + time_t now = time(NULL); + + (void)arg; + + base32_decode(desc_id, sizeof(desc_id), STR_DESC_ID_BASE32, + REND_DESC_ID_V2_LEN_BASE32); + memset(client_cookie, 'e', sizeof(client_cookie)); + + client = rend_data_client_create(STR_HS_ADDR, desc_id, client_cookie, + REND_NO_AUTH); + tt_assert(client); + tt_int_op(client->auth_type, ==, REND_NO_AUTH); + tt_str_op(client->onion_address, OP_EQ, STR_HS_ADDR); + tt_mem_op(client->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id)); + tt_mem_op(client->descriptor_cookie, OP_EQ, client_cookie, + sizeof(client_cookie)); + tt_assert(client->hsdirs_fp); + tt_int_op(smartlist_len(client->hsdirs_fp), ==, 0); + for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { + int ret = rend_compute_v2_desc_id(desc_id, client->onion_address, + client->descriptor_cookie, now, rep); + /* That shouldn't never fail. */ + tt_int_op(ret, ==, 0); + tt_mem_op(client->descriptor_id[rep], OP_EQ, desc_id, sizeof(desc_id)); + } + /* The rest should be zeroed because this is a client request. */ + tt_int_op(tor_digest_is_zero(client->rend_pk_digest), ==, 1); + tt_int_op(tor_digest_is_zero(client->rend_cookie), ==, 1); + + /* Test dup(). */ + rend_data_t *client_dup = rend_data_dup(client); + tt_assert(client_dup); + tt_int_op(client_dup->auth_type, ==, client->auth_type); + tt_str_op(client_dup->onion_address, OP_EQ, client->onion_address); + tt_mem_op(client_dup->desc_id_fetch, OP_EQ, client->desc_id_fetch, + sizeof(client_dup->desc_id_fetch)); + tt_mem_op(client_dup->descriptor_cookie, OP_EQ, client->descriptor_cookie, + sizeof(client_dup->descriptor_cookie)); + + tt_assert(client_dup->hsdirs_fp); + tt_int_op(smartlist_len(client_dup->hsdirs_fp), ==, 0); + for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { + tt_mem_op(client_dup->descriptor_id[rep], OP_EQ, + client->descriptor_id[rep], DIGEST_LEN); + } + /* The rest should be zeroed because this is a client request. */ + tt_int_op(tor_digest_is_zero(client_dup->rend_pk_digest), ==, 1); + tt_int_op(tor_digest_is_zero(client_dup->rend_cookie), ==, 1); + rend_data_free(client); + rend_data_free(client_dup); + + /* Reset state. */ + base32_decode(desc_id, sizeof(desc_id), STR_DESC_ID_BASE32, + REND_DESC_ID_V2_LEN_BASE32); + memset(client_cookie, 'e', sizeof(client_cookie)); + + /* Try with different parameters here for which some content should be + * zeroed out. */ + client = rend_data_client_create(NULL, desc_id, NULL, REND_BASIC_AUTH); + tt_assert(client); + tt_int_op(client->auth_type, ==, REND_BASIC_AUTH); + tt_int_op(strlen(client->onion_address), ==, 0); + tt_mem_op(client->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id)); + tt_int_op(tor_mem_is_zero(client->descriptor_cookie, + sizeof(client->descriptor_cookie)), ==, 1); + tt_assert(client->hsdirs_fp); + tt_int_op(smartlist_len(client->hsdirs_fp), ==, 0); + for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { + tt_int_op(tor_digest_is_zero(client->descriptor_id[rep]), ==, 1); + } + /* The rest should be zeroed because this is a client request. */ + tt_int_op(tor_digest_is_zero(client->rend_pk_digest), ==, 1); + tt_int_op(tor_digest_is_zero(client->rend_cookie), ==, 1); + rend_data_free(client); + + /* Let's test the service object now. */ + rend_data_t *service; + char rend_pk_digest[DIGEST_LEN]; + uint8_t rend_cookie[DIGEST_LEN]; + memset(rend_pk_digest, 'f', sizeof(rend_pk_digest)); + memset(rend_cookie, 'g', sizeof(rend_cookie)); + + service = rend_data_service_create(STR_HS_ADDR, rend_pk_digest, + rend_cookie, REND_NO_AUTH); + tt_assert(service); + tt_int_op(service->auth_type, ==, REND_NO_AUTH); + tt_str_op(service->onion_address, OP_EQ, STR_HS_ADDR); + tt_mem_op(service->rend_pk_digest, OP_EQ, rend_pk_digest, + sizeof(rend_pk_digest)); + tt_mem_op(service->rend_cookie, OP_EQ, rend_cookie, sizeof(rend_cookie)); + tt_assert(service->hsdirs_fp); + tt_int_op(smartlist_len(service->hsdirs_fp), ==, 0); + for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { + tt_int_op(tor_digest_is_zero(service->descriptor_id[rep]), ==, 1); + } + /* The rest should be zeroed because this is a service request. */ + tt_int_op(tor_digest_is_zero(service->descriptor_cookie), ==, 1); + tt_int_op(tor_digest_is_zero(service->desc_id_fetch), ==, 1); + + /* Test dup(). */ + rend_data_t *service_dup = rend_data_dup(service); + tt_assert(service_dup); + tt_int_op(service_dup->auth_type, ==, service->auth_type); + tt_str_op(service_dup->onion_address, OP_EQ, service->onion_address); + tt_mem_op(service_dup->rend_pk_digest, OP_EQ, service->rend_pk_digest, + sizeof(service_dup->rend_pk_digest)); + tt_mem_op(service_dup->rend_cookie, OP_EQ, service->rend_cookie, + sizeof(service_dup->rend_cookie)); + tt_assert(service_dup->hsdirs_fp); + tt_int_op(smartlist_len(service_dup->hsdirs_fp), ==, 0); + for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { + tt_int_op(tor_digest_is_zero(service_dup->descriptor_id[rep]), ==, 1); + } + /* The rest should be zeroed because this is a service request. */ + tt_int_op(tor_digest_is_zero(service_dup->descriptor_cookie), ==, 1); + tt_int_op(tor_digest_is_zero(service_dup->desc_id_fetch), ==, 1); + rend_data_free(service); + rend_data_free(service_dup); + + done: + return; +} + struct testcase_t hs_tests[] = { + { "hs_rend_data", test_hs_rend_data, TT_FORK, + NULL, NULL }, { "hs_desc_event", test_hs_desc_event, TT_FORK, NULL, NULL }, { "pick_tor2web_rendezvous_node", test_pick_tor2web_rendezvous_node, TT_FORK, diff --git a/src/test/test_ntor.sh.in b/src/test/test_ntor.sh.in new file mode 100644 index 0000000000..be35384ddf --- /dev/null +++ b/src/test/test_ntor.sh.in @@ -0,0 +1,9 @@ +#!@SHELL@ +# Validate Tor's ntor implementation. + +exitcode=0 + +@PYTHON@ @abs_top_srcdir@/src/test/ntor_ref.py test-tor || exitcode=1 +@PYTHON@ @abs_top_srcdir@/src/test/ntor_ref.py self-test || exitcode=1 + +exit ${exitcode} diff --git a/src/test/test_status.c b/src/test/test_status.c index 0aa82ca087..cbc8af188c 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -337,7 +337,7 @@ NS(test_main)(void *arg) actual = log_heartbeat(0); tt_int_op(actual, OP_EQ, expected); - tt_int_op(CALLED(logv), OP_EQ, 4); + tt_int_op(CALLED(logv), OP_EQ, 5); done: NS_UNMOCK(tls_get_write_overhead_ratio); @@ -430,6 +430,12 @@ NS(logv)(int severity, log_domain_mask_t domain, tt_int_op(va_arg(ap, int), OP_EQ, 1); /* handshakes assigned (NTOR) */ tt_int_op(va_arg(ap, int), OP_EQ, 1); /* handshakes requested (NTOR) */ break; + case 4: + tt_int_op(severity, OP_EQ, LOG_NOTICE); + tt_int_op(domain, OP_EQ, LD_HEARTBEAT); + tt_ptr_op(strstr(funcname, "rep_hist_log_link_protocol_counts"), + OP_NE, NULL); + break; default: tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args break; @@ -878,7 +884,8 @@ NS(logv)(int severity, log_domain_mask_t domain, const char *funcname, tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL); tt_ptr_op(suffix, OP_EQ, NULL); tt_str_op(format, OP_EQ, - "Average packaged cell fullness: %2.3f%%. TLS write overhead: %.f%%"); + "Average packaged cell fullness: %2.3f%%. " + "TLS write overhead: %.f%%"); tt_double_op(fabs(va_arg(ap, double) - 50.0), <=, DBL_EPSILON); tt_double_op(fabs(va_arg(ap, double) - 0.0), <=, DBL_EPSILON); break; @@ -1026,7 +1033,8 @@ NS(logv)(int severity, log_domain_mask_t domain, tt_ptr_op(strstr(funcname, "log_heartbeat"), OP_NE, NULL); tt_ptr_op(suffix, OP_EQ, NULL); tt_str_op(format, OP_EQ, - "Average packaged cell fullness: %2.3f%%. TLS write overhead: %.f%%"); + "Average packaged cell fullness: %2.3f%%. " + "TLS write overhead: %.f%%"); tt_int_op(fabs(va_arg(ap, double) - 100.0) <= DBL_EPSILON, OP_EQ, 1); tt_double_op(fabs(va_arg(ap, double) - 100.0), <=, DBL_EPSILON); break; diff --git a/src/test/test_util.c b/src/test/test_util.c index 51e9e761ab..30dc59844a 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -4111,26 +4111,6 @@ test_util_laplace(void *arg) ; } -static void -test_util_strclear(void *arg) -{ - static const char *vals[] = { "", "a", "abcdef", "abcdefgh", NULL }; - int i; - char *v = NULL; - (void)arg; - - for (i = 0; vals[i]; ++i) { - size_t n; - v = tor_strdup(vals[i]); - n = strlen(v); - tor_strclear(v); - tt_assert(tor_mem_is_zero(v, n+1)); - tor_free(v); - } - done: - tor_free(v); -} - #define UTIL_LEGACY(name) \ { #name, test_util_ ## name , 0, NULL, NULL } @@ -4322,6 +4302,35 @@ test_util_ipv4_validation(void *arg) return; } +static void +test_util_writepid(void *arg) +{ + (void) arg; + + char *contents = NULL; + const char *fname = get_fname("tmp_pid"); + unsigned long pid; + char c; + + write_pidfile(fname); + + contents = read_file_to_str(fname, 0, NULL); + tt_assert(contents); + + int n = sscanf(contents, "%lu\n%c", &pid, &c); + tt_int_op(n, OP_EQ, 1); + tt_uint_op(pid, OP_EQ, +#ifdef _WIN32 + _getpid() +#else + getpid() +#endif + ); + + done: + tor_free(contents); +} + struct testcase_t util_tests[] = { UTIL_LEGACY(time), UTIL_TEST(parse_http_time, 0), @@ -4348,7 +4357,6 @@ struct testcase_t util_tests[] = { UTIL_LEGACY(di_ops), UTIL_TEST(round_to_next_multiple_of, 0), UTIL_TEST(laplace, 0), - UTIL_TEST(strclear, 0), UTIL_TEST(find_str_at_start_of_line, 0), UTIL_TEST(string_is_C_identifier, 0), UTIL_TEST(asprintf, 0), @@ -4389,6 +4397,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(max_mem, 0), UTIL_TEST(hostname_validation, 0), UTIL_TEST(ipv4_validation, 0), + UTIL_TEST(writepid, 0), END_OF_TESTCASES }; diff --git a/src/test/test_util_slow.c b/src/test/test_util_slow.c index a597ef3cbc..dcd0c9af36 100644 --- a/src/test/test_util_slow.c +++ b/src/test/test_util_slow.c @@ -107,9 +107,11 @@ run_util_spawn_background(const char *argv[], const char *expected_out, #ifdef _WIN32 tt_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE); tt_assert(process_handle->stderr_pipe != INVALID_HANDLE_VALUE); + tt_assert(process_handle->stdin_pipe != INVALID_HANDLE_VALUE); #else tt_assert(process_handle->stdout_pipe >= 0); tt_assert(process_handle->stderr_pipe >= 0); + tt_assert(process_handle->stdin_pipe >= 0); #endif /* Check stdout */ diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c index aaff5069be..77053b0760 100644 --- a/src/test/test_workqueue.c +++ b/src/test/test_workqueue.c @@ -18,6 +18,8 @@ #include <event.h> #endif +#define MAX_INFLIGHT (1<<16) + static int opt_verbose = 0; static int opt_n_threads = 8; static int opt_n_items = 10000; @@ -348,7 +350,7 @@ main(int argc, char **argv) } if (opt_n_threads < 1 || opt_n_items < 1 || opt_n_inflight < 1 || opt_n_lowwater < 0 || - opt_n_cancel > opt_n_inflight || + opt_n_cancel > opt_n_inflight || opt_n_inflight > MAX_INFLIGHT || opt_ratio_rsa < 0) { help(); return 1; @@ -356,7 +358,7 @@ main(int argc, char **argv) init_logging(1); crypto_global_init(1, NULL, NULL); - crypto_seed_rng(1); + crypto_seed_rng(); rq = replyqueue_new(as_flags); tor_assert(rq); diff --git a/src/test/test_zero_length_keys.sh.in b/src/test/test_zero_length_keys.sh.in new file mode 100644 index 0000000000..d1492d5e20 --- /dev/null +++ b/src/test/test_zero_length_keys.sh.in @@ -0,0 +1,10 @@ +#!@SHELL@ +# Check that tor regenerates keys when key files are zero-length + +exitcode=0 + +@SHELL@ @abs_top_srcdir@/src/test/zero_length_keys.sh "@builddir@/src/or/tor" -z || exitcode=1 +@SHELL@ @abs_top_srcdir@/src/test/zero_length_keys.sh "@builddir@/src/or/tor" -d || exitcode=1 +@SHELL@ @abs_top_srcdir@/src/test/zero_length_keys.sh "@builddir@/src/or/tor" -e || exitcode=1 + +exit ${exitcode} diff --git a/src/test/testing_common.c b/src/test/testing_common.c index d7d6dacee6..7f387c0b3d 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -165,18 +165,21 @@ static crypto_pk_t *pregen_keys[5] = {NULL, NULL, NULL, NULL, NULL}; crypto_pk_t * pk_generate(int idx) { + int res; #ifdef CACHE_GENERATED_KEYS tor_assert(idx < N_PREGEN_KEYS); if (! pregen_keys[idx]) { pregen_keys[idx] = crypto_pk_new(); - tor_assert(!crypto_pk_generate_key(pregen_keys[idx])); + res = crypto_pk_generate_key(pregen_keys[idx]); + tor_assert(!res); } return crypto_pk_dup_key(pregen_keys[idx]); #else crypto_pk_t *result; (void) idx; result = crypto_pk_new(); - tor_assert(!crypto_pk_generate_key(result)); + res = crypto_pk_generate_key(result); + tor_assert(!res); return result; #endif } @@ -266,8 +269,8 @@ main(int c, const char **v) printf("Can't initialize crypto subsystem; exiting.\n"); return 1; } - crypto_set_tls_dh_prime(NULL); - crypto_seed_rng(1); + crypto_set_tls_dh_prime(); + crypto_seed_rng(); rep_hist_init(); network_init(); setup_directory(); diff --git a/src/test/zero_length_keys.sh b/src/test/zero_length_keys.sh index 4dea283fdb..3c61f8d465 100755 --- a/src/test/zero_length_keys.sh +++ b/src/test/zero_length_keys.sh @@ -3,13 +3,13 @@ # Test for bug #13111 - Tor fails to start if onion keys are zero length # # Usage: -# ./zero_length_keys.sh +# ./zero_length_keys.sh PATH_TO_TOR # Run all the tests below -# ./zero_length_keys.sh -z +# ./zero_length_keys.sh PATH_TO_TOR -z # Check tor will launch and regenerate zero-length keys -# ./zero_length_keys.sh -d +# ./zero_length_keys.sh PATH_TO_TOR -d # Check tor regenerates deleted keys (existing behaviour) -# ./zero_length_keys.sh -e +# ./zero_length_keys.sh PATH_TO_TOR -e # Check tor does not overwrite existing keys (existing behaviour) # # Exit Statuses: @@ -19,10 +19,16 @@ # 3: a command failed - the test could not be completed # -if [ $# -lt 1 ]; then +if [ $# -eq 0 ] || [ ! -f ${1} ] || [ ! -x ${1} ]; then + echo "Usage: ${0} PATH_TO_TOR [-z|-d|-e]" + exit 1 +elif [ $# -eq 1 ]; then echo "Testing that tor correctly handles zero-length keys" - "$0" -z && "$0" -d && "$0" -e + "$0" "${1}" -z && "$0" "${1}" -d && "$0" "${1}" -e exit $? +else #[$# -gt 1 ]; then + TOR_BINARY="${1}" + shift fi DATA_DIR=`mktemp -d -t tor_zero_length_keys.XXXXXX` @@ -36,9 +42,11 @@ if [ ! -d "$DATA_DIR" ]; then fi trap "rm -rf '$DATA_DIR'" 0 +touch "$DATA_DIR"/empty_torrc + # DisableNetwork means that the ORPort won't actually be opened. # 'ExitRelay 0' suppresses a warning. -TOR="./src/or/tor --hush --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0" +TOR="${TOR_BINARY} --hush --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f $DATA_DIR/empty_torrc" if [ -s "$DATA_DIR"/keys/secret_id_key ] && [ -s "$DATA_DIR"/keys/secret_onion_key ] && [ -s "$DATA_DIR"/keys/secret_onion_key_ntor ]; then |