summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/include.am31
-rw-r--r--src/test/log_test_helpers.c111
-rw-r--r--src/test/log_test_helpers.h31
-rw-r--r--src/test/rend_test_helpers.c66
-rw-r--r--src/test/rend_test_helpers.h15
-rw-r--r--src/test/test.c13
-rw-r--r--src/test/test_address.c325
-rwxr-xr-xsrc/test/test_bt.sh10
-rw-r--r--src/test/test_bt.sh.in9
-rw-r--r--src/test/test_bt_cl.c11
-rw-r--r--src/test/test_compat_libevent.c238
-rw-r--r--src/test/test_crypto_slow.c2
-rw-r--r--src/test/test_dir_handle_get.c2533
-rw-r--r--src/test/test_keypin.c13
-rwxr-xr-xsrc/test/test_ntor.sh9
-rw-r--r--src/test/test_ntor.sh.in9
-rw-r--r--src/test/test_policy.c192
-rw-r--r--src/test/test_routerset.c109
-rw-r--r--src/test/test_tortls.c2950
-rw-r--r--src/test/test_util_format.c76
-rwxr-xr-xsrc/test/test_zero_length_keys.sh10
-rw-r--r--src/test/test_zero_length_keys.sh.in10
-rw-r--r--src/test/vote_descriptors.inc94
23 files changed, 6751 insertions, 116 deletions
diff --git a/src/test/include.am b/src/test/include.am
index 762216e6dc..e056138b48 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -1,4 +1,9 @@
+export PYTHON=@PYTHON@
+export SHELL=@SHELL@
+export abs_top_srcdir=@abs_top_srcdir@
+export builddir=@builddir@
+
TESTSCRIPTS = src/test/test_zero_length_keys.sh
if USEPYTHON
@@ -16,18 +21,11 @@ TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min
TEST_CHUTNEY_FLAVORS_MIXED = mixed
### 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.
+### doesn't require that yet.
###
# 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+= \
@@ -51,6 +49,7 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# matters a lot there, and is quite hard to debug if you forget to do it.
src_test_test_SOURCES = \
+ src/test/log_test_helpers.c \
src/test/test.c \
src/test/test_accounting.c \
src/test/test_addr.c \
@@ -63,6 +62,7 @@ src_test_test_SOURCES = \
src/test/test_checkdir.c \
src/test/test_circuitlist.c \
src/test/test_circuitmux.c \
+ src/test/test_compat_libevent.c \
src/test/test_config.c \
src/test/test_containers.c \
src/test/test_controller.c \
@@ -70,6 +70,7 @@ src_test_test_SOURCES = \
src/test/test_crypto.c \
src/test/test_data.c \
src/test/test_dir.c \
+ src/test/test_dir_handle_get.c \
src/test/test_entryconn.c \
src/test/test_entrynodes.c \
src/test/test_guardfraction.c \
@@ -95,10 +96,12 @@ src_test_test_SOURCES = \
src/test/test_socks.c \
src/test/test_status.c \
src/test/test_threads.c \
+ src/test/test_tortls.c \
src/test/test_util.c \
src/test/test_util_format.c \
src/test/test_helpers.c \
- src/test/test_dns.c \
+ src/test/rend_test_helpers.c \
+ src/test/test_dns.c \
src/test/testing_common.c \
src/ext/tinytest.c
@@ -164,13 +167,16 @@ src_test_test_workqueue_LDADD = src/or/libtor-testing.a \
noinst_HEADERS+= \
src/test/fakechans.h \
+ src/test/log_test_helpers.h \
+ src/test/rend_test_helpers.h \
src/test/test.h \
src/test/test_helpers.h \
src/test/test_descriptors.inc \
src/test/example_extrainfo.inc \
src/test/failing_routerdescs.inc \
src/test/ed25519_vectors.inc \
- src/test/test_descriptors.inc
+ src/test/test_descriptors.inc \
+ src/test/vote_descriptors.inc
noinst_PROGRAMS+= src/test/test-ntor-cl
src_test_test_ntor_cl_SOURCES = src/test/test_ntor_cl.c
@@ -195,4 +201,7 @@ EXTRA_DIST += \
src/test/ntor_ref.py \
src/test/slownacl_curve25519.py \
src/test/zero_length_keys.sh \
- src/test/test_keygen.sh
+ src/test/test_keygen.sh \
+ src/test/test_zero_length_keys.sh \
+ src/test/test_ntor.sh src/test/test_bt.sh \
+ src/test/test-network.sh
diff --git a/src/test/log_test_helpers.c b/src/test/log_test_helpers.c
new file mode 100644
index 0000000000..51b5f9b7b1
--- /dev/null
+++ b/src/test/log_test_helpers.c
@@ -0,0 +1,111 @@
+/* Copyright (c) 2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+#define LOG_PRIVATE
+#include "torlog.h"
+#include "log_test_helpers.h"
+
+static smartlist_t *saved_logs = NULL;
+
+int
+setup_capture_of_logs(int new_level)
+{
+ int previous_log = log_global_min_severity_;
+ log_global_min_severity_ = new_level;
+ mock_clean_saved_logs();
+ MOCK(logv, mock_saving_logv);
+ return previous_log;
+}
+
+void
+teardown_capture_of_logs(int prev)
+{
+ UNMOCK(logv);
+ log_global_min_severity_ = prev;
+ mock_clean_saved_logs();
+}
+
+void
+mock_clean_saved_logs(void)
+{
+ if (!saved_logs)
+ return;
+ SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
+ { tor_free(m->generated_msg); tor_free(m); });
+ smartlist_free(saved_logs);
+ saved_logs = NULL;
+}
+
+static mock_saved_log_entry_t *
+mock_get_log_entry(int ix)
+{
+ int saved_log_count = mock_saved_log_number();
+ if (ix < 0) {
+ ix = saved_log_count + ix;
+ }
+
+ if (saved_log_count <= ix)
+ return NULL;
+
+ return smartlist_get(saved_logs, ix);
+}
+
+const char *
+mock_saved_log_at(int ix)
+{
+ mock_saved_log_entry_t *ent = mock_get_log_entry(ix);
+ if (ent)
+ return ent->generated_msg;
+ else
+ return "";
+}
+
+int
+mock_saved_severity_at(int ix)
+{
+ mock_saved_log_entry_t *ent = mock_get_log_entry(ix);
+ if (ent)
+ return ent->severity;
+ else
+ return -1;
+}
+
+int
+mock_saved_log_number(void)
+{
+ if (!saved_logs)
+ return 0;
+ return smartlist_len(saved_logs);
+}
+
+const smartlist_t *
+mock_saved_logs(void)
+{
+ return saved_logs;
+}
+
+void
+mock_saving_logv(int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap)
+{
+ (void)domain;
+ char *buf = tor_malloc_zero(10240);
+ int n;
+ n = tor_vsnprintf(buf,10240,format,ap);
+ tor_assert(n < 10240-1);
+ buf[n]='\n';
+ buf[n+1]='\0';
+
+ mock_saved_log_entry_t *e = tor_malloc_zero(sizeof(mock_saved_log_entry_t));
+ e->severity = severity;
+ e->funcname = funcname;
+ e->suffix = suffix;
+ e->format = format;
+ e->generated_msg = tor_strdup(buf);
+ tor_free(buf);
+
+ if (!saved_logs)
+ saved_logs = smartlist_new();
+ smartlist_add(saved_logs, e);
+}
+
diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h
new file mode 100644
index 0000000000..af8e8a60e7
--- /dev/null
+++ b/src/test/log_test_helpers.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2014-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+
+#ifndef TOR_LOG_TEST_HELPERS_H
+#define TOR_LOG_TEST_HELPERS_H
+
+typedef struct mock_saved_log_entry_t {
+ int severity;
+ const char *funcname;
+ const char *suffix;
+ const char *format;
+ char *generated_msg;
+ struct mock_saved_log_entry_t *next;
+} mock_saved_log_entry_t;
+
+void mock_saving_logv(int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap)
+ CHECK_PRINTF(5, 0);
+void mock_clean_saved_logs(void);
+const smartlist_t *mock_saved_logs(void);
+int setup_capture_of_logs(int new_level);
+void teardown_capture_of_logs(int prev);
+const char *mock_saved_log_at(int ix);
+int mock_saved_severity_at(int ix);
+int mock_saved_log_number(void);
+
+#endif
+
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
new file mode 100644
index 0000000000..0a1b1c8967
--- /dev/null
+++ b/src/test/rend_test_helpers.c
@@ -0,0 +1,66 @@
+#include "rend_test_helpers.h"
+
+#include "test.h"
+#include "rendcommon.h"
+
+void
+generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc,
+ char **service_id, int intro_points)
+{
+ rend_service_descriptor_t *generated = NULL;
+ smartlist_t *descs = smartlist_new();
+ time_t now;
+
+ now = time(NULL) + time_diff;
+ create_descriptor(&generated, service_id, intro_points);
+ generated->timestamp = now;
+
+ rend_encode_v2_descriptors(descs, generated, now, 0, REND_NO_AUTH, NULL,
+ NULL);
+ *desc = ((rend_encoded_v2_service_descriptor_t *)smartlist_get(descs, 0));
+
+ smartlist_free(descs);
+ rend_service_descriptor_free(generated);
+}
+
+void
+create_descriptor(rend_service_descriptor_t **generated, char **service_id,
+ int intro_points)
+{
+ crypto_pk_t *pk1 = NULL;
+ crypto_pk_t *pk2 = NULL;
+ int i;
+
+ *service_id = tor_malloc(REND_SERVICE_ID_LEN_BASE32+1);
+ pk1 = pk_generate(0);
+ pk2 = pk_generate(1);
+
+ *generated = tor_malloc_zero(sizeof(rend_service_descriptor_t));
+ (*generated)->pk = crypto_pk_dup_key(pk1);
+ rend_get_service_id((*generated)->pk, *service_id);
+
+ (*generated)->version = 2;
+ (*generated)->protocols = 42;
+ (*generated)->intro_nodes = smartlist_new();
+
+ for (i = 0; i < intro_points; i++) {
+ rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t));
+ crypto_pk_t *okey = pk_generate(2 + i);
+ intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+ intro->extend_info->onion_key = okey;
+ crypto_pk_get_digest(intro->extend_info->onion_key,
+ intro->extend_info->identity_digest);
+ intro->extend_info->nickname[0] = '$';
+ base16_encode(intro->extend_info->nickname + 1,
+ sizeof(intro->extend_info->nickname) - 1,
+ intro->extend_info->identity_digest, DIGEST_LEN);
+ tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536));
+ intro->extend_info->port = 1 + crypto_rand_int(65535);
+ intro->intro_key = crypto_pk_dup_key(pk2);
+ smartlist_add((*generated)->intro_nodes, intro);
+ }
+
+ crypto_pk_free(pk1);
+ crypto_pk_free(pk2);
+}
+
diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h
new file mode 100644
index 0000000000..1ef03747d7
--- /dev/null
+++ b/src/test/rend_test_helpers.h
@@ -0,0 +1,15 @@
+/* Copyright (c) 2014-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+
+#ifndef TOR_REND_TEST_HELPERS_H
+#define TOR_REND_TEST_HELPERS_H
+
+void generate_desc(int time_diff, rend_encoded_v2_service_descriptor_t **desc,
+ char **service_id, int intro_points);
+void create_descriptor(rend_service_descriptor_t **generated,
+ char **service_id, int intro_points);
+
+#endif
+
diff --git a/src/test/test.c b/src/test/test.c
index aff7d8e048..d8aca276e7 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -47,6 +47,7 @@ double fabs(double x);
#include "connection_edge.h"
#include "geoip.h"
#include "rendcommon.h"
+#include "rendcache.h"
#include "test.h"
#include "torgzip.h"
#include "memarea.h"
@@ -494,6 +495,9 @@ test_rend_fns(void *arg)
tt_str_op(address6,OP_EQ, "abcdefghijklmnop");
tt_assert(BAD_HOSTNAME == parse_extended_hostname(address7));
+ /* Initialize the service cache. */
+ rend_cache_init();
+
pk1 = pk_generate(0);
pk2 = pk_generate(1);
generated = tor_malloc_zero(sizeof(rend_service_descriptor_t));
@@ -1106,7 +1110,7 @@ static struct testcase_t test_array[] = {
ENT(onion_queues),
{ "ntor_handshake", test_ntor_handshake, 0, NULL, NULL },
ENT(circuit_timeout),
- ENT(rend_fns),
+ FORK(rend_fns),
ENT(geoip),
FORK(geoip_with_pt),
FORK(stats),
@@ -1125,12 +1129,14 @@ extern struct testcase_t channeltls_tests[];
extern struct testcase_t checkdir_tests[];
extern struct testcase_t circuitlist_tests[];
extern struct testcase_t circuitmux_tests[];
+extern struct testcase_t compat_libevent_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[];
+extern struct testcase_t dir_handle_get_tests[];
extern struct testcase_t entryconn_tests[];
extern struct testcase_t entrynodes_tests[];
extern struct testcase_t guardfraction_tests[];
@@ -1157,6 +1163,7 @@ extern struct testcase_t scheduler_tests[];
extern struct testcase_t socks_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t thread_tests[];
+extern struct testcase_t tortls_tests[];
extern struct testcase_t util_tests[];
extern struct testcase_t util_format_tests[];
extern struct testcase_t dns_tests[];
@@ -1174,12 +1181,14 @@ struct testgroup_t testgroups[] = {
{ "checkdir/", checkdir_tests },
{ "circuitlist/", circuitlist_tests },
{ "circuitmux/", circuitmux_tests },
+ { "compat/libevent/", compat_libevent_tests },
{ "config/", config_tests },
{ "container/", container_tests },
{ "control/", controller_tests },
{ "control/event/", controller_event_tests },
{ "crypto/", crypto_tests },
{ "dir/", dir_tests },
+ { "dir_handle_get/", dir_handle_get_tests },
{ "dir/md/", microdesc_tests },
{ "entryconn/", entryconn_tests },
{ "entrynodes/", entrynodes_tests },
@@ -1203,6 +1212,7 @@ struct testgroup_t testgroups[] = {
{ "scheduler/", scheduler_tests },
{ "socks/", socks_tests },
{ "status/" , status_tests },
+ { "tortls/", tortls_tests },
{ "util/", util_tests },
{ "util/format/", util_format_tests },
{ "util/logging/", logging_tests },
@@ -1210,3 +1220,4 @@ struct testgroup_t testgroups[] = {
{ "dns/", dns_tests },
END_OF_GROUPS
};
+
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 9d6456315c..e48c06a6c4 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -74,35 +74,79 @@ sockaddr_in_from_string(const char *ip_str, struct sockaddr_in *out)
}
/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
- * that points to 127.0.0.1. Otherwise, return 0.
+ * that is an IPv4 or IPv6 localhost address. Otherwise, return 0.
*/
static int
smartlist_contains_localhost_tor_addr(smartlist_t *smartlist)
{
- int found_localhost = 0;
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ if (tor_addr_is_loopback(tor_addr)) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
- struct sockaddr_in *sockaddr_localhost;
- struct sockaddr_storage *sockaddr_to_check;
+ return 0;
+}
- sockaddr_localhost = sockaddr_in_from_string("127.0.0.1",NULL);
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is an IPv4 or IPv6 multicast address. Otherwise, return 0.
+ */
+static int
+smartlist_contains_multicast_tor_addr(smartlist_t *smartlist)
+{
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ if (tor_addr_is_multicast(tor_addr)) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
- sockaddr_to_check = tor_malloc(sizeof(struct sockaddr_in));
+ return 0;
+}
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is an IPv4 or IPv6 internal address. Otherwise, return 0.
+ */
+static int
+smartlist_contains_internal_tor_addr(smartlist_t *smartlist)
+{
SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
- tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
- sizeof(struct sockaddr_in));
+ if (tor_addr_is_internal(tor_addr, 0)) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
+
+ return 0;
+}
- if (sockaddr_in_are_equal((struct sockaddr_in *)sockaddr_to_check,
- sockaddr_localhost)) {
- found_localhost = 1;
- break;
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is an IPv4 address. Otherwise, return 0.
+ */
+static int
+smartlist_contains_ipv4_tor_addr(smartlist_t *smartlist)
+{
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ if (tor_addr_is_v4(tor_addr)) {
+ return 1;
}
} SMARTLIST_FOREACH_END(tor_addr);
- tor_free(sockaddr_localhost);
- tor_free(sockaddr_to_check);
+ return 0;
+}
+
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is an IPv6 address. Otherwise, return 0.
+ */
+static int
+smartlist_contains_ipv6_tor_addr(smartlist_t *smartlist)
+{
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ /* Since there's no tor_addr_is_v6, assume all non-v4s are v6 */
+ if (!tor_addr_is_v4(tor_addr)) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
- return found_localhost;
+ return 0;
}
#ifdef HAVE_IFADDRS_TO_SMARTLIST
@@ -634,12 +678,263 @@ test_address_udp_socket_trick_blackbox(void *arg)
return;
}
+static void
+test_address_get_if_addrs_list_internal(void *arg)
+{
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_address_list(LOG_ERR, 1);
+
+ tt_assert(results != NULL);
+ /* Assume every system has at least 1 non-local non-multicast IPv4
+ * interface, even if it is an internal one */
+ tt_int_op(smartlist_len(results),>=,1);
+
+ tt_assert(!smartlist_contains_localhost_tor_addr(results));
+ tt_assert(!smartlist_contains_multicast_tor_addr(results));
+ /* The list may or may not contain internal addresses */
+
+ tt_assert(smartlist_contains_ipv4_tor_addr(results));
+ tt_assert(!smartlist_contains_ipv6_tor_addr(results));
+
+ done:
+ free_interface_address_list(results);
+ return;
+}
+
+static void
+test_address_get_if_addrs_list_no_internal(void *arg)
+{
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_address_list(LOG_ERR, 0);
+
+ tt_assert(results != NULL);
+ /* Work even on systems with only internal IPv4 addresses */
+ tt_int_op(smartlist_len(results),>=,0);
+
+ tt_assert(!smartlist_contains_localhost_tor_addr(results));
+ tt_assert(!smartlist_contains_multicast_tor_addr(results));
+ tt_assert(!smartlist_contains_internal_tor_addr(results));
+
+ /* The list may or may not contain IPv4 addresses */
+ tt_assert(!smartlist_contains_ipv6_tor_addr(results));
+
+ done:
+ free_interface_address_list(results);
+ return;
+}
+
+static void
+test_address_get_if_addrs6_list_internal(void *arg)
+{
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_address6_list(LOG_ERR, AF_INET6, 1);
+
+ tt_assert(results != NULL);
+ /* Work even on systems without IPv6 interfaces */
+ tt_int_op(smartlist_len(results),>=,0);
+
+ tt_assert(!smartlist_contains_localhost_tor_addr(results));
+ tt_assert(!smartlist_contains_multicast_tor_addr(results));
+ /* The list may or may not contain internal addresses */
+
+ tt_assert(!smartlist_contains_ipv4_tor_addr(results));
+ /* The list may or may not contain IPv6 addresses */
+
+ done:
+ free_interface_address6_list(results);
+ return;
+}
+
+static void
+test_address_get_if_addrs6_list_no_internal(void *arg)
+{
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_address6_list(LOG_ERR, AF_INET6, 0);
+
+ tt_assert(results != NULL);
+ /* Work even on systems without IPv6 interfaces */
+ tt_int_op(smartlist_len(results),>=,0);
+
+ tt_assert(!smartlist_contains_localhost_tor_addr(results));
+ tt_assert(!smartlist_contains_multicast_tor_addr(results));
+ tt_assert(!smartlist_contains_internal_tor_addr(results));
+
+ tt_assert(!smartlist_contains_ipv4_tor_addr(results));
+ /* The list may or may not contain IPv6 addresses */
+
+ done:
+ free_interface_address6_list(results);
+ return;
+}
+
+static int called_get_interface_addresses_raw = 0;
+
+static smartlist_t *
+mock_get_interface_addresses_raw_fail(int severity)
+{
+ (void)severity;
+
+ called_get_interface_addresses_raw++;
+ return smartlist_new();
+}
+
+static int called_get_interface_address6_via_udp_socket_hack = 0;
+
+static int
+mock_get_interface_address6_via_udp_socket_hack_fail(int severity,
+ sa_family_t family,
+ tor_addr_t *addr)
+{
+ (void)severity;
+ (void)family;
+ (void)addr;
+
+ called_get_interface_address6_via_udp_socket_hack++;
+ return -1;
+}
+
+static void
+test_address_get_if_addrs_internal_fail(void *arg)
+{
+ smartlist_t *results1 = NULL, *results2 = NULL;
+ int rv = 0;
+ uint32_t ipv4h_addr = 0;
+ tor_addr_t ipv6_addr;
+
+ memset(&ipv6_addr, 0, sizeof(tor_addr_t));
+
+ (void)arg;
+
+ MOCK(get_interface_addresses_raw,
+ mock_get_interface_addresses_raw_fail);
+ MOCK(get_interface_address6_via_udp_socket_hack,
+ mock_get_interface_address6_via_udp_socket_hack_fail);
+
+ results1 = get_interface_address6_list(LOG_ERR, AF_INET6, 1);
+ tt_assert(results1 != NULL);
+ tt_int_op(smartlist_len(results1),==,0);
+
+ results2 = get_interface_address_list(LOG_ERR, 1);
+ tt_assert(results2 != NULL);
+ tt_int_op(smartlist_len(results2),==,0);
+
+ rv = get_interface_address6(LOG_ERR, AF_INET6, &ipv6_addr);
+ tt_assert(rv == -1);
+
+ rv = get_interface_address(LOG_ERR, &ipv4h_addr);
+ tt_assert(rv == -1);
+
+ done:
+ UNMOCK(get_interface_addresses_raw);
+ UNMOCK(get_interface_address6_via_udp_socket_hack);
+ free_interface_address6_list(results1);
+ free_interface_address6_list(results2);
+ return;
+}
+
+static void
+test_address_get_if_addrs_no_internal_fail(void *arg)
+{
+ smartlist_t *results1 = NULL, *results2 = NULL;
+
+ (void)arg;
+
+ MOCK(get_interface_addresses_raw,
+ mock_get_interface_addresses_raw_fail);
+ MOCK(get_interface_address6_via_udp_socket_hack,
+ mock_get_interface_address6_via_udp_socket_hack_fail);
+
+ results1 = get_interface_address6_list(LOG_ERR, AF_INET6, 0);
+ tt_assert(results1 != NULL);
+ tt_int_op(smartlist_len(results1),==,0);
+
+ results2 = get_interface_address_list(LOG_ERR, 0);
+ tt_assert(results2 != NULL);
+ tt_int_op(smartlist_len(results2),==,0);
+
+ done:
+ UNMOCK(get_interface_addresses_raw);
+ UNMOCK(get_interface_address6_via_udp_socket_hack);
+ free_interface_address6_list(results1);
+ free_interface_address6_list(results2);
+ return;
+}
+
+static void
+test_address_get_if_addrs(void *arg)
+{
+ int rv;
+ uint32_t addr_h = 0;
+ tor_addr_t tor_addr;
+
+ (void)arg;
+
+ rv = get_interface_address(LOG_ERR, &addr_h);
+
+ /* Assume every system has at least 1 non-local non-multicast IPv4
+ * interface, even if it is an internal one */
+ tt_assert(rv == 0);
+ tor_addr_from_ipv4h(&tor_addr, addr_h);
+
+ tt_assert(!tor_addr_is_loopback(&tor_addr));
+ tt_assert(!tor_addr_is_multicast(&tor_addr));
+ /* The address may or may not be an internal address */
+
+ tt_assert(tor_addr_is_v4(&tor_addr));
+
+ done:
+ return;
+}
+
+static void
+test_address_get_if_addrs6(void *arg)
+{
+ int rv;
+ tor_addr_t tor_addr;
+
+ (void)arg;
+
+ rv = get_interface_address6(LOG_ERR, AF_INET6, &tor_addr);
+
+ /* Work even on systems without IPv6 interfaces */
+ if (rv == 0) {
+ tt_assert(!tor_addr_is_loopback(&tor_addr));
+ tt_assert(!tor_addr_is_multicast(&tor_addr));
+ /* The address may or may not be an internal address */
+
+ tt_assert(!tor_addr_is_v4(&tor_addr));
+ }
+
+ 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),
+ ADDRESS_TEST(get_if_addrs_list_internal, 0),
+ ADDRESS_TEST(get_if_addrs_list_no_internal, 0),
+ ADDRESS_TEST(get_if_addrs6_list_internal, 0),
+ ADDRESS_TEST(get_if_addrs6_list_no_internal, 0),
+ ADDRESS_TEST(get_if_addrs_internal_fail, 0),
+ ADDRESS_TEST(get_if_addrs_no_internal_fail, 0),
+ ADDRESS_TEST(get_if_addrs, 0),
+ ADDRESS_TEST(get_if_addrs6, 0),
#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 b/src/test/test_bt.sh
new file mode 100755
index 0000000000..f55f451f92
--- /dev/null
+++ b/src/test/test_bt.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Test backtrace functionality.
+
+exitcode=0
+
+"${builddir:-.}/src/test/test-bt-cl" backtraces || exit 77
+"${builddir:-.}/src/test/test-bt-cl" assert | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode=1
+"${builddir:-.}/src/test/test-bt-cl" crash | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode=1
+
+exit ${exitcode}
diff --git a/src/test/test_bt.sh.in b/src/test/test_bt.sh.in
deleted file mode 100644
index ca8be965d4..0000000000
--- a/src/test/test_bt.sh.in
+++ /dev/null
@@ -1,9 +0,0 @@
-#!@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 01c621eb0e..dabaee6e0a 100644
--- a/src/test/test_bt_cl.c
+++ b/src/test/test_bt_cl.c
@@ -84,15 +84,24 @@ main(int argc, char **argv)
if (argc < 2) {
puts("I take an argument. It should be \"assert\" or \"crash\" or "
- "\"none\"");
+ "\"backtraces\" or \"none\"");
return 1;
}
+
+#if !(defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
+ defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION))
+ puts("Backtrace reporting is not supported on this platform");
+ return 77;
+#endif
+
if (!strcmp(argv[1], "assert")) {
crashtype = 1;
} else if (!strcmp(argv[1], "crash")) {
crashtype = 0;
} else if (!strcmp(argv[1], "none")) {
crashtype = -1;
+ } else if (!strcmp(argv[1], "backtraces")) {
+ return 0;
} else {
puts("Argument should be \"assert\" or \"crash\" or \"none\"");
return 1;
diff --git a/src/test/test_compat_libevent.c b/src/test/test_compat_libevent.c
new file mode 100644
index 0000000000..96502df308
--- /dev/null
+++ b/src/test/test_compat_libevent.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2010-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define COMPAT_LIBEVENT_PRIVATE
+#include "orconfig.h"
+#include "or.h"
+
+#include "test.h"
+
+#include "compat_libevent.h"
+
+#ifdef HAVE_EVENT2_EVENT_H
+#include <event2/event.h>
+#include <event2/thread.h>
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#endif
+#else
+#include <event.h>
+#endif
+
+#include "log_test_helpers.h"
+
+#define NS_MODULE compat_libevent
+
+static void
+test_compat_libevent_logging_callback(void *ignored)
+{
+ (void)ignored;
+ int previous_log = setup_capture_of_logs(LOG_DEBUG);
+
+ libevent_logging_callback(_EVENT_LOG_DEBUG, "hello world");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Message from libevent: hello world\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_DEBUG);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_MSG, "hello world another time");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Message from libevent: hello world another time\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_WARN, "hello world a third time");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Warning from libevent: hello world a third time\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_ERR, "hello world a fourth time");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Error from libevent: hello world a fourth time\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_ERR);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(42, "hello world a fifth time");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Message [42] from libevent: hello world a fifth time\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_DEBUG,
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ );
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "Message from libevent: "
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_DEBUG);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(42, "xxx\n");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "Message [42] from libevent: xxx\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
+
+ suppress_libevent_log_msg("something");
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_MSG, "hello there");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Message from libevent: hello there\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_MSG, "hello there something else");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 0);
+
+ // No way of verifying the result of this, it seems =/
+ configure_libevent_logging();
+
+ done:
+ suppress_libevent_log_msg(NULL);
+ teardown_capture_of_logs(previous_log);
+}
+
+static void
+test_compat_libevent_le_versions_compatibility(void *ignored)
+{
+ (void)ignored;
+ int res;
+
+ res = le_versions_compatibility(LE_OTHER);
+ tt_int_op(res, OP_EQ, 0);
+
+ res = le_versions_compatibility(V_OLD(0,9,'c'));
+ tt_int_op(res, OP_EQ, 1);
+
+ res = le_versions_compatibility(V(1,3,98));
+ tt_int_op(res, OP_EQ, 2);
+
+ res = le_versions_compatibility(V(1,4,98));
+ tt_int_op(res, OP_EQ, 3);
+
+ res = le_versions_compatibility(V(1,5,0));
+ tt_int_op(res, OP_EQ, 4);
+
+ res = le_versions_compatibility(V(2,0,0));
+ tt_int_op(res, OP_EQ, 4);
+
+ res = le_versions_compatibility(V(2,0,2));
+ tt_int_op(res, OP_EQ, 5);
+
+ done:
+ (void)0;
+}
+
+static void
+test_compat_libevent_tor_decode_libevent_version(void *ignored)
+{
+ (void)ignored;
+ le_version_t res;
+
+ res = tor_decode_libevent_version("SOMETHING WRONG");
+ tt_int_op(res, OP_EQ, LE_OTHER);
+
+ res = tor_decode_libevent_version("1.4.11");
+ tt_int_op(res, OP_EQ, V(1,4,11));
+
+ res = tor_decode_libevent_version("1.4.12b-stable");
+ tt_int_op(res, OP_EQ, V(1,4,12));
+
+ res = tor_decode_libevent_version("1.4.17b_stable");
+ tt_int_op(res, OP_EQ, V(1,4,17));
+
+ res = tor_decode_libevent_version("1.4.12!stable");
+ tt_int_op(res, OP_EQ, LE_OTHER);
+
+ res = tor_decode_libevent_version("1.4.12b!stable");
+ tt_int_op(res, OP_EQ, LE_OTHER);
+
+ res = tor_decode_libevent_version("1.4.13-");
+ tt_int_op(res, OP_EQ, V(1,4,13));
+
+ res = tor_decode_libevent_version("1.4.14_");
+ tt_int_op(res, OP_EQ, V(1,4,14));
+
+ res = tor_decode_libevent_version("1.4.15c-");
+ tt_int_op(res, OP_EQ, V(1,4,15));
+
+ res = tor_decode_libevent_version("1.4.16c_");
+ tt_int_op(res, OP_EQ, V(1,4,16));
+
+ res = tor_decode_libevent_version("1.4.17-s");
+ tt_int_op(res, OP_EQ, V(1,4,17));
+
+ res = tor_decode_libevent_version("1.5");
+ tt_int_op(res, OP_EQ, V(1,5,0));
+
+ res = tor_decode_libevent_version("1.2");
+ tt_int_op(res, OP_EQ, V(1,2,0));
+
+ res = tor_decode_libevent_version("1.2-");
+ tt_int_op(res, OP_EQ, LE_OTHER);
+
+ res = tor_decode_libevent_version("1.6e");
+ tt_int_op(res, OP_EQ, V_OLD(1,6,'e'));
+
+ done:
+ (void)0;
+}
+
+#if defined(LIBEVENT_VERSION)
+#define HEADER_VERSION LIBEVENT_VERSION
+#elif defined(_EVENT_VERSION)
+#define HEADER_VERSION _EVENT_VERSION
+#endif
+
+static void
+test_compat_libevent_header_version(void *ignored)
+{
+ (void)ignored;
+ const char *res;
+
+ res = tor_libevent_get_header_version_str();
+ tt_str_op(res, OP_EQ, HEADER_VERSION);
+
+ done:
+ (void)0;
+}
+
+struct testcase_t compat_libevent_tests[] = {
+ { "logging_callback", test_compat_libevent_logging_callback,
+ TT_FORK, NULL, NULL },
+ { "le_versions_compatibility",
+ test_compat_libevent_le_versions_compatibility, 0, NULL, NULL },
+ { "tor_decode_libevent_version",
+ test_compat_libevent_tor_decode_libevent_version, 0, NULL, NULL },
+ { "header_version", test_compat_libevent_header_version, 0, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c
index d0f50f83b9..853a08d886 100644
--- a/src/test/test_crypto_slow.c
+++ b/src/test/test_crypto_slow.c
@@ -217,7 +217,7 @@ test_libscrypt_eq_openssl(void *arg)
memset(buf2,0,64);
N = 1048576;
- maxmem = 2 * 1024 * 1024 * 1024; // 2 GB
+ maxmem = 2 * 1024 * 1024 * (uint64_t)1024; // 2 GB
libscrypt_retval =
libscrypt_scrypt((const uint8_t *)"pleaseletmein",
diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c
new file mode 100644
index 0000000000..5a84f17c12
--- /dev/null
+++ b/src/test/test_dir_handle_get.c
@@ -0,0 +1,2533 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define RENDCOMMON_PRIVATE
+#define GEOIP_PRIVATE
+
+#include "or.h"
+#include "config.h"
+#include "directory.h"
+#include "test.h"
+#include "connection.h"
+#include "rendcommon.h"
+#include "rendcache.h"
+#include "router.h"
+#include "routerlist.h"
+#include "rend_test_helpers.h"
+#include "microdesc.h"
+#include "test_helpers.h"
+#include "nodelist.h"
+#include "entrynodes.h"
+#include "routerparse.h"
+#include "networkstatus.h"
+#include "geoip.h"
+#include "dirserv.h"
+#include "torgzip.h"
+#include "dirvote.h"
+
+#ifdef _WIN32
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif
+
+#include "vote_descriptors.inc"
+
+#define NS_MODULE dir_handle_get
+
+static void
+connection_write_to_buf_mock(const char *string, size_t len,
+ connection_t *conn, int zlib)
+{
+ (void) zlib;
+
+ tor_assert(string);
+ tor_assert(conn);
+
+ write_to_buf(string, len, conn->outbuf);
+}
+
+#define GET(path) "GET " path " HTTP/1.0\r\n\r\n"
+#define NOT_FOUND "HTTP/1.0 404 Not found\r\n\r\n"
+#define BAD_REQUEST "HTTP/1.0 400 Bad request\r\n\r\n"
+#define SERVER_BUSY "HTTP/1.0 503 Directory busy, try again later\r\n\r\n"
+#define NOT_ENOUGH_CONSENSUS_SIGNATURES "HTTP/1.0 404 " \
+ "Consensus not signed by sufficient number of requested authorities\r\n\r\n"
+
+static tor_addr_t MOCK_TOR_ADDR;
+
+static void
+test_dir_handle_get_bad_request(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(directory_handle_command_get(conn, "", NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(header, OP_EQ, BAD_REQUEST);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_v1_command_not_found(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ // no frontpage configured
+ tt_ptr_op(get_dirportfrontpage(), OP_EQ, NULL);
+
+ /* V1 path */
+ tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0),
+ OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static const char*
+mock_get_dirportfrontpage(void)
+{
+ return "HELLO FROM FRONTPAGE";
+}
+
+static void
+test_dir_handle_get_v1_command(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0, body_len = 0;
+ const char *exp_body = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+ MOCK(get_dirportfrontpage, mock_get_dirportfrontpage);
+
+ exp_body = get_dirportfrontpage();
+ body_len = strlen(exp_body);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0),
+ OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, body_len+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/html\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 20\r\n"));
+
+ tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_str_op(body, OP_EQ, exp_body);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(get_dirportfrontpage);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+}
+
+static void
+test_dir_handle_get_not_found(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ /* Unrecognized path */
+ tt_int_op(directory_handle_command_get(conn, GET("/anything"), NULL, 0),
+ OP_EQ, 0);
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_robots_txt(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ tt_int_op(directory_handle_command_get(conn, GET("/tor/robots.txt"),
+ NULL, 0), OP_EQ, 0);
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, 29, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 28\r\n"));
+
+ tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_str_op(body, OP_EQ, "User-agent: *\r\nDisallow: /\r\n");
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+}
+
+static void
+test_dir_handle_get_bytes_txt(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0, body_len = 0;
+ char buff[30];
+ char *exp_body = NULL;
+ (void) data;
+
+ exp_body = directory_dump_request_log();
+ body_len = strlen(exp_body);
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ tt_int_op(directory_handle_command_get(conn, GET("/tor/bytes.txt"), NULL, 0),
+ OP_EQ, 0);
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, body_len+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Pragma: no-cache\r\n"));
+
+ sprintf(buff, "Content-Length: %ld\r\n", (long) body_len);
+ tt_assert(strstr(header, buff));
+
+ tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_str_op(body, OP_EQ, exp_body);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+}
+
+#define RENDEZVOUS2_GET(descid) GET("/tor/rendezvous2/" descid)
+static void
+test_dir_handle_get_rendezvous2_not_found_if_not_encrypted(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ // connection is not encrypted
+ tt_assert(!connection_dir_is_encrypted(conn))
+
+ tt_int_op(directory_handle_command_get(conn, RENDEZVOUS2_GET(), NULL, 0),
+ OP_EQ, 0);
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_rendezvous2_on_encrypted_conn_with_invalid_desc_id(
+ void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ // connection is encrypted
+ TO_CONN(conn)->linked = 1;
+ tt_assert(connection_dir_is_encrypted(conn));
+
+ tt_int_op(directory_handle_command_get(conn,
+ RENDEZVOUS2_GET("invalid-desc-id"), NULL, 0), OP_EQ, 0);
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(header, OP_EQ, BAD_REQUEST);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_rendezvous2_on_encrypted_conn_not_well_formed(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ // connection is encrypted
+ TO_CONN(conn)->linked = 1;
+ tt_assert(connection_dir_is_encrypted(conn));
+
+ //TODO: this cant be reached because rend_valid_descriptor_id() prevents this
+ //case to happen. This test is the same as
+ //test_dir_handle_get_rendezvous2_on_encrypted_conn_with_invalid_desc_id
+ //We should refactor to remove the case from the switch.
+
+ const char *req = RENDEZVOUS2_GET("1bababababababababababababababab");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(header, OP_EQ, BAD_REQUEST);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_rendezvous2_not_found(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ rend_cache_init();
+
+ // connection is encrypted
+ TO_CONN(conn)->linked = 1;
+ tt_assert(connection_dir_is_encrypted(conn));
+
+ const char *req = RENDEZVOUS2_GET("3xqunszqnaolrrfmtzgaki7mxelgvkje");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ rend_cache_free_all();
+}
+
+NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+NS_DECL(int, hid_serv_responsible_for_desc_id, (const char *id));
+
+static routerinfo_t *mock_routerinfo;
+static int hid_serv_responsible_for_desc_id_response;
+
+static const routerinfo_t *
+NS(router_get_my_routerinfo)(void)
+{
+ if (!mock_routerinfo) {
+ mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
+ }
+
+ return mock_routerinfo;
+}
+
+static int
+NS(hid_serv_responsible_for_desc_id)(const char *id)
+{
+ (void)id;
+ return hid_serv_responsible_for_desc_id_response;
+}
+
+static void
+test_dir_handle_get_rendezvous2_on_encrypted_conn_success(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ char buff[30];
+ char req[70];
+ rend_encoded_v2_service_descriptor_t *desc_holder = NULL;
+ char *service_id = NULL;
+ char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
+ size_t body_len = 0;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+ NS_MOCK(router_get_my_routerinfo);
+ NS_MOCK(hid_serv_responsible_for_desc_id);
+
+ rend_cache_init();
+ hid_serv_responsible_for_desc_id_response = 1;
+
+ /* create a valid rend service descriptor */
+ #define RECENT_TIME -10
+ generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
+
+ tt_int_op(rend_cache_store_v2_desc_as_dir(desc_holder->desc_str),
+ OP_EQ, RCS_OKAY);
+
+ base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
+ DIGEST_LEN);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ // connection is encrypted
+ TO_CONN(conn)->linked = 1;
+ tt_assert(connection_dir_is_encrypted(conn));
+
+ sprintf(req, RENDEZVOUS2_GET("%s"), desc_id_base32);
+
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ body_len = strlen(desc_holder->desc_str);
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, body_len+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Pragma: no-cache\r\n"));
+ sprintf(buff, "Content-Length: %ld\r\n", (long) body_len);
+ tt_assert(strstr(header, buff));
+
+ tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_str_op(body, OP_EQ, desc_holder->desc_str);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ NS_UNMOCK(router_get_my_routerinfo);
+ NS_UNMOCK(hid_serv_responsible_for_desc_id);
+
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+ rend_cache_free_all();
+}
+
+#define MICRODESC_GET(digest) GET("/tor/micro/d/" digest)
+static void
+test_dir_handle_get_micro_d_not_found(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ #define B64_256_1 "8/Pz8/u7vz8/Pz+7vz8/Pz+7u/Pz8/P7u/Pz8/P7u78"
+ #define B64_256_2 "zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMw"
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = MICRODESC_GET(B64_256_1 "-" B64_256_2);
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+
+ tor_free(conn);
+ tor_free(header);
+}
+
+static or_options_t *mock_options = NULL;
+static void
+init_mock_options(void)
+{
+ mock_options = malloc(sizeof(or_options_t));
+ memset(mock_options, 0, sizeof(or_options_t));
+ mock_options->TestingTorNetwork = 1;
+}
+
+static const or_options_t *
+mock_get_options(void)
+{
+ tor_assert(mock_options);
+ return mock_options;
+}
+
+static const char microdesc[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
+ "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
+ "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static void
+test_dir_handle_get_micro_d(void *data)
+{
+ dir_connection_t *conn = NULL;
+ microdesc_cache_t *mc = NULL ;
+ smartlist_t *list = NULL;
+ char digest[DIGEST256_LEN];
+ char digest_base64[128];
+ char path[80];
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ MOCK(get_options, mock_get_options);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* SETUP */
+ init_mock_options();
+ const char *fn = get_fname("dir_handle_datadir_test1");
+ mock_options->DataDirectory = tor_strdup(fn);
+
+#ifdef _WIN32
+ tt_int_op(0, OP_EQ, mkdir(mock_options->DataDirectory));
+#else
+ tt_int_op(0, OP_EQ, mkdir(mock_options->DataDirectory, 0700));
+#endif
+
+ /* Add microdesc to cache */
+ crypto_digest256(digest, microdesc, strlen(microdesc), DIGEST_SHA256);
+ base64_encode_nopad(digest_base64, sizeof(digest_base64),
+ (uint8_t *) digest, DIGEST256_LEN);
+
+ mc = get_microdesc_cache();
+ list = microdescs_add_to_cache(mc, microdesc, NULL, SAVED_NOWHERE, 0,
+ time(NULL), NULL);
+ tt_int_op(1, OP_EQ, smartlist_len(list));
+
+ /* Make the request */
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ sprintf(path, MICRODESC_GET("%s"), digest_base64);
+ tt_int_op(directory_handle_command_get(conn, path, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(microdesc)+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+
+ tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_str_op(body, OP_EQ, microdesc);
+
+ done:
+ UNMOCK(get_options);
+ UNMOCK(connection_write_to_buf_impl_);
+
+ if (mock_options)
+ tor_free(mock_options->DataDirectory);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+ smartlist_free(list);
+ microdesc_free_all();
+}
+
+static void
+test_dir_handle_get_micro_d_server_busy(void *data)
+{
+ dir_connection_t *conn = NULL;
+ microdesc_cache_t *mc = NULL ;
+ smartlist_t *list = NULL;
+ char digest[DIGEST256_LEN];
+ char digest_base64[128];
+ char path[80];
+ char *header = NULL;
+ (void) data;
+
+ MOCK(get_options, mock_get_options);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* SETUP */
+ init_mock_options();
+ const char *fn = get_fname("dir_handle_datadir_test2");
+ mock_options->DataDirectory = tor_strdup(fn);
+
+#ifdef _WIN32
+ tt_int_op(0, OP_EQ, mkdir(mock_options->DataDirectory));
+#else
+ tt_int_op(0, OP_EQ, mkdir(mock_options->DataDirectory, 0700));
+#endif
+
+ /* Add microdesc to cache */
+ crypto_digest256(digest, microdesc, strlen(microdesc), DIGEST_SHA256);
+ base64_encode_nopad(digest_base64, sizeof(digest_base64),
+ (uint8_t *) digest, DIGEST256_LEN);
+
+ mc = get_microdesc_cache();
+ list = microdescs_add_to_cache(mc, microdesc, NULL, SAVED_NOWHERE, 0,
+ time(NULL), NULL);
+ tt_int_op(1, OP_EQ, smartlist_len(list));
+
+ //Make it busy
+ mock_options->CountPrivateBandwidth = 1;
+
+ /* Make the request */
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ sprintf(path, MICRODESC_GET("%s"), digest_base64);
+ tt_int_op(directory_handle_command_get(conn, path, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(SERVER_BUSY, OP_EQ, header);
+
+ done:
+ UNMOCK(get_options);
+ UNMOCK(connection_write_to_buf_impl_);
+
+ if (mock_options)
+ tor_free(mock_options->DataDirectory);
+
+ tor_free(conn);
+ tor_free(header);
+ smartlist_free(list);
+ microdesc_free_all();
+}
+
+#define BRIDGES_PATH "/tor/networkstatus-bridges"
+static void
+test_dir_handle_get_networkstatus_bridges_not_found_without_auth(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(get_options, mock_get_options);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* SETUP */
+ init_mock_options();
+ mock_options->BridgeAuthoritativeDir = 1;
+ mock_options->BridgePassword_AuthDigest_ = tor_strdup("digest");
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ TO_CONN(conn)->linked = 1;
+
+ const char *req = GET(BRIDGES_PATH);
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(get_options);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(mock_options);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_networkstatus_bridges(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(get_options, mock_get_options);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* SETUP */
+ init_mock_options();
+ mock_options->BridgeAuthoritativeDir = 1;
+ mock_options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN);
+ crypto_digest256(mock_options->BridgePassword_AuthDigest_,
+ "abcdefghijklm12345", 18, DIGEST_SHA256);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ TO_CONN(conn)->linked = 1;
+
+ const char *req = "GET " BRIDGES_PATH " HTTP/1.0\r\n"
+ "Authorization: Basic abcdefghijklm12345\r\n\r\n";
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 0\r\n"));
+
+ done:
+ UNMOCK(get_options);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(mock_options);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_networkstatus_bridges_not_found_wrong_auth(void *data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(get_options, mock_get_options);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* SETUP */
+ init_mock_options();
+ mock_options->BridgeAuthoritativeDir = 1;
+ mock_options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN);
+ crypto_digest256(mock_options->BridgePassword_AuthDigest_,
+ "abcdefghijklm12345", 18, DIGEST_SHA256);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ TO_CONN(conn)->linked = 1;
+
+ const char *req = "GET " BRIDGES_PATH " HTTP/1.0\r\n"
+ "Authorization: Basic NOTSAMEDIGEST\r\n\r\n";
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(get_options);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(mock_options);
+ tor_free(conn);
+ tor_free(header);
+}
+
+#define SERVER_DESC_GET(id) GET("/tor/server/" id)
+static void
+test_dir_handle_get_server_descriptors_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = SERVER_DESC_GET("invalid");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+ tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_SERVER_BY_FP);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(mock_options);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_server_descriptors_all(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ /* Setup fake routerlist. */
+ helper_setup_fake_routerlist();
+
+ //TODO: change to router_get_my_extrainfo when testing "extra" path
+ NS_MOCK(router_get_my_routerinfo);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ // We are one of the routers
+ routerlist_t *our_routerlist = router_get_routerlist();
+ tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
+ mock_routerinfo = smartlist_get(our_routerlist->routers, 0);
+ set_server_identity_key(mock_routerinfo->identity_pkey);
+
+ /* Treat "all" requests as if they were unencrypted */
+ mock_routerinfo->cache_info.send_unencrypted = 1;
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = SERVER_DESC_GET("all");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ //TODO: Is this a BUG?
+ //It requires strlen(signed_descriptor_len)+1 as body_len but returns a body
+ //which is smaller than that by annotation_len bytes
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used,
+ mock_routerinfo->cache_info.signed_descriptor_len+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+
+ //TODO: Is this a BUG?
+ //This is what should be expected: tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_int_op(body_used, OP_EQ,
+ mock_routerinfo->cache_info.signed_descriptor_len);
+
+ tt_str_op(body, OP_EQ, mock_routerinfo->cache_info.signed_descriptor_body +
+ mock_routerinfo->cache_info.annotations_len);
+ tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+
+ done:
+ NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+
+ routerlist_free_all();
+ nodelist_free_all();
+ entry_guards_free_all();
+}
+
+static char
+TEST_DESCRIPTOR[] =
+"@uploaded-at 2014-06-08 19:20:11\n"
+"@source \"127.0.0.1\"\n"
+"router test000a 127.0.0.1 5000 0 7000\n"
+"platform Tor 0.2.5.3-alpha-dev on Linux\n"
+"protocols Link 1 2 Circuit 1\n"
+"published 2014-06-08 19:20:11\n"
+"fingerprint C7E7 CCB8 179F 8CC3 7F5C 8A04 2B3A 180B 934B 14BA\n"
+"uptime 0\n"
+"bandwidth 1073741824 1073741824 0\n"
+"extra-info-digest 67A152A4C7686FB07664F872620635F194D76D95\n"
+"caches-extra-info\n"
+"onion-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAOuBUIEBARMkkka/TGyaQNgUEDLP0KG7sy6KNQTNOlZHUresPr/vlVjo\n"
+"HPpLMfu9M2z18c51YX/muWwY9x4MyQooD56wI4+AqXQcJRwQfQlPn3Ay82uZViA9\n"
+"DpBajRieLlKKkl145KjArpD7F5BVsqccvjErgFYXvhhjSrx7BVLnAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBAN6NLnSxWQnFXxqZi5D3b0BMgV6y9NJLGjYQVP+eWtPZWgqyv4zeYsqv\n"
+"O9y6c5lvxyUxmNHfoAbe/s8f2Vf3/YaC17asAVSln4ktrr3e9iY74a9RMWHv1Gzk\n"
+"3042nMcqj3PEhRN0PoLkcOZNjjmNbaqki6qy9bWWZDNTdo+uI44dAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"hidden-service-dir\n"
+"contact auth0@test.test\n"
+"ntor-onion-key pK4bs08ERYN591jj7ca17Rn9Q02TIEfhnjR6hSq+fhU=\n"
+"reject *:*\n"
+"router-signature\n"
+"-----BEGIN SIGNATURE-----\n"
+"rx88DuM3Y7tODlHNDDEVzKpwh3csaG1or+T4l2Xs1oq3iHHyPEtB6QTLYrC60trG\n"
+"aAPsj3DEowGfjga1b248g2dtic8Ab+0exfjMm1RHXfDam5TXXZU3A0wMyoHjqHuf\n"
+"eChGPgFNUvEc+5YtD27qEDcUjcinYztTs7/dzxBT4PE=\n"
+"-----END SIGNATURE-----\n";
+
+static void
+test_dir_handle_get_server_descriptors_authority(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ crypto_pk_t *identity_pkey = pk_generate(0);
+ (void) data;
+
+ NS_MOCK(router_get_my_routerinfo);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* init mock */
+ router_get_my_routerinfo();
+ crypto_pk_get_digest(identity_pkey,
+ mock_routerinfo->cache_info.identity_digest);
+
+ // the digest is mine (the channel is unnecrypted, so we must allow sending)
+ set_server_identity_key(identity_pkey);
+ mock_routerinfo->cache_info.send_unencrypted = 1;
+
+ /* Setup descriptor */
+ long annotation_len = strstr(TEST_DESCRIPTOR, "router ") - TEST_DESCRIPTOR;
+ mock_routerinfo->cache_info.signed_descriptor_body =
+ tor_strdup(TEST_DESCRIPTOR);
+ mock_routerinfo->cache_info.signed_descriptor_len = strlen(TEST_DESCRIPTOR);
+ mock_routerinfo->cache_info.annotations_len = annotation_len;
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = SERVER_DESC_GET("authority");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ //TODO: Is this a BUG?
+ //It requires strlen(TEST_DESCRIPTOR)+1 as body_len but returns a body which
+ //is smaller than that by annotation_len bytes
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(TEST_DESCRIPTOR)+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+
+ //TODO: Is this a BUG?
+ //This is what should be expected:
+ //tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_int_op(body_used, OP_EQ, strlen(TEST_DESCRIPTOR));
+
+ tt_str_op(body, OP_EQ, TEST_DESCRIPTOR + annotation_len);
+ tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+
+ done:
+ NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(mock_routerinfo);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+ crypto_pk_free(identity_pkey);
+}
+
+static void
+test_dir_handle_get_server_descriptors_fp(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ crypto_pk_t *identity_pkey = pk_generate(0);
+ (void) data;
+
+ NS_MOCK(router_get_my_routerinfo);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* init mock */
+ router_get_my_routerinfo();
+ crypto_pk_get_digest(identity_pkey,
+ mock_routerinfo->cache_info.identity_digest);
+
+ // the digest is mine (the channel is unnecrypted, so we must allow sending)
+ set_server_identity_key(identity_pkey);
+ mock_routerinfo->cache_info.send_unencrypted = 1;
+
+ /* Setup descriptor */
+ long annotation_len = strstr(TEST_DESCRIPTOR, "router ") - TEST_DESCRIPTOR;
+ mock_routerinfo->cache_info.signed_descriptor_body =
+ tor_strdup(TEST_DESCRIPTOR);
+ mock_routerinfo->cache_info.signed_descriptor_len = strlen(TEST_DESCRIPTOR);
+ mock_routerinfo->cache_info.annotations_len = annotation_len;
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ #define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
+ #define HEX2 "Deadbeef99999991111119999911111111f00ba4"
+ const char *hex_digest = hex_str(mock_routerinfo->cache_info.identity_digest,
+ DIGEST_LEN);
+
+ char req[155];
+ sprintf(req, SERVER_DESC_GET("fp/%s+" HEX1 "+" HEX2), hex_digest);
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ //TODO: Is this a BUG?
+ //It requires strlen(TEST_DESCRIPTOR)+1 as body_len but returns a body which
+ //is smaller than that by annotation_len bytes
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(TEST_DESCRIPTOR)+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+
+ //TODO: Is this a BUG?
+ //This is what should be expected:
+ //tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_int_op(body_used, OP_EQ, strlen(TEST_DESCRIPTOR));
+
+ tt_str_op(body, OP_EQ, TEST_DESCRIPTOR + annotation_len);
+ tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+
+ done:
+ NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(mock_routerinfo);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+ crypto_pk_free(identity_pkey);
+}
+
+#define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
+#define HEX2 "Deadbeef99999991111119999911111111f00ba4"
+
+static void
+test_dir_handle_get_server_descriptors_d(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ crypto_pk_t *identity_pkey = pk_generate(0);
+ (void) data;
+
+ /* Setup fake routerlist. */
+ helper_setup_fake_routerlist();
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* Get one router's signed_descriptor_digest */
+ routerlist_t *our_routerlist = router_get_routerlist();
+ tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
+ routerinfo_t *router = smartlist_get(our_routerlist->routers, 0);
+ const char *hex_digest = hex_str(router->cache_info.signed_descriptor_digest,
+ DIGEST_LEN);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ char req_header[155];
+ sprintf(req_header, SERVER_DESC_GET("d/%s+" HEX1 "+" HEX2), hex_digest);
+ tt_int_op(directory_handle_command_get(conn, req_header, NULL, 0), OP_EQ, 0);
+
+ //TODO: Is this a BUG?
+ //It requires strlen(signed_descriptor_len)+1 as body_len but returns a body
+ //which is smaller than that by annotation_len bytes
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used,
+ router->cache_info.signed_descriptor_len+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+
+ //TODO: Is this a BUG?
+ //This is what should be expected:
+ //tt_int_op(body_used, OP_EQ, strlen(body));
+ tt_int_op(body_used, OP_EQ, router->cache_info.signed_descriptor_len);
+
+ tt_str_op(body, OP_EQ, router->cache_info.signed_descriptor_body +
+ router->cache_info.annotations_len);
+ tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(mock_routerinfo);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+ crypto_pk_free(identity_pkey);
+
+ routerlist_free_all();
+ nodelist_free_all();
+ entry_guards_free_all();
+}
+
+static void
+test_dir_handle_get_server_descriptors_busy(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ crypto_pk_t *identity_pkey = pk_generate(0);
+ (void) data;
+
+ /* Setup fake routerlist. */
+ helper_setup_fake_routerlist();
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ //Make it busy
+ MOCK(get_options, mock_get_options);
+ init_mock_options();
+ mock_options->CountPrivateBandwidth = 1;
+
+ /* Get one router's signed_descriptor_digest */
+ routerlist_t *our_routerlist = router_get_routerlist();
+ tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
+ routerinfo_t *router = smartlist_get(our_routerlist->routers, 0);
+ const char *hex_digest = hex_str(router->cache_info.signed_descriptor_digest,
+ DIGEST_LEN);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ #define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
+ #define HEX2 "Deadbeef99999991111119999911111111f00ba4"
+ char req_header[155];
+ sprintf(req_header, SERVER_DESC_GET("d/%s+" HEX1 "+" HEX2), hex_digest);
+ tt_int_op(directory_handle_command_get(conn, req_header, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(SERVER_BUSY, OP_EQ, header);
+
+ tt_int_op(conn->dir_spool_src, OP_EQ, DIR_SPOOL_NONE);
+
+ done:
+ UNMOCK(get_options);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(mock_routerinfo);
+ tor_free(conn);
+ tor_free(header);
+ crypto_pk_free(identity_pkey);
+
+ routerlist_free_all();
+ nodelist_free_all();
+ entry_guards_free_all();
+}
+
+static void
+test_dir_handle_get_server_keys_bad_req(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = GET("/tor/keys/");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(BAD_REQUEST, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_server_keys_all_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = GET("/tor/keys/all");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+#define TEST_CERTIFICATE AUTHORITY_CERT_3
+#define TEST_SIGNING_KEY AUTHORITY_SIGNKEY_A_DIGEST
+extern const char AUTHORITY_CERT_3[];
+extern const char AUTHORITY_SIGNKEY_A_DIGEST[];
+
+static const char TEST_CERT_IDENT_KEY[] =
+ "D867ACF56A9D229B35C25F0090BC9867E906BE69";
+
+static void
+test_dir_handle_get_server_keys_all(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+
+ dir_server_t *ds = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ clear_dir_servers();
+ routerlist_free_all();
+
+ /* create a trusted ds */
+ ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, "", NULL,
+ V3_DIRINFO, 1.0);
+ tt_assert(ds);
+ dir_server_add(ds);
+
+ /* ds v3_identity_digest is the certificate's identity_key */
+ base16_decode(ds->v3_identity_digest, DIGEST_LEN,
+ TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
+ tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = GET("/tor/keys/all");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 1883\r\n"));
+
+ tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+
+ clear_dir_servers();
+ routerlist_free_all();
+}
+
+static void
+test_dir_handle_get_server_keys_authority_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = GET("/tor/keys/authority");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static authority_cert_t * mock_cert = NULL;
+
+static authority_cert_t *
+get_my_v3_authority_cert_m(void)
+{
+ tor_assert(mock_cert);
+ return mock_cert;
+}
+
+static void
+test_dir_handle_get_server_keys_authority(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE, NULL);
+
+ MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = GET("/tor/keys/authority");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 1883\r\n"));
+
+ tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
+
+ done:
+ UNMOCK(get_my_v3_authority_cert);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+ tor_free(mock_cert);
+}
+
+static void
+test_dir_handle_get_server_keys_fp_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = GET("/tor/keys/fp/somehex");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_server_keys_fp(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ dir_server_t *ds = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ clear_dir_servers();
+ routerlist_free_all();
+
+ /* create a trusted ds */
+ ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, "", NULL,
+ V3_DIRINFO, 1.0);
+ tt_assert(ds);
+ dir_server_add(ds);
+
+ /* ds v3_identity_digest is the certificate's identity_key */
+ base16_decode(ds->v3_identity_digest, DIGEST_LEN,
+ TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
+
+ tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ char req[71];
+ sprintf(req, GET("/tor/keys/fp/%s"), TEST_CERT_IDENT_KEY);
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 1883\r\n"));
+
+ tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+ clear_dir_servers();
+ routerlist_free_all();
+}
+
+static void
+test_dir_handle_get_server_keys_sk_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = GET("/tor/keys/sk/somehex");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_server_keys_sk(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE, NULL);
+ MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ clear_dir_servers();
+ routerlist_free_all();
+
+ tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ char req[71];
+ sprintf(req, GET("/tor/keys/sk/%s"), TEST_SIGNING_KEY);
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 1883\r\n"));
+
+ tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
+
+ done:
+ UNMOCK(get_my_v3_authority_cert);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+}
+
+static void
+test_dir_handle_get_server_keys_fpsk_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ const char *req = GET("/tor/keys/fp-sk/somehex");
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_server_keys_fpsk(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ dir_server_t *ds = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ clear_dir_servers();
+ routerlist_free_all();
+
+ /* create a trusted ds */
+ ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, "", NULL,
+ V3_DIRINFO, 1.0);
+ tt_assert(ds);
+
+ /* ds v3_identity_digest is the certificate's identity_key */
+ base16_decode(ds->v3_identity_digest, DIGEST_LEN,
+ TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
+ dir_server_add(ds);
+
+ tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ char req[115];
+ sprintf(req, GET("/tor/keys/fp-sk/%s-%s"),
+ TEST_CERT_IDENT_KEY, TEST_SIGNING_KEY);
+
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
+
+ tt_assert(header);
+ tt_assert(body);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 1883\r\n"));
+
+ tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+
+ clear_dir_servers();
+ routerlist_free_all();
+}
+
+static void
+test_dir_handle_get_server_keys_busy(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ dir_server_t *ds = NULL;
+ (void) data;
+
+ clear_dir_servers();
+ routerlist_free_all();
+
+ /* create a trusted ds */
+ ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, "", NULL,
+ V3_DIRINFO, 1.0);
+ tt_assert(ds);
+
+ /* ds v3_identity_digest is the certificate's identity_key */
+ base16_decode(ds->v3_identity_digest, DIGEST_LEN,
+ TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
+ dir_server_add(ds);
+
+ tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+
+ MOCK(get_options, mock_get_options);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* setup busy server */
+ init_mock_options();
+ mock_options->CountPrivateBandwidth = 1;
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ char req[71];
+ sprintf(req, GET("/tor/keys/fp/%s"), TEST_CERT_IDENT_KEY);
+ tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(SERVER_BUSY, OP_EQ, header);
+
+ done:
+ UNMOCK(get_options);
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(mock_options);
+
+ clear_dir_servers();
+ routerlist_free_all();
+}
+
+static networkstatus_t *mock_ns_val = NULL;
+static networkstatus_t *
+mock_ns_get_by_flavor(consensus_flavor_t f)
+{
+ (void)f;
+ return mock_ns_val;
+}
+
+static void
+test_dir_handle_get_status_vote_current_consensus_ns_not_enough_sigs(void* d)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) d;
+
+ /* init mock */
+ mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
+ mock_ns_val->flavor = FLAV_NS;
+ mock_ns_val->voters = smartlist_new();
+
+ /* init mock */
+ init_mock_options();
+
+ MOCK(get_options, mock_get_options);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+ MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
+
+ /* start gathering stats */
+ mock_options->DirReqStatistics = 1;
+ geoip_dirreq_stats_init(time(NULL));
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/current/consensus-ns/" HEX1 "+" HEX2), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+
+ tt_assert(header);
+ tt_str_op(NOT_ENOUGH_CONSENSUS_SIGNATURES, OP_EQ, header);
+
+ char *stats = geoip_format_dirreq_stats(time(NULL));
+ tt_assert(stats);
+ tt_assert(strstr(stats, "not-enough-sigs=8"));
+
+ done:
+ UNMOCK(networkstatus_get_latest_consensus_by_flavor);
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(get_options);
+
+ tor_free(conn);
+ tor_free(header);
+ smartlist_free(mock_ns_val->voters);
+ tor_free(mock_ns_val);
+ tor_free(mock_options);
+}
+
+static void
+test_dir_handle_get_status_vote_current_consensus_ns_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ init_mock_options();
+
+ MOCK(get_options, mock_get_options);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ /* start gathering stats */
+ mock_options->DirReqStatistics = 1;
+ geoip_dirreq_stats_init(time(NULL));
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/current/consensus-ns"), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ char *stats = geoip_format_dirreq_stats(time(NULL));
+ tt_assert(stats);
+ tt_assert(strstr(stats, "not-found=8"));
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(get_options);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(mock_options);
+}
+
+NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr));
+
+int
+NS(geoip_get_country_by_addr)(const tor_addr_t *addr)
+{
+ (void)addr;
+ CALLED(geoip_get_country_by_addr)++;
+ return 1;
+}
+
+static void
+status_vote_current_consensus_ns_test(char **header, char **body,
+ size_t *body_len)
+{
+ digests_t digests;
+ dir_connection_t *conn = NULL;
+
+ #define NETWORK_STATUS "some network status string"
+ dirserv_set_cached_consensus_networkstatus(NETWORK_STATUS, "ns", &digests,
+ time(NULL));
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ tt_assert(mock_options);
+ mock_options->DirReqStatistics = 1;
+ geoip_dirreq_stats_init(time(NULL));
+
+ /* init geoip database */
+ geoip_parse_entry("10,50,AB", AF_INET);
+ tt_str_op("ab", OP_EQ, geoip_get_country_name(1));
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ TO_CONN(conn)->address = tor_strdup("127.0.0.1");
+
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/current/consensus-ns"), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
+ body, body_len, strlen(NETWORK_STATUS)+7, 0);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+}
+
+static void
+test_dir_handle_get_status_vote_current_consensus_ns(void* data)
+{
+ char *header = NULL;
+ char *body = NULL, *comp_body = NULL;
+ size_t body_used = 0, comp_body_used = 0;
+ char *stats = NULL, *hist = NULL;
+ (void) data;
+
+ dirserv_free_all();
+ clear_geoip_db();
+
+ NS_MOCK(geoip_get_country_by_addr);
+ MOCK(get_options, mock_get_options);
+
+ init_mock_options();
+
+ status_vote_current_consensus_ns_test(&header, &comp_body, &comp_body_used);
+ tt_assert(header);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Pragma: no-cache\r\n"));
+
+ compress_method_t compression = detect_compression_method(comp_body,
+ comp_body_used);
+ tt_int_op(ZLIB_METHOD, OP_EQ, compression);
+
+ tor_gzip_uncompress(&body, &body_used, comp_body, comp_body_used,
+ compression, 0, LOG_PROTOCOL_WARN);
+
+ tt_str_op(NETWORK_STATUS, OP_EQ, body);
+ tt_int_op(strlen(NETWORK_STATUS), OP_EQ, body_used);
+
+ stats = geoip_format_dirreq_stats(time(NULL));
+ tt_assert(stats);
+
+ tt_assert(strstr(stats, "ok=8"));
+ tt_assert(strstr(stats, "dirreq-v3-ips ab=8"));
+ tt_assert(strstr(stats, "dirreq-v3-reqs ab=8"));
+ tt_assert(strstr(stats, "dirreq-v3-direct-dl"
+ " complete=0,timeout=0,running=4"));
+
+ hist = geoip_get_request_history();
+ tt_assert(hist);
+ tt_str_op("ab=8", OP_EQ, hist);
+
+ done:
+ NS_UNMOCK(geoip_get_country_by_addr);
+ UNMOCK(get_options);
+ tor_free(header);
+ tor_free(comp_body);
+ tor_free(body);
+ tor_free(stats);
+ tor_free(hist);
+ tor_free(mock_options);
+
+ dirserv_free_all();
+ clear_geoip_db();
+}
+
+static void
+test_dir_handle_get_status_vote_current_consensus_ns_busy(void* data)
+{
+ char *header = NULL;
+ char *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ dirserv_free_all();
+ clear_geoip_db();
+
+ MOCK(get_options, mock_get_options);
+
+ // Make it busy
+ init_mock_options();
+ mock_options->CountPrivateBandwidth = 1;
+
+ status_vote_current_consensus_ns_test(&header, &body, &body_used);
+ tt_assert(header);
+
+ tt_str_op(SERVER_BUSY, OP_EQ, header);
+
+ char *stats = geoip_format_dirreq_stats(time(NULL));
+ tt_assert(stats);
+ tt_assert(strstr(stats, "busy=8"));
+
+ done:
+ UNMOCK(get_options);
+ tor_free(header);
+ tor_free(body);
+ tor_free(mock_options);
+
+ dirserv_free_all();
+ clear_geoip_db();
+}
+
+static void
+test_dir_handle_get_status_vote_current_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/current/" HEX1), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+#define VOTE_DIGEST "312A4890D4D832597ABBD3089C782DBBFB81E48D"
+
+static void
+status_vote_current_d_test(char **header, char **body, size_t *body_l)
+{
+ dir_connection_t *conn = NULL;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/current/d/" VOTE_DIGEST), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
+ body, body_l, strlen(VOTE_BODY_V3)+1, 0);
+ tt_assert(header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+}
+
+static void
+status_vote_next_d_test(char **header, char **body, size_t *body_l)
+{
+ dir_connection_t *conn = NULL;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/next/d/" VOTE_DIGEST), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
+ body, body_l, strlen(VOTE_BODY_V3)+1, 0);
+ tt_assert(header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+}
+
+static void
+test_dir_handle_get_status_vote_current_d_not_found(void* data)
+{
+ char *header = NULL;
+ (void) data;
+
+ status_vote_current_d_test(&header, NULL, NULL);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_status_vote_next_d_not_found(void* data)
+{
+ char *header = NULL;
+ (void) data;
+
+ status_vote_next_d_test(&header, NULL, NULL);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_status_vote_d(void* data)
+{
+ char *header = NULL, *body = NULL;
+ size_t body_used = 0;
+ dir_server_t *ds = NULL;
+ (void) data;
+
+ clear_dir_servers();
+ dirvote_free_all();
+
+ /* create a trusted ds */
+ ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, "", NULL,
+ V3_DIRINFO, 1.0);
+ tt_assert(ds);
+ dir_server_add(ds);
+
+ /* ds v3_identity_digest is the certificate's identity_key */
+ base16_decode(ds->v3_identity_digest, DIGEST_LEN,
+ TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
+
+ init_mock_options();
+ mock_options->AuthoritativeDir = 1;
+ mock_options->V3AuthoritativeDir = 1;
+ mock_options->TestingV3AuthVotingStartOffset = 0;
+ mock_options->TestingV3AuthInitialVotingInterval = 1;
+ mock_options->TestingV3AuthInitialVoteDelay = 1;
+ mock_options->TestingV3AuthInitialDistDelay = 1;
+
+ time_t now = 1441223455 -1;
+ dirvote_recalculate_timing(mock_options, now);
+
+ const char *msg_out = NULL;
+ int status_out = 0;
+ struct pending_vote_t *pv = dirvote_add_vote(VOTE_BODY_V3, &msg_out,
+ &status_out);
+ tt_assert(pv);
+
+ status_vote_current_d_test(&header, &body, &body_used);
+
+ tt_assert(header);
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+
+ tt_str_op(VOTE_BODY_V3, OP_EQ, body);
+
+ tor_free(header);
+ tor_free(body);
+
+ status_vote_next_d_test(&header, &body, &body_used);
+
+ tt_assert(header);
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+
+ tt_str_op(VOTE_BODY_V3, OP_EQ, body);
+
+ done:
+ tor_free(header);
+ tor_free(body);
+ tor_free(mock_options);
+
+ clear_dir_servers();
+ dirvote_free_all();
+}
+
+static void
+test_dir_handle_get_status_vote_next_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/next/" HEX1), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+status_vote_next_consensus_test(char **header, char **body, size_t *body_used)
+{
+ dir_connection_t *conn = NULL;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/next/consensus"), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
+ body, body_used, 18, 0);
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+}
+
+static void
+test_dir_handle_get_status_vote_next_consensus_not_found(void* data)
+{
+ char *header = NULL, *body = NULL;
+ size_t body_used;
+ (void) data;
+
+ status_vote_next_consensus_test(&header, &body, &body_used);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ tor_free(header);
+ tor_free(body);
+}
+
+static void
+test_dir_handle_get_status_vote_current_authority_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/current/authority"), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+static void
+test_dir_handle_get_status_vote_next_authority_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL;
+ (void) data;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/next/authority"), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ NULL, NULL, 1, 0);
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ tor_free(conn);
+ tor_free(header);
+}
+
+NS_DECL(const char*,
+dirvote_get_pending_consensus, (consensus_flavor_t flav));
+
+const char*
+NS(dirvote_get_pending_consensus)(consensus_flavor_t flav)
+{
+ (void)flav;
+ return "pending consensus";
+}
+
+static void
+test_dir_handle_get_status_vote_next_consensus(void* data)
+{
+ char *header = NULL, *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ NS_MOCK(dirvote_get_pending_consensus);
+
+ status_vote_next_consensus_test(&header, &body, &body_used);
+ tt_assert(header);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 17\r\n"));
+
+ tt_str_op("pending consensus", OP_EQ, body);
+
+ done:
+ NS_UNMOCK(dirvote_get_pending_consensus);
+ tor_free(header);
+ tor_free(body);
+}
+
+static void
+test_dir_handle_get_status_vote_next_consensus_busy(void* data)
+{
+ char *header = NULL, *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ MOCK(get_options, mock_get_options);
+ NS_MOCK(dirvote_get_pending_consensus);
+
+ //Make it busy
+ init_mock_options();
+ mock_options->CountPrivateBandwidth = 1;
+
+ status_vote_next_consensus_test(&header, &body, &body_used);
+
+ tt_assert(header);
+ tt_str_op(SERVER_BUSY, OP_EQ, header);
+
+ done:
+ NS_UNMOCK(dirvote_get_pending_consensus);
+ UNMOCK(get_options);
+ tor_free(header);
+ tor_free(body);
+ tor_free(mock_options);
+}
+
+static void
+status_vote_next_consensus_signatures_test(char **header, char **body,
+ size_t *body_used)
+{
+ dir_connection_t *conn = NULL;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/next/consensus-signatures"), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
+ body, body_used, 22, 0);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+}
+
+static void
+test_dir_handle_get_status_vote_next_consensus_signatures_not_found(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL, *body = NULL;
+ size_t body_used;
+ (void) data;
+
+ status_vote_next_consensus_signatures_test(&header, &body, &body_used);
+
+ tt_assert(header);
+ tt_str_op(NOT_FOUND, OP_EQ, header);
+
+ done:
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+}
+
+NS_DECL(const char*,
+dirvote_get_pending_detached_signatures, (void));
+
+const char*
+NS(dirvote_get_pending_detached_signatures)(void)
+{
+ return "pending detached sigs";
+}
+
+static void
+test_dir_handle_get_status_vote_next_consensus_signatures(void* data)
+{
+ char *header = NULL, *body = NULL;
+ size_t body_used = 0;
+ (void) data;
+
+ NS_MOCK(dirvote_get_pending_detached_signatures);
+
+ status_vote_next_consensus_signatures_test(&header, &body, &body_used);
+ tt_assert(header);
+
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 21\r\n"));
+
+ tt_str_op("pending detached sigs", OP_EQ, body);
+
+ done:
+ NS_UNMOCK(dirvote_get_pending_detached_signatures);
+ tor_free(header);
+ tor_free(body);
+}
+
+static void
+test_dir_handle_get_status_vote_next_consensus_signatures_busy(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL, *body = NULL;
+ size_t body_used;
+ (void) data;
+
+ NS_MOCK(dirvote_get_pending_detached_signatures);
+ MOCK(get_options, mock_get_options);
+
+ //Make it busy
+ init_mock_options();
+ mock_options->CountPrivateBandwidth = 1;
+
+ status_vote_next_consensus_signatures_test(&header, &body, &body_used);
+
+ tt_assert(header);
+ tt_str_op(SERVER_BUSY, OP_EQ, header);
+
+ done:
+ UNMOCK(get_options);
+ NS_UNMOCK(dirvote_get_pending_detached_signatures);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(body);
+ tor_free(mock_options);
+}
+
+static void
+test_dir_handle_get_status_vote_next_authority(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL, *body = NULL;
+ const char *msg_out = NULL;
+ int status_out = 0;
+ size_t body_used = 0;
+ dir_server_t *ds = NULL;
+ (void) data;
+
+ clear_dir_servers();
+ routerlist_free_all();
+ dirvote_free_all();
+
+ mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE, NULL);
+
+ /* create a trusted ds */
+ ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, "", NULL,
+ V3_DIRINFO, 1.0);
+ tt_assert(ds);
+ dir_server_add(ds);
+
+ /* ds v3_identity_digest is the certificate's identity_key */
+ base16_decode(ds->v3_identity_digest, DIGEST_LEN,
+ TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
+ tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+
+ init_mock_options();
+ mock_options->AuthoritativeDir = 1;
+ mock_options->V3AuthoritativeDir = 1;
+ mock_options->TestingV3AuthVotingStartOffset = 0;
+ mock_options->TestingV3AuthInitialVotingInterval = 1;
+ mock_options->TestingV3AuthInitialVoteDelay = 1;
+ mock_options->TestingV3AuthInitialDistDelay = 1;
+
+ time_t now = 1441223455 -1;
+ dirvote_recalculate_timing(mock_options, now);
+
+ struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, &msg_out,
+ &status_out);
+ tt_assert(vote);
+
+ MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/next/authority"), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(VOTE_BODY_V3)+1, 0);
+
+ tt_assert(header);
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+
+ tt_str_op(VOTE_BODY_V3, OP_EQ, body);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(get_my_v3_authority_cert);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(mock_cert);
+
+ clear_dir_servers();
+ routerlist_free_all();
+ dirvote_free_all();
+}
+
+static void
+test_dir_handle_get_status_vote_current_authority(void* data)
+{
+ dir_connection_t *conn = NULL;
+ char *header = NULL, *body = NULL;
+ const char *msg_out = NULL;
+ int status_out = 0;
+ size_t body_used = 0;
+
+ dir_server_t *ds = NULL;
+ (void) data;
+
+ clear_dir_servers();
+ routerlist_free_all();
+ dirvote_free_all();
+
+ mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE, NULL);
+
+ /* create a trusted ds */
+ ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, "", NULL,
+ V3_DIRINFO, 1.0);
+ tt_assert(ds);
+ dir_server_add(ds);
+
+ /* ds v3_identity_digest is the certificate's identity_key */
+ base16_decode(ds->v3_identity_digest, DIGEST_LEN,
+ TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
+
+ tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+
+ init_mock_options();
+ mock_options->AuthoritativeDir = 1;
+ mock_options->V3AuthoritativeDir = 1;
+ mock_options->TestingV3AuthVotingStartOffset = 0;
+ mock_options->TestingV3AuthInitialVotingInterval = 1;
+ mock_options->TestingV3AuthInitialVoteDelay = 1;
+ mock_options->TestingV3AuthInitialDistDelay = 1;
+
+ time_t now = 1441223455;
+ dirvote_recalculate_timing(mock_options, now-1);
+
+ struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, &msg_out,
+ &status_out);
+ tt_assert(vote);
+
+ // move the pending vote to previous vote
+ dirvote_act(mock_options, now+1);
+
+ MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
+ tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
+ GET("/tor/status-vote/current/authority"), NULL, 0));
+
+ fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
+ &body, &body_used, strlen(VOTE_BODY_V3)+1, 0);
+
+ tt_assert(header);
+ tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
+ tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
+ tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
+ tt_assert(strstr(header, "Content-Length: 4135\r\n"));
+
+ tt_str_op(VOTE_BODY_V3, OP_EQ, body);
+
+ done:
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(get_my_v3_authority_cert);
+ tor_free(conn);
+ tor_free(header);
+ tor_free(mock_cert);
+
+ clear_dir_servers();
+ routerlist_free_all();
+ dirvote_free_all();
+}
+
+#define DIR_HANDLE_CMD(name,flags) \
+ { #name, test_dir_handle_get_##name, (flags), NULL, NULL }
+
+struct testcase_t dir_handle_get_tests[] = {
+ DIR_HANDLE_CMD(not_found, 0),
+ DIR_HANDLE_CMD(bad_request, 0),
+ DIR_HANDLE_CMD(v1_command_not_found, 0),
+ DIR_HANDLE_CMD(v1_command, 0),
+ DIR_HANDLE_CMD(robots_txt, 0),
+ DIR_HANDLE_CMD(bytes_txt, 0),
+ DIR_HANDLE_CMD(rendezvous2_not_found_if_not_encrypted, 0),
+ DIR_HANDLE_CMD(rendezvous2_not_found, 0),
+ DIR_HANDLE_CMD(rendezvous2_on_encrypted_conn_with_invalid_desc_id, 0),
+ DIR_HANDLE_CMD(rendezvous2_on_encrypted_conn_not_well_formed, 0),
+ DIR_HANDLE_CMD(rendezvous2_on_encrypted_conn_success, 0),
+ DIR_HANDLE_CMD(micro_d_not_found, 0),
+ DIR_HANDLE_CMD(micro_d_server_busy, 0),
+ DIR_HANDLE_CMD(micro_d, 0),
+ DIR_HANDLE_CMD(networkstatus_bridges_not_found_without_auth, 0),
+ DIR_HANDLE_CMD(networkstatus_bridges_not_found_wrong_auth, 0),
+ DIR_HANDLE_CMD(networkstatus_bridges, 0),
+ DIR_HANDLE_CMD(server_descriptors_not_found, 0),
+ DIR_HANDLE_CMD(server_descriptors_busy, TT_FORK),
+ DIR_HANDLE_CMD(server_descriptors_all, TT_FORK),
+ DIR_HANDLE_CMD(server_descriptors_authority, TT_FORK),
+ DIR_HANDLE_CMD(server_descriptors_fp, TT_FORK),
+ DIR_HANDLE_CMD(server_descriptors_d, TT_FORK),
+ DIR_HANDLE_CMD(server_keys_bad_req, 0),
+ DIR_HANDLE_CMD(server_keys_busy, 0),
+ DIR_HANDLE_CMD(server_keys_all_not_found, 0),
+ DIR_HANDLE_CMD(server_keys_all, 0),
+ DIR_HANDLE_CMD(server_keys_authority_not_found, 0),
+ DIR_HANDLE_CMD(server_keys_authority, 0),
+ DIR_HANDLE_CMD(server_keys_fp_not_found, 0),
+ DIR_HANDLE_CMD(server_keys_fp, 0),
+ DIR_HANDLE_CMD(server_keys_sk_not_found, 0),
+ DIR_HANDLE_CMD(server_keys_sk, 0),
+ DIR_HANDLE_CMD(server_keys_fpsk_not_found, 0),
+ DIR_HANDLE_CMD(server_keys_fpsk, 0),
+ DIR_HANDLE_CMD(status_vote_current_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_next_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_current_authority_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_current_authority, 0),
+ DIR_HANDLE_CMD(status_vote_next_authority_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_next_authority, 0),
+ DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_enough_sigs, 0),
+ DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_current_consensus_ns_busy, 0),
+ DIR_HANDLE_CMD(status_vote_current_consensus_ns, 0),
+ DIR_HANDLE_CMD(status_vote_current_d_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_next_d_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_d, 0),
+ DIR_HANDLE_CMD(status_vote_next_consensus_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_next_consensus_busy, 0),
+ DIR_HANDLE_CMD(status_vote_next_consensus, 0),
+ DIR_HANDLE_CMD(status_vote_next_consensus_signatures_not_found, 0),
+ DIR_HANDLE_CMD(status_vote_next_consensus_signatures_busy, 0),
+ DIR_HANDLE_CMD(status_vote_next_consensus_signatures, 0),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_keypin.c b/src/test/test_keypin.c
index afd4ca201d..bd0f6fdd52 100644
--- a/src/test/test_keypin.c
+++ b/src/test/test_keypin.c
@@ -108,21 +108,21 @@ test_keypin_parse_file(void *arg)
;
tt_int_op(0, ==, keypin_load_journal_impl(data2, strlen(data2)));
- tt_int_op(11, ==, smartlist_len(mock_addent_got));
+ tt_int_op(13, ==, smartlist_len(mock_addent_got));
ent = smartlist_get(mock_addent_got, 9);
tt_mem_op(ent->rsa_id, ==, "\"You have made a goo", 20);
tt_mem_op(ent->ed25519_key, ==, "d beginning.\" But no more. Wizar", 32);
- ent = smartlist_get(mock_addent_got, 10);
+ ent = smartlist_get(mock_addent_got, 12);
tt_mem_op(ent->rsa_id, ==, "ds speak truth, and ", 20);
- tt_mem_op(ent->ed25519_key, ==, "it was true that all the master\n", 32);
+ tt_mem_op(ent->ed25519_key, ==, "it was tru\xa5 that all the master\n", 32);
/* File truncated before NL */
const char data3[] =
"Tm8gZHJhZ29uIGNhbiByZXNpc3Q IHRoZSBmYXNjaW5hdGlvbiBvZiByaWRkbGluZyB0YWw";
tt_int_op(0, ==, keypin_load_journal_impl(data3, strlen(data3)));
- tt_int_op(12, ==, smartlist_len(mock_addent_got));
- ent = smartlist_get(mock_addent_got, 11);
+ tt_int_op(14, ==, smartlist_len(mock_addent_got));
+ ent = smartlist_get(mock_addent_got, 13);
tt_mem_op(ent->rsa_id, ==, "No dragon can resist", 20);
tt_mem_op(ent->ed25519_key, ==, " the fascination of riddling tal", 32);
@@ -131,7 +131,8 @@ test_keypin_parse_file(void *arg)
smartlist_free(mock_addent_got);
}
-#define ADD(a,b) keypin_check_and_add((const uint8_t*)(a),(const uint8_t*)(b))
+#define ADD(a,b) keypin_check_and_add((const uint8_t*)(a),\
+ (const uint8_t*)(b),0)
#define LONE_RSA(a) keypin_check_lone_rsa((const uint8_t*)(a))
static void
diff --git a/src/test/test_ntor.sh b/src/test/test_ntor.sh
new file mode 100755
index 0000000000..5081dabc54
--- /dev/null
+++ b/src/test/test_ntor.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# Validate Tor's ntor implementation.
+
+exitcode=0
+
+"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/ntor_ref.py" test-tor || exitcode=1
+"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/ntor_ref.py" self-test || exitcode=1
+
+exit ${exitcode}
diff --git a/src/test/test_ntor.sh.in b/src/test/test_ntor.sh.in
deleted file mode 100644
index be35384ddf..0000000000
--- a/src/test/test_ntor.sh.in
+++ /dev/null
@@ -1,9 +0,0 @@
-#!@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_policy.c b/src/test/test_policy.c
index 33f90c7da5..37c36fed99 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -49,7 +49,7 @@ test_policy_summary_helper(const char *policy_str,
r = policies_parse_exit_policy(&line, &policy,
EXIT_POLICY_IPV6_ENABLED |
- EXIT_POLICY_ADD_DEFAULT ,0);
+ EXIT_POLICY_ADD_DEFAULT, 0, NULL, 0);
tt_int_op(r,OP_EQ, 0);
summary = policy_summarize(policy, AF_INET);
@@ -77,18 +77,21 @@ test_policies_general(void *arg)
int i;
smartlist_t *policy = NULL, *policy2 = NULL, *policy3 = NULL,
*policy4 = NULL, *policy5 = NULL, *policy6 = NULL,
- *policy7 = NULL;
+ *policy7 = NULL, *policy8 = NULL, *policy9 = NULL,
+ *policy10 = NULL, *policy11 = NULL, *policy12 = NULL;
addr_policy_t *p;
tor_addr_t tar;
config_line_t line;
smartlist_t *sm = NULL;
char *policy_str = NULL;
short_policy_t *short_parsed = NULL;
+ int malformed_list = -1;
(void)arg;
policy = smartlist_new();
- p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
tt_int_op(ADDR_POLICY_REJECT,OP_EQ, p->policy_type);
tor_addr_from_ipv4h(&tar, 0xc0a80000u);
@@ -112,68 +115,122 @@ test_policies_general(void *arg)
tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy2,
EXIT_POLICY_IPV6_ENABLED |
EXIT_POLICY_REJECT_PRIVATE |
- EXIT_POLICY_ADD_DEFAULT, 0));
+ EXIT_POLICY_ADD_DEFAULT, 0,
+ NULL, 0));
tt_assert(policy2);
+ tor_addr_parse(&tar, "[2000::1234]");
+ tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy12,
+ EXIT_POLICY_IPV6_ENABLED |
+ EXIT_POLICY_REJECT_PRIVATE |
+ EXIT_POLICY_ADD_DEFAULT,
+ 0x0306090cu, &tar, 1));
+
+ tt_assert(policy12);
+
policy3 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("reject *:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject *:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy3, p);
- p = router_parse_addr_policy_item_from_string("accept *:*",-1);
+ p = router_parse_addr_policy_item_from_string("accept *:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy3, p);
policy4 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("accept *:443",-1);
+ p = router_parse_addr_policy_item_from_string("accept *:443", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy4, p);
- p = router_parse_addr_policy_item_from_string("accept *:443",-1);
+ p = router_parse_addr_policy_item_from_string("accept *:443", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy4, p);
policy5 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",
+ -1, &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject *:1-65534",-1);
+ p = router_parse_addr_policy_item_from_string("reject *:1-65534", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject *:65535",-1);
+ p = router_parse_addr_policy_item_from_string("reject *:65535", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("accept *:1-65535",-1);
+ p = router_parse_addr_policy_item_from_string("accept *:1-65535", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
policy6 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*",-1);
+ p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy6, p);
policy7 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*",-1);
+ p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy7, p);
+ tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy8,
+ EXIT_POLICY_IPV6_ENABLED |
+ EXIT_POLICY_REJECT_PRIVATE |
+ EXIT_POLICY_ADD_DEFAULT, 0,
+ NULL, 0));
+
+ tt_assert(policy8);
+
+ tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy9,
+ EXIT_POLICY_REJECT_PRIVATE |
+ EXIT_POLICY_ADD_DEFAULT, 0,
+ NULL, 0));
+
+ tt_assert(policy9);
+
+ /* accept6 * and reject6 * produce IPv6 wildcards only */
+ policy10 = smartlist_new();
+ p = router_parse_addr_policy_item_from_string("accept6 *:*", -1,
+ &malformed_list);
+ tt_assert(p != NULL);
+ smartlist_add(policy10, p);
+
+ policy11 = smartlist_new();
+ p = router_parse_addr_policy_item_from_string("reject6 *:*", -1,
+ &malformed_list);
+ tt_assert(p != NULL);
+ smartlist_add(policy11, p);
+
tt_assert(!exit_policy_is_general_exit(policy));
tt_assert(exit_policy_is_general_exit(policy2));
tt_assert(!exit_policy_is_general_exit(NULL));
@@ -182,6 +239,10 @@ test_policies_general(void *arg)
tt_assert(!exit_policy_is_general_exit(policy5));
tt_assert(!exit_policy_is_general_exit(policy6));
tt_assert(!exit_policy_is_general_exit(policy7));
+ tt_assert(exit_policy_is_general_exit(policy8));
+ tt_assert(exit_policy_is_general_exit(policy9));
+ tt_assert(!exit_policy_is_general_exit(policy10));
+ tt_assert(!exit_policy_is_general_exit(policy11));
tt_assert(cmp_addr_policies(policy, policy2));
tt_assert(cmp_addr_policies(policy, NULL));
@@ -190,7 +251,12 @@ test_policies_general(void *arg)
tt_assert(!policy_is_reject_star(policy2, AF_INET));
tt_assert(policy_is_reject_star(policy, AF_INET));
+ tt_assert(policy_is_reject_star(policy10, AF_INET));
+ tt_assert(!policy_is_reject_star(policy10, AF_INET6));
+ tt_assert(policy_is_reject_star(policy11, AF_INET));
+ tt_assert(policy_is_reject_star(policy11, AF_INET6));
tt_assert(policy_is_reject_star(NULL, AF_INET));
+ tt_assert(policy_is_reject_star(NULL, AF_INET6));
addr_policy_list_free(policy);
policy = NULL;
@@ -202,7 +268,8 @@ test_policies_general(void *arg)
line.next = NULL;
tt_int_op(0, OP_EQ, policies_parse_exit_policy(&line,&policy,
EXIT_POLICY_IPV6_ENABLED |
- EXIT_POLICY_ADD_DEFAULT,0));
+ EXIT_POLICY_ADD_DEFAULT, 0,
+ NULL, 0));
tt_assert(policy);
//test_streq(policy->string, "accept *:80");
@@ -297,6 +364,68 @@ test_policies_general(void *arg)
TT_BAD_SHORT_POLICY("accept 1-,3");
TT_BAD_SHORT_POLICY("accept 1-,3");
+ /* Make sure that IPv4 addresses are ignored in accept6/reject6 lines. */
+ p = router_parse_addr_policy_item_from_string("accept6 1.2.3.4:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(!malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject6 2.4.6.0/24:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(!malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept6 *4:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(!malformed_list);
+
+ /* Make sure malformed policies are detected as such. */
+ p = router_parse_addr_policy_item_from_string("bad_token *4:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept6 **:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept */15:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject6 */:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept 127.0.0.1/33:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept6 [::1]/129:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject 8.8.8.8/-1:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject 8.8.4.4:10-5", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject 1.2.3.4:-1", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
/* Test a too-long policy. */
{
int i;
@@ -347,6 +476,11 @@ test_policies_general(void *arg)
addr_policy_list_free(policy5);
addr_policy_list_free(policy6);
addr_policy_list_free(policy7);
+ addr_policy_list_free(policy8);
+ addr_policy_list_free(policy9);
+ addr_policy_list_free(policy10);
+ addr_policy_list_free(policy11);
+ addr_policy_list_free(policy12);
tor_free(policy_str);
if (sm) {
SMARTLIST_FOREACH(sm, char *, s, tor_free(s));
@@ -360,6 +494,7 @@ test_dump_exit_policy_to_string(void *arg)
{
char *ep;
addr_policy_t *policy_entry;
+ int malformed_list = -1;
routerinfo_t *ri = tor_malloc_zero(sizeof(routerinfo_t));
@@ -376,7 +511,8 @@ test_dump_exit_policy_to_string(void *arg)
ri->exit_policy = smartlist_new();
ri->policy_is_reject_star = 0;
- policy_entry = router_parse_addr_policy_item_from_string("accept *:*",-1);
+ policy_entry = router_parse_addr_policy_item_from_string("accept *:*", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
@@ -386,7 +522,8 @@ test_dump_exit_policy_to_string(void *arg)
tor_free(ep);
- policy_entry = router_parse_addr_policy_item_from_string("reject *:25",-1);
+ policy_entry = router_parse_addr_policy_item_from_string("reject *:25", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
@@ -397,7 +534,8 @@ test_dump_exit_policy_to_string(void *arg)
tor_free(ep);
policy_entry =
- router_parse_addr_policy_item_from_string("reject 8.8.8.8:*",-1);
+ router_parse_addr_policy_item_from_string("reject 8.8.8.8:*", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
@@ -407,7 +545,8 @@ test_dump_exit_policy_to_string(void *arg)
tor_free(ep);
policy_entry =
- router_parse_addr_policy_item_from_string("reject6 [FC00::]/7:*",-1);
+ router_parse_addr_policy_item_from_string("reject6 [FC00::]/7:*", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
@@ -418,7 +557,8 @@ test_dump_exit_policy_to_string(void *arg)
tor_free(ep);
policy_entry =
- router_parse_addr_policy_item_from_string("accept6 [c000::]/3:*",-1);
+ router_parse_addr_policy_item_from_string("accept6 [c000::]/3:*", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index 9bd0c125c3..74b39c0486 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -423,14 +423,14 @@ NS(test_main)(void *arg)
}
#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, policy)
+#define NS_SUBMODULE ASPECT(routerset_parse, policy_wildcard)
/*
- * Structural test for routerset_parse, when given a valid policy.
+ * Structural test for routerset_parse, when given a valid wildcard policy.
*/
NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action));
+ (const char *s, int assume_action, int *malformed_list));
addr_policy_t *NS(mock_addr_policy);
@@ -457,16 +457,113 @@ NS(test_main)(void *arg)
}
addr_policy_t *
-NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action)
+NS(router_parse_addr_policy_item_from_string)(const char *s,
+ int assume_action,
+ int *malformed_list)
{
(void)s;
(void)assume_action;
+ (void)malformed_list;
CALLED(router_parse_addr_policy_item_from_string)++;
return NS(mock_addr_policy);
}
#undef NS_SUBMODULE
+#define NS_SUBMODULE ASPECT(routerset_parse, policy_ipv4)
+
+/*
+ * Structural test for routerset_parse, when given a valid IPv4 address
+ * literal policy.
+ */
+
+NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
+ (const char *s, int assume_action, int *bogus));
+
+addr_policy_t *NS(mock_addr_policy);
+
+static void
+NS(test_main)(void *arg)
+{
+ routerset_t *set;
+ const char *s;
+ int r;
+ (void)arg;
+
+ NS_MOCK(router_parse_addr_policy_item_from_string);
+ NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+
+ set = routerset_new();
+ s = "127.0.0.1";
+ r = routerset_parse(set, s, "");
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(set->policies), OP_NE, 0);
+ tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+
+ done:
+ routerset_free(set);
+}
+
+addr_policy_t *
+NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action,
+ int *bogus)
+{
+ (void)s;
+ (void)assume_action;
+ CALLED(router_parse_addr_policy_item_from_string)++;
+ *bogus = 0;
+
+ return NS(mock_addr_policy);
+}
+
+#undef NS_SUBMODULE
+#define NS_SUBMODULE ASPECT(routerset_parse, policy_ipv6)
+
+/*
+ * Structural test for routerset_parse, when given a valid IPv6 address
+ * literal policy.
+ */
+
+NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
+ (const char *s, int assume_action, int *bad));
+
+addr_policy_t *NS(mock_addr_policy);
+
+static void
+NS(test_main)(void *arg)
+{
+ routerset_t *set;
+ const char *s;
+ int r;
+ (void)arg;
+
+ NS_MOCK(router_parse_addr_policy_item_from_string);
+ NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+
+ set = routerset_new();
+ s = "::1";
+ r = routerset_parse(set, s, "");
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(set->policies), OP_NE, 0);
+ tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+
+ done:
+ routerset_free(set);
+}
+
+addr_policy_t *
+NS(router_parse_addr_policy_item_from_string)(const char *s,
+ int assume_action, int *bad)
+{
+ (void)s;
+ (void)assume_action;
+ CALLED(router_parse_addr_policy_item_from_string)++;
+ *bad = 0;
+
+ return NS(mock_addr_policy);
+}
+
+#undef NS_SUBMODULE
#define NS_SUBMODULE ASPECT(routerset_union, source_bad)
/*
@@ -2106,7 +2203,9 @@ struct testcase_t routerset_tests[] = {
TEST_CASE_ASPECT(routerset_parse, valid_hexdigest),
TEST_CASE_ASPECT(routerset_parse, valid_nickname),
TEST_CASE_ASPECT(routerset_parse, get_countryname),
- TEST_CASE_ASPECT(routerset_parse, policy),
+ TEST_CASE_ASPECT(routerset_parse, policy_wildcard),
+ TEST_CASE_ASPECT(routerset_parse, policy_ipv4),
+ TEST_CASE_ASPECT(routerset_parse, policy_ipv6),
TEST_CASE(routerset_subtract_nodes),
TEST_CASE_ASPECT(routerset_subtract_nodes, null_routerset),
TEST_CASE(routerset_to_string),
diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c
new file mode 100644
index 0000000000..2e53293373
--- /dev/null
+++ b/src/test/test_tortls.c
@@ -0,0 +1,2950 @@
+/* Copyright (c) 2010-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define TORTLS_PRIVATE
+#define LOG_PRIVATE
+#include "orconfig.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
+
+#ifdef __GNUC__
+#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#endif
+
+#if __GNUC__ && GCC_VERSION >= 402
+#if GCC_VERSION >= 406
+#pragma GCC diagnostic push
+#endif
+/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
+ * srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
+#include <openssl/opensslv.h>
+
+#include <openssl/ssl.h>
+#include <openssl/ssl3.h>
+#include <openssl/err.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+
+#if __GNUC__ && GCC_VERSION >= 402
+#if GCC_VERSION >= 406
+#pragma GCC diagnostic pop
+#else
+#pragma GCC diagnostic warning "-Wredundant-decls"
+#endif
+#endif
+
+#include "or.h"
+#include "torlog.h"
+#include "config.h"
+#include "tortls.h"
+
+#include "test.h"
+#include "log_test_helpers.h"
+#define NS_MODULE tortls
+
+extern tor_tls_context_t *server_tls_context;
+extern tor_tls_context_t *client_tls_context;
+
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+#define OPENSSL_OPAQUE
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static SSL_METHOD *
+give_me_a_test_method(void)
+{
+ SSL_METHOD *method = tor_malloc_zero(sizeof(SSL_METHOD));
+ memcpy(method, TLSv1_method(), sizeof(SSL_METHOD));
+ return method;
+}
+
+static int
+fake_num_ciphers(void)
+{
+ return 0;
+}
+#endif
+
+static void
+test_tortls_errno_to_tls_error(void *data)
+{
+ (void) data;
+ tt_int_op(tor_errno_to_tls_error(SOCK_ERRNO(ECONNRESET)),OP_EQ,
+ TOR_TLS_ERROR_CONNRESET);
+ tt_int_op(tor_errno_to_tls_error(SOCK_ERRNO(ETIMEDOUT)),OP_EQ,
+ TOR_TLS_ERROR_TIMEOUT);
+ tt_int_op(tor_errno_to_tls_error(SOCK_ERRNO(EHOSTUNREACH)),OP_EQ,
+ TOR_TLS_ERROR_NO_ROUTE);
+ tt_int_op(tor_errno_to_tls_error(SOCK_ERRNO(ENETUNREACH)),OP_EQ,
+ TOR_TLS_ERROR_NO_ROUTE);
+ tt_int_op(tor_errno_to_tls_error(SOCK_ERRNO(ECONNREFUSED)),OP_EQ,
+ TOR_TLS_ERROR_CONNREFUSED);
+ tt_int_op(tor_errno_to_tls_error(0),OP_EQ,TOR_TLS_ERROR_MISC);
+ done:
+ (void)1;
+}
+
+static void
+test_tortls_err_to_string(void *data)
+{
+ (void) data;
+ tt_str_op(tor_tls_err_to_string(1),OP_EQ,"[Not an error.]");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_ERROR_MISC),OP_EQ,"misc error");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_ERROR_IO),OP_EQ,"unexpected close");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_ERROR_CONNREFUSED),OP_EQ,
+ "connection refused");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_ERROR_CONNRESET),OP_EQ,
+ "connection reset");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_ERROR_NO_ROUTE),OP_EQ,
+ "host unreachable");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_ERROR_TIMEOUT),OP_EQ,
+ "connection timed out");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_CLOSE),OP_EQ,"closed");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_WANTREAD),OP_EQ,"want to read");
+ tt_str_op(tor_tls_err_to_string(TOR_TLS_WANTWRITE),OP_EQ,"want to write");
+ tt_str_op(tor_tls_err_to_string(-100),OP_EQ,"(unknown error code)");
+ done:
+ (void)1;
+}
+
+static int
+mock_tls_cert_matches_key(const tor_tls_t *tls, const tor_x509_cert_t *cert)
+{
+ (void) tls;
+ (void) cert; // XXXX look at this.
+ return 1;
+}
+
+static void
+test_tortls_tor_tls_new(void *data)
+{
+ (void) data;
+ MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key);
+ crypto_pk_t *key1 = NULL, *key2 = NULL;
+ key1 = pk_generate(2);
+ key2 = pk_generate(3);
+
+ tor_tls_t *tls;
+ tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER,
+ key1, key2, 86400), OP_EQ, 0);
+ tls = tor_tls_new(-1, 0);
+ tt_want(tls);
+
+ client_tls_context->ctx = NULL;
+ tls = tor_tls_new(-1, 0);
+ tt_assert(!tls);
+
+#ifndef OPENSSL_OPAQUE
+ SSL_METHOD *method = give_me_a_test_method();
+ SSL_CTX *ctx = SSL_CTX_new(method);
+ method->num_ciphers = fake_num_ciphers;
+ client_tls_context->ctx = ctx;
+ tls = tor_tls_new(-1, 0);
+ tt_assert(!tls);
+#endif
+
+ done:
+ UNMOCK(tor_tls_cert_matches_key);
+ crypto_pk_free(key1);
+ crypto_pk_free(key2);
+}
+
+#define NS_MODULE tortls
+NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap));
+
+static void
+NS(logv)(int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix, const char *format,
+ va_list ap)
+{
+ (void) severity;
+ (void) domain;
+ (void) funcname;
+ (void) suffix;
+ (void) format;
+ (void) ap; // XXXX look at this.
+ CALLED(logv)++;
+}
+
+static void
+test_tortls_tor_tls_get_error(void *data)
+{
+ (void) data;
+ MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key);
+ crypto_pk_t *key1 = NULL, *key2 = NULL;
+ key1 = pk_generate(2);
+ key2 = pk_generate(3);
+
+ tor_tls_t *tls;
+ tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER,
+ key1, key2, 86400), OP_EQ, 0);
+ tls = tor_tls_new(-1, 0);
+ NS_MOCK(logv);
+ tt_int_op(CALLED(logv), OP_EQ, 0);
+ tor_tls_get_error(tls, 0, 0,
+ (const char *)"test", 0, 0);
+ tt_int_op(CALLED(logv), OP_EQ, 1);
+
+ done:
+ UNMOCK(tor_tls_cert_matches_key);
+ NS_UNMOCK(logv);
+ crypto_pk_free(key1);
+ crypto_pk_free(key2);
+}
+
+static void
+test_tortls_get_state_description(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ char *buf;
+ SSL_CTX *ctx;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(SSLv23_method());
+
+ buf = tor_malloc_zero(1000);
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+
+ tor_tls_get_state_description(NULL, buf, 20);
+ tt_str_op(buf, OP_EQ, "(No SSL object)");
+
+ tls->ssl = NULL;
+ tor_tls_get_state_description(tls, buf, 20);
+ tt_str_op(buf, OP_EQ, "(No SSL object)");
+
+ tls->ssl = SSL_new(ctx);
+ tor_tls_get_state_description(tls, buf, 200);
+ tt_str_op(buf, OP_EQ, "before/accept initialization in HANDSHAKE");
+
+ tls->state = TOR_TLS_ST_OPEN;
+ tor_tls_get_state_description(tls, buf, 200);
+ tt_str_op(buf, OP_EQ, "before/accept initialization in OPEN");
+
+ tls->state = TOR_TLS_ST_GOTCLOSE;
+ tor_tls_get_state_description(tls, buf, 200);
+ tt_str_op(buf, OP_EQ, "before/accept initialization in GOTCLOSE");
+
+ tls->state = TOR_TLS_ST_SENTCLOSE;
+ tor_tls_get_state_description(tls, buf, 200);
+ tt_str_op(buf, OP_EQ, "before/accept initialization in SENTCLOSE");
+
+ tls->state = TOR_TLS_ST_CLOSED;
+ tor_tls_get_state_description(tls, buf, 200);
+ tt_str_op(buf, OP_EQ, "before/accept initialization in CLOSED");
+
+ tls->state = TOR_TLS_ST_RENEGOTIATE;
+ tor_tls_get_state_description(tls, buf, 200);
+ tt_str_op(buf, OP_EQ, "before/accept initialization in RENEGOTIATE");
+
+ tls->state = TOR_TLS_ST_BUFFEREVENT;
+ tor_tls_get_state_description(tls, buf, 200);
+ tt_str_op(buf, OP_EQ, "before/accept initialization");
+
+ tls->state = 7;
+ tor_tls_get_state_description(tls, buf, 200);
+ tt_str_op(buf, OP_EQ, "before/accept initialization in unknown TLS state");
+
+ done:
+ SSL_CTX_free(ctx);
+ tor_free(buf);
+ tor_free(tls);
+}
+
+extern int tor_tls_object_ex_data_index;
+
+static void
+test_tortls_get_by_ssl(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ tor_tls_t *res;
+ SSL_CTX *ctx;
+ SSL *ssl;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+
+ ctx = SSL_CTX_new(SSLv23_method());
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->magic = TOR_TLS_MAGIC;
+
+ ssl = SSL_new(ctx);
+
+ res = tor_tls_get_by_ssl(ssl);
+ tt_assert(!res);
+
+ SSL_set_ex_data(ssl, tor_tls_object_ex_data_index, tls);
+
+ res = tor_tls_get_by_ssl(ssl);
+ tt_assert(res == tls);
+
+ done:
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ tor_free(tls);
+}
+
+static void
+test_tortls_allocate_tor_tls_object_ex_data_index(void *ignored)
+{
+ (void)ignored;
+ int first;
+
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+
+ first = tor_tls_object_ex_data_index;
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+ tt_int_op(first, OP_EQ, tor_tls_object_ex_data_index);
+
+ done:
+ (void)0;
+}
+
+static void
+test_tortls_log_one_error(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ SSL_CTX *ctx;
+ SSL *ssl = NULL;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(SSLv23_method());
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ int previous_log = setup_capture_of_logs(LOG_INFO);
+
+ tor_tls_log_one_error(NULL, 0, LOG_WARN, 0, "something");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error while something: "
+ "(null) (in (null):(null):---)\n");
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error: (null) "
+ "(in (null):(null):---)\n");
+
+ mock_clean_saved_logs();
+ tls->address = tor_strdup("127.hello");
+ tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error with 127.hello: (null) "
+ "(in (null):(null):---)\n");
+
+ mock_clean_saved_logs();
+ tls->address = tor_strdup("127.hello");
+ tor_tls_log_one_error(tls, 0, LOG_WARN, 0, "blarg");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error while blarg with "
+ "127.hello: (null) (in (null):(null):---)\n");
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, ERR_PACK(1, 2, 3), LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error with 127.hello: "
+ "BN lib (in unknown library:(null):---)\n");
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_HTTP_REQUEST),
+ LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_HTTPS_PROXY_REQUEST),
+ LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_RECORD_LENGTH_MISMATCH),
+ LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_RECORD_TOO_LARGE),
+ LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_UNKNOWN_PROTOCOL),
+ LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_UNSUPPORTED_PROTOCOL),
+ LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ tls->ssl = SSL_new(ctx);
+
+ mock_clean_saved_logs();
+ tor_tls_log_one_error(tls, 0, LOG_WARN, 0, NULL);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error with 127.hello: (null)"
+ " (in (null):(null):before/accept initialization)\n");
+
+ done:
+ teardown_capture_of_logs(previous_log);
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ tor_free(tls);
+}
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_get_error(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ int ret;
+ SSL_CTX *ctx;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(SSLv23_method());
+ int previous_log = setup_capture_of_logs(LOG_INFO);
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = SSL_new(ctx);
+ SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL);
+
+ ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_IO);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error: unexpected close while"
+ " something (before/accept initialization)\n");
+
+ mock_clean_saved_logs();
+ ret = tor_tls_get_error(tls, 2, 0, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 0);
+
+ mock_clean_saved_logs();
+ ret = tor_tls_get_error(tls, 0, 1, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, -11);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 0);
+
+ mock_clean_saved_logs();
+ ERR_clear_error();
+ ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99);
+ ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error while something: (null)"
+ " (in bignum routines:(null):before/accept initialization)\n");
+
+ mock_clean_saved_logs();
+ ERR_clear_error();
+ tls->ssl->rwstate = SSL_READING;
+ SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_READ;
+ ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, TOR_TLS_WANTREAD);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 0);
+
+ mock_clean_saved_logs();
+ ERR_clear_error();
+ tls->ssl->rwstate = SSL_READING;
+ SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_WRITE;
+ ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, TOR_TLS_WANTWRITE);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 0);
+
+ mock_clean_saved_logs();
+ ERR_clear_error();
+ tls->ssl->rwstate = 0;
+ tls->ssl->shutdown = SSL_RECEIVED_SHUTDOWN;
+ tls->ssl->s3->warn_alert =SSL_AD_CLOSE_NOTIFY;
+ ret = tor_tls_get_error(tls, 0, 0, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, TOR_TLS_CLOSE);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+
+ mock_clean_saved_logs();
+ ret = tor_tls_get_error(tls, 0, 2, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, -10);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 0);
+
+ mock_clean_saved_logs();
+ ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99);
+ ret = tor_tls_get_error(tls, -1, 0, "something", LOG_WARN, 0);
+ tt_int_op(ret, OP_EQ, -9);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 2);
+ tt_str_op(mock_saved_log_at(1), OP_EQ,
+ "TLS error while something: (null) (in system library:"
+ "connect:before/accept initialization)\n");
+
+ done:
+ teardown_capture_of_logs(previous_log);
+ tor_free(tls);
+}
+#endif
+
+static void
+test_tortls_always_accept_verify_cb(void *ignored)
+{
+ (void)ignored;
+ int ret;
+
+ ret = always_accept_verify_cb(0, NULL);
+ tt_int_op(ret, OP_EQ, 1);
+
+ done:
+ (void)0;
+}
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_x509_cert_free(void *ignored)
+{
+ (void)ignored;
+ tor_x509_cert_t *cert;
+
+ cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ tor_x509_cert_free(cert);
+
+ cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ cert->cert = tor_malloc_zero(sizeof(X509));
+ cert->encoded = tor_malloc_zero(1);
+ tor_x509_cert_free(cert);
+}
+#endif
+
+static void
+test_tortls_x509_cert_get_id_digests(void *ignored)
+{
+ (void)ignored;
+ tor_x509_cert_t *cert;
+ digests_t *d;
+ const digests_t *res;
+ cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ d = tor_malloc_zero(sizeof(digests_t));
+ d->d[0][0] = 42;
+
+ res = tor_x509_cert_get_id_digests(cert);
+ tt_assert(!res);
+
+ cert->pkey_digests_set = 1;
+ cert->pkey_digests = *d;
+ res = tor_x509_cert_get_id_digests(cert);
+ tt_int_op(res->d[0][0], OP_EQ, 42);
+
+ done:
+ (void)0;
+}
+
+#ifndef OPENSSL_OPAQUE
+static int
+fixed_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+ (void) a; (void) b;
+ return 1;
+}
+
+static void
+test_tortls_cert_matches_key(void *ignored)
+{
+ (void)ignored;
+ int res;
+ tor_tls_t *tls;
+ tor_x509_cert_t *cert;
+ X509 *one, *two;
+ EVP_PKEY_ASN1_METHOD *meth = EVP_PKEY_asn1_new(999, 0, NULL, NULL);
+ EVP_PKEY_asn1_set_public(meth, NULL, NULL, fixed_pub_cmp, NULL, NULL, NULL);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ one = tor_malloc_zero(sizeof(X509));
+ one->references = 1;
+ two = tor_malloc_zero(sizeof(X509));
+ two->references = 1;
+
+ res = tor_tls_cert_matches_key(tls, cert);
+ tt_int_op(res, OP_EQ, 0);
+
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION));
+ tls->ssl->session->peer = one;
+ res = tor_tls_cert_matches_key(tls, cert);
+ tt_int_op(res, OP_EQ, 0);
+
+ cert->cert = two;
+ res = tor_tls_cert_matches_key(tls, cert);
+ tt_int_op(res, OP_EQ, 0);
+
+ one->cert_info = tor_malloc_zero(sizeof(X509_CINF));
+ one->cert_info->key = tor_malloc_zero(sizeof(X509_PUBKEY));
+ one->cert_info->key->pkey = tor_malloc_zero(sizeof(EVP_PKEY));
+ one->cert_info->key->pkey->references = 1;
+ one->cert_info->key->pkey->ameth = meth;
+ one->cert_info->key->pkey->type = 1;
+
+ two->cert_info = tor_malloc_zero(sizeof(X509_CINF));
+ two->cert_info->key = tor_malloc_zero(sizeof(X509_PUBKEY));
+ two->cert_info->key->pkey = tor_malloc_zero(sizeof(EVP_PKEY));
+ two->cert_info->key->pkey->references = 1;
+ two->cert_info->key->pkey->ameth = meth;
+ two->cert_info->key->pkey->type = 2;
+
+ res = tor_tls_cert_matches_key(tls, cert);
+ tt_int_op(res, OP_EQ, 0);
+
+ one->cert_info->key->pkey->type = 1;
+ two->cert_info->key->pkey->type = 1;
+ res = tor_tls_cert_matches_key(tls, cert);
+ tt_int_op(res, OP_EQ, 1);
+
+ done:
+ EVP_PKEY_asn1_free(meth);
+ tor_free(tls);
+ tor_free(cert);
+}
+
+static void
+test_tortls_cert_get_key(void *ignored)
+{
+ (void)ignored;
+ tor_x509_cert_t *cert;
+ crypto_pk_t *res;
+ cert = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ X509 *key;
+ key = tor_malloc_zero(sizeof(X509));
+ key->references = 1;
+
+ res = tor_tls_cert_get_key(cert);
+ tt_assert(!res);
+
+ cert->cert = key;
+ key->cert_info = tor_malloc_zero(sizeof(X509_CINF));
+ key->cert_info->key = tor_malloc_zero(sizeof(X509_PUBKEY));
+ key->cert_info->key->pkey = tor_malloc_zero(sizeof(EVP_PKEY));
+ key->cert_info->key->pkey->references = 1;
+ key->cert_info->key->pkey->type = 2;
+ res = tor_tls_cert_get_key(cert);
+ tt_assert(!res);
+
+ done:
+ (void)0;
+}
+#endif
+
+static void
+test_tortls_get_my_client_auth_key(void *ignored)
+{
+ (void)ignored;
+ crypto_pk_t *ret;
+ crypto_pk_t *expected;
+ tor_tls_context_t *ctx;
+ RSA *k = tor_malloc_zero(sizeof(RSA));
+
+ ctx = tor_malloc_zero(sizeof(tor_tls_context_t));
+ expected = crypto_new_pk_from_rsa_(k);
+ ctx->auth_key = expected;
+
+ client_tls_context = NULL;
+ ret = tor_tls_get_my_client_auth_key();
+ tt_assert(!ret);
+
+ client_tls_context = ctx;
+ ret = tor_tls_get_my_client_auth_key();
+ tt_assert(ret == expected);
+
+ done:
+ tor_free(expected);
+ tor_free(k);
+ tor_free(ctx);
+}
+
+static void
+test_tortls_get_my_certs(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_context_t *ctx;
+ const tor_x509_cert_t *link_cert_out = NULL;
+ const tor_x509_cert_t *id_cert_out = NULL;
+
+ ctx = tor_malloc_zero(sizeof(tor_tls_context_t));
+
+ client_tls_context = NULL;
+ ret = tor_tls_get_my_certs(0, NULL, NULL);
+ tt_int_op(ret, OP_EQ, -1);
+
+ server_tls_context = NULL;
+ ret = tor_tls_get_my_certs(1, NULL, NULL);
+ tt_int_op(ret, OP_EQ, -1);
+
+ client_tls_context = ctx;
+ ret = tor_tls_get_my_certs(0, NULL, NULL);
+ tt_int_op(ret, OP_EQ, 0);
+
+ client_tls_context = ctx;
+ ret = tor_tls_get_my_certs(0, &link_cert_out, &id_cert_out);
+ tt_int_op(ret, OP_EQ, 0);
+
+ server_tls_context = ctx;
+ ret = tor_tls_get_my_certs(1, &link_cert_out, &id_cert_out);
+ tt_int_op(ret, OP_EQ, 0);
+
+ done:
+ (void)1;
+}
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_get_ciphersuite_name(void *ignored)
+{
+ (void)ignored;
+ const char *ret;
+ tor_tls_t *ctx;
+ ctx = tor_malloc_zero(sizeof(tor_tls_t));
+ ctx->ssl = tor_malloc_zero(sizeof(SSL));
+
+ ret = tor_tls_get_ciphersuite_name(ctx);
+ tt_str_op(ret, OP_EQ, "(NONE)");
+
+ done:
+ (void)1;
+}
+
+static SSL_CIPHER *
+get_cipher_by_name(const char *name)
+{
+ int i;
+ const SSL_METHOD *method = SSLv23_method();
+ int num = method->num_ciphers();
+ for (i = 0; i < num; ++i) {
+ const SSL_CIPHER *cipher = method->get_cipher(i);
+ const char *ciphername = SSL_CIPHER_get_name(cipher);
+ if (!strcmp(ciphername, name)) {
+ return (SSL_CIPHER *)cipher;
+ }
+ }
+
+ return NULL;
+}
+
+static SSL_CIPHER *
+get_cipher_by_id(uint16_t id)
+{
+ int i;
+ const SSL_METHOD *method = SSLv23_method();
+ int num = method->num_ciphers();
+ for (i = 0; i < num; ++i) {
+ const SSL_CIPHER *cipher = method->get_cipher(i);
+ if (id == (SSL_CIPHER_get_id(cipher) & 0xffff)) {
+ return (SSL_CIPHER *)cipher;
+ }
+ }
+
+ return NULL;
+}
+
+extern uint16_t v2_cipher_list[];
+
+static void
+test_tortls_classify_client_ciphers(void *ignored)
+{
+ (void)ignored;
+ int i;
+ int ret;
+ SSL_CTX *ctx;
+ SSL *ssl;
+ tor_tls_t *tls;
+ STACK_OF(SSL_CIPHER) *ciphers;
+ SSL_CIPHER *tmp_cipher;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->magic = TOR_TLS_MAGIC;
+
+ ctx = SSL_CTX_new(TLSv1_method());
+ ssl = SSL_new(ctx);
+ tls->ssl = ssl;
+
+ ciphers = sk_SSL_CIPHER_new_null();
+
+ ret = tor_tls_classify_client_ciphers(ssl, NULL);
+ tt_int_op(ret, OP_EQ, -1);
+
+ SSL_set_ex_data(ssl, tor_tls_object_ex_data_index, tls);
+ tls->client_cipher_list_type = 42;
+
+ ret = tor_tls_classify_client_ciphers(ssl, NULL);
+ tt_int_op(ret, OP_EQ, 42);
+
+ tls->client_cipher_list_type = 0;
+ ret = tor_tls_classify_client_ciphers(ssl, ciphers);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_int_op(tls->client_cipher_list_type, OP_EQ, 1);
+
+ tls->client_cipher_list_type = 0;
+ ret = tor_tls_classify_client_ciphers(ssl, SSL_get_ciphers(ssl));
+ tt_int_op(ret, OP_EQ, 3);
+ tt_int_op(tls->client_cipher_list_type, OP_EQ, 3);
+
+ SSL_CIPHER *one = get_cipher_by_name(TLS1_TXT_DHE_RSA_WITH_AES_128_SHA),
+ *two = get_cipher_by_name(TLS1_TXT_DHE_RSA_WITH_AES_256_SHA),
+ *three = get_cipher_by_name(SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA),
+ *four = NULL;
+ sk_SSL_CIPHER_push(ciphers, one);
+ sk_SSL_CIPHER_push(ciphers, two);
+ sk_SSL_CIPHER_push(ciphers, three);
+ sk_SSL_CIPHER_push(ciphers, four);
+
+ tls->client_cipher_list_type = 0;
+ ret = tor_tls_classify_client_ciphers(ssl, ciphers);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_int_op(tls->client_cipher_list_type, OP_EQ, 1);
+
+ sk_SSL_CIPHER_zero(ciphers);
+
+ one = get_cipher_by_name("ECDH-RSA-AES256-GCM-SHA384");
+ one->id = 0x00ff;
+ two = get_cipher_by_name("ECDH-RSA-AES128-GCM-SHA256");
+ two->id = 0x0000;
+ sk_SSL_CIPHER_push(ciphers, one);
+ tls->client_cipher_list_type = 0;
+ ret = tor_tls_classify_client_ciphers(ssl, ciphers);
+ tt_int_op(ret, OP_EQ, 3);
+ tt_int_op(tls->client_cipher_list_type, OP_EQ, 3);
+
+ sk_SSL_CIPHER_push(ciphers, two);
+ tls->client_cipher_list_type = 0;
+ ret = tor_tls_classify_client_ciphers(ssl, ciphers);
+ tt_int_op(ret, OP_EQ, 3);
+ tt_int_op(tls->client_cipher_list_type, OP_EQ, 3);
+
+ one->id = 0xC00A;
+ tls->client_cipher_list_type = 0;
+ ret = tor_tls_classify_client_ciphers(ssl, ciphers);
+ tt_int_op(ret, OP_EQ, 3);
+ tt_int_op(tls->client_cipher_list_type, OP_EQ, 3);
+
+ sk_SSL_CIPHER_zero(ciphers);
+ for (i=0; v2_cipher_list[i]; i++) {
+ tmp_cipher = get_cipher_by_id(v2_cipher_list[i]);
+ tt_assert(tmp_cipher);
+ sk_SSL_CIPHER_push(ciphers, tmp_cipher);
+ }
+ tls->client_cipher_list_type = 0;
+ ret = tor_tls_classify_client_ciphers(ssl, ciphers);
+ tt_int_op(ret, OP_EQ, 2);
+ tt_int_op(tls->client_cipher_list_type, OP_EQ, 2);
+
+ done:
+ (void)1;
+}
+#endif
+
+static void
+test_tortls_client_is_using_v2_ciphers(void *ignored)
+{
+ (void)ignored;
+
+#ifdef HAVE_SSL_GET_CLIENT_CIPHERS
+ tt_skip();
+#else
+
+ int ret;
+ SSL_CTX *ctx;
+ SSL *ssl;
+ SSL_SESSION *sess;
+ STACK_OF(SSL_CIPHER) *ciphers;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(TLSv1_method());
+ ssl = SSL_new(ctx);
+ sess = SSL_SESSION_new();
+
+ ret = tor_tls_client_is_using_v2_ciphers(ssl);
+ tt_int_op(ret, OP_EQ, -1);
+
+ ssl->session = sess;
+ ret = tor_tls_client_is_using_v2_ciphers(ssl);
+ tt_int_op(ret, OP_EQ, 0);
+
+ ciphers = sk_SSL_CIPHER_new_null();
+ SSL_CIPHER *one = get_cipher_by_name("ECDH-RSA-AES256-GCM-SHA384");
+ one->id = 0x00ff;
+ sk_SSL_CIPHER_push(ciphers, one);
+ sess->ciphers = ciphers;
+ ret = tor_tls_client_is_using_v2_ciphers(ssl);
+ tt_int_op(ret, OP_EQ, 1);
+#endif
+
+ done:
+ (void)1;
+}
+
+#ifndef OPENSSL_OPAQUE
+static X509 *fixed_try_to_extract_certs_from_tls_cert_out_result = NULL;
+static X509 *fixed_try_to_extract_certs_from_tls_id_cert_out_result = NULL;
+
+static void
+fixed_try_to_extract_certs_from_tls(int severity, tor_tls_t *tls,
+ X509 **cert_out, X509 **id_cert_out)
+{
+ (void) severity;
+ (void) tls;
+ *cert_out = fixed_try_to_extract_certs_from_tls_cert_out_result;
+ *id_cert_out = fixed_try_to_extract_certs_from_tls_id_cert_out_result;
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static const char* notCompletelyValidCertString =
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIICVjCCAb8CAg37MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG\n"
+ "A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE\n"
+ "MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl\n"
+ "YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw\n"
+ "ODIyMDUyNzIzWhcNMTcwODIxMDUyNzIzWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE\n"
+ "CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs\n"
+ "ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYBBrx5PlP0WNI/ZdzD\n"
+ "+6Pktmurn+F2kQYbtc7XQh8/LTBvCo+P6iZoLEmUA9e7EXLRxgU1CVqeAi7QcAn9\n"
+ "MwBlc8ksFJHB0rtf9pmf8Oza9E0Bynlq/4/Kb1x+d+AyhL7oK9tQwB24uHOueHi1\n"
+ "C/iVv8CSWKiYe6hzN1txYe8rAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAASPdjigJ\n"
+ "kXCqKWpnZ/Oc75EUcMi6HztaW8abUMlYXPIgkV2F7YanHOB7K4f7OOLjiz8DTPFf\n"
+ "jC9UeuErhaA/zzWi8ewMTFZW/WshOrm3fNvcMrMLKtH534JKvcdMg6qIdjTFINIr\n"
+ "evnAhf0cwULaebn+lMs8Pdl7y37+sfluVok=\n"
+ "-----END CERTIFICATE-----\n";
+#endif
+
+static const char* validCertString = "-----BEGIN CERTIFICATE-----\n"
+ "MIIDpTCCAY0CAg3+MA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMREwDwYD\n"
+ "VQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIGA1UECgwLVG9yIFRl\n"
+ "c3RpbmcxFDASBgNVBAMMC1RvciBUZXN0aW5nMB4XDTE1MDkwNjEzMzk1OVoXDTQz\n"
+ "MDEyMjEzMzk1OVowVjELMAkGA1UEBhMCVVMxEDAOBgNVBAcMB0NoaWNhZ28xFDAS\n"
+ "BgNVBAoMC1RvciBUZXN0aW5nMR8wHQYDVQQDDBZ0ZXN0aW5nLnRvcnByb2plY3Qu\n"
+ "b3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoT6uyVVhWyOF3wkHjjYbd\n"
+ "nKaykyRv4JVtKQdZ4OpEErmX1zw4MmyzpQNV6iR4bQnWiyLfzyVJMZDIC/WILBfX\n"
+ "w2Pza/yuLgUvDc3twMuhOACzOQVO8PrEF/aVv2+hbCCy2udXvKhnYn+CCXl3ozc8\n"
+ "XcKYvujTXDyvGWY3xwAjlQIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCUvnhzQWuQ\n"
+ "MrN+pERkE+zcTI/9dGS90rUMMLgu8VDNqTa0TUQh8uO0EQ6uDvI8Js6e8tgwS0BR\n"
+ "UBahqb7ZHv+rejGCBr5OudqD+x4STiiuPNJVs86JTLN8SpM9CHjIBH5WCCN2KOy3\n"
+ "mevNoRcRRyYJzSFULCunIK6FGulszigMYGscrO4oiTkZiHPh9KvWT40IMiHfL+Lw\n"
+ "EtEWiLex6064LcA2YQ1AMuSZyCexks63lcfaFmQbkYOKqXa1oLkIRuDsOaSVjTfe\n"
+ "vec+X6jvf12cFTKS5WIeqkKF2Irt+dJoiHEGTe5RscUMN/f+gqHPzfFz5dR23sxo\n"
+ "g+HC6MZHlFkLAOx3wW6epPS8A/m1mw3zMPoTnb2U2YYt8T0dJMMlUn/7Y1sEAa+a\n"
+ "dSTMaeUf6VnJ//11m454EZl1to9Z7oJOgqmFffSrdD4BGIWe8f7hhW6L1Enmqe/J\n"
+ "BKL3wbzZh80O1W0bndAwhnEEhlzneFY84cbBo9pmVxpODHkUcStpr5Z7pBDrcL21\n"
+ "Ss/aB/1YrsVXhdvJdOGxl3Mnl9dUY57CympLGlT8f0pPS6GAKOelECOhFMHmJd8L\n"
+ "dj3XQSmKtYHevZ6IvuMXSlB/fJvSjSlkCuLo5+kJoaqPuRu+i/S1qxeRy3CBwmnE\n"
+ "LdSNdcX4N79GQJ996PA8+mUCQG7YRtK+WA==\n"
+ "-----END CERTIFICATE-----\n";
+
+static const char* caCertString = "-----BEGIN CERTIFICATE-----\n"
+ "MIIFjzCCA3egAwIBAgIJAKd5WgyfPMYRMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNV\n"
+ "BAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIG\n"
+ "A1UECgwLVG9yIFRlc3RpbmcxFDASBgNVBAMMC1RvciBUZXN0aW5nMB4XDTE1MDkw\n"
+ "NjEzMzc0MVoXDTQzMDEyMjEzMzc0MVowXjELMAkGA1UEBhMCVVMxETAPBgNVBAgM\n"
+ "CElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMRQwEgYDVQQKDAtUb3IgVGVzdGlu\n"
+ "ZzEUMBIGA1UEAwwLVG9yIFRlc3RpbmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n"
+ "ggIKAoICAQCpLMUEiLW5leUgBZoEJms2V7lZRhIAjnJBhVMHD0e3UubNknmaQoxf\n"
+ "ARz3rvqOaRd0JlV+qM9qE0DjiYcCVP1cAfqAo9d83uS1vwY3YMVJzADlaIiHfyVW\n"
+ "uEgBy0vvkeUBqaua24dYlcwsemOiXYLu41yM1wkcGHW1AhBNHppY6cznb8TyLgNM\n"
+ "2x3SGUdzc5XMyAFx51faKGBA3wjs+Hg1PLY7d30nmCgEOBavpm5I1disM/0k+Mcy\n"
+ "YmAKEo/iHJX/rQzO4b9znP69juLlR8PDBUJEVIG/CYb6+uw8MjjUyiWXYoqfVmN2\n"
+ "hm/lH8b6rXw1a2Aa3VTeD0DxaWeacMYHY/i01fd5n7hCoDTRNdSw5KJ0L3Z0SKTu\n"
+ "0lzffKzDaIfyZGlpW5qdouACkWYzsaitQOePVE01PIdO30vUfzNTFDfy42ccx3Di\n"
+ "59UCu+IXB+eMtrBfsok0Qc63vtF1linJgjHW1z/8ujk8F7/qkOfODhk4l7wngc2A\n"
+ "EmwWFIFoGaiTEZHB9qteXr4unbXZ0AHpM02uGGwZEGohjFyebEb73M+J57WKKAFb\n"
+ "PqbLcGUksL1SHNBNAJcVLttX55sO4nbidOS/kA3m+F1R04MBTyQF9qA6YDDHqdI3\n"
+ "h/3pw0Z4fxVouTYT4/NfRnX4JTP4u+7Mpcoof28VME0qWqD1LnRhFQIDAQABo1Aw\n"
+ "TjAdBgNVHQ4EFgQUMoAgIXH7pZ3QMRwTjT+DM9Yo/v0wHwYDVR0jBBgwFoAUMoAg\n"
+ "IXH7pZ3QMRwTjT+DM9Yo/v0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n"
+ "AgEAUJxacjXR9sT+Xs6ISFiUsyd0T6WVKMnV46xrYJHirGfx+krWHrjxMY+ZtxYD\n"
+ "DBDGlo11Qc4v6QrclNf5QUBfIiGQsP9Cm6hHcQ+Tpg9HHCgSqG1YNPwCPReCR4br\n"
+ "BLvLfrfkcBL2IWM0PdQdCze+59DBfipsULD2mEn9fjYRXQEwb2QWtQ9qRc20Yb/x\n"
+ "Q4b/+CvUodLkaq7B8MHz0BV8HHcBoph6DYaRmO/N+hPauIuSp6XyaGYcEefGKVKj\n"
+ "G2+fcsdyXsoijNdL8vNKwm4j2gVwCBnw16J00yfFoV46YcbfqEdJB2je0XSvwXqt\n"
+ "14AOTngxso2h9k9HLtrfpO1ZG/B5AcCMs1lzbZ2fp5DPHtjvvmvA2RJqgo3yjw4W\n"
+ "4DHAuTglYFlC3mDHNfNtcGP20JvepcQNzNP2UzwcpOc94hfKikOFw+gf9Vf1qd0y\n"
+ "h/Sk6OZHn2+JVUPiWHIQV98Vtoh4RmUZDJD+b55ia3fQGTGzt4z1XFzQYSva5sfs\n"
+ "wocS/papthqWldQU7x+3wofNd5CNU1x6WKXG/yw30IT/4F8ADJD6GeygNT8QJYvt\n"
+ "u/8lAkbOy6B9xGmSvr0Kk1oq9P2NshA6kalxp1Oz/DTNDdL4AeBXV3JmM6WWCjGn\n"
+ "Yy1RT69d0rwYc5u/vnqODz1IjvT90smsrkBumGt791FAFeg=\n"
+ "-----END CERTIFICATE-----\n";
+
+static X509 *
+read_cert_from(const char *str)
+{
+ BIO *bio = BIO_new(BIO_s_mem());
+ BIO_write(bio, str, (int) strlen(str));
+ X509 *res = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ return res;
+}
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_verify(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ crypto_pk_t *k = NULL;
+ X509 *cert1 = NULL, *cert2 = NULL, *invalidCert = NULL,
+ *validCert = NULL, *caCert = NULL;
+
+ cert1 = tor_malloc_zero(sizeof(X509));
+ cert1->references = 10;
+
+ cert2 = tor_malloc_zero(sizeof(X509));
+ cert2->references = 10;
+
+ validCert = read_cert_from(validCertString);
+ caCert = read_cert_from(caCertString);
+ invalidCert = read_cert_from(notCompletelyValidCertString);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ ret = tor_tls_verify(LOG_WARN, tls, &k);
+ tt_int_op(ret, OP_EQ, -1);
+
+ MOCK(try_to_extract_certs_from_tls, fixed_try_to_extract_certs_from_tls);
+
+ fixed_try_to_extract_certs_from_tls_cert_out_result = cert1;
+ ret = tor_tls_verify(LOG_WARN, tls, &k);
+ tt_int_op(ret, OP_EQ, -1);
+
+ fixed_try_to_extract_certs_from_tls_id_cert_out_result = cert2;
+ ret = tor_tls_verify(LOG_WARN, tls, &k);
+ tt_int_op(ret, OP_EQ, -1);
+
+ fixed_try_to_extract_certs_from_tls_cert_out_result = invalidCert;
+ fixed_try_to_extract_certs_from_tls_id_cert_out_result = invalidCert;
+
+ ret = tor_tls_verify(LOG_WARN, tls, &k);
+ tt_int_op(ret, OP_EQ, -1);
+
+ fixed_try_to_extract_certs_from_tls_cert_out_result = validCert;
+ fixed_try_to_extract_certs_from_tls_id_cert_out_result = caCert;
+
+ ret = tor_tls_verify(LOG_WARN, tls, &k);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_assert(k);
+
+ done:
+ UNMOCK(try_to_extract_certs_from_tls);
+ tor_free(cert1);
+ tor_free(cert2);
+ tor_free(tls);
+ tor_free(k);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_check_lifetime(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ X509 *validCert = read_cert_from(validCertString);
+ time_t now = time(NULL);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ ret = tor_tls_check_lifetime(LOG_WARN, tls, 0, 0);
+ tt_int_op(ret, OP_EQ, -1);
+
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION));
+ tls->ssl->session->peer = validCert;
+ ret = tor_tls_check_lifetime(LOG_WARN, tls, 0, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ validCert->cert_info->validity->notBefore = ASN1_TIME_set(NULL, now-10);
+ validCert->cert_info->validity->notAfter = ASN1_TIME_set(NULL, now+60);
+
+ ret = tor_tls_check_lifetime(LOG_WARN, tls, 0, -1000);
+ tt_int_op(ret, OP_EQ, -1);
+
+ ret = tor_tls_check_lifetime(LOG_WARN, tls, -1000, 0);
+ tt_int_op(ret, OP_EQ, -1);
+
+ done:
+ tor_free(tls->ssl->session);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static int fixed_ssl_pending_result = 0;
+
+static int
+fixed_ssl_pending(const SSL *ignored)
+{
+ (void)ignored;
+ return fixed_ssl_pending_result;
+}
+
+static void
+test_tortls_get_pending_bytes(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ SSL_METHOD *method;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ method = tor_malloc_zero(sizeof(SSL_METHOD));
+ method->ssl_pending = fixed_ssl_pending;
+ tls->ssl->method = method;
+
+ fixed_ssl_pending_result = 42;
+ ret = tor_tls_get_pending_bytes(tls);
+ tt_int_op(ret, OP_EQ, 42);
+
+ done:
+ tor_free(method);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+static void
+test_tortls_get_forced_write_size(void *ignored)
+{
+ (void)ignored;
+ long ret;
+ tor_tls_t *tls;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+
+ tls->wantwrite_n = 43;
+ ret = tor_tls_get_forced_write_size(tls);
+ tt_int_op(ret, OP_EQ, 43);
+
+ done:
+ tor_free(tls);
+}
+
+extern uint64_t total_bytes_written_over_tls;
+extern uint64_t total_bytes_written_by_tls;
+
+static void
+test_tortls_get_write_overhead_ratio(void *ignored)
+{
+ (void)ignored;
+ double ret;
+
+ total_bytes_written_over_tls = 0;
+ ret = tls_get_write_overhead_ratio();
+ tt_int_op(ret, OP_EQ, 1.0);
+
+ total_bytes_written_by_tls = 10;
+ total_bytes_written_over_tls = 1;
+ ret = tls_get_write_overhead_ratio();
+ tt_int_op(ret, OP_EQ, 10.0);
+
+ total_bytes_written_by_tls = 10;
+ total_bytes_written_over_tls = 2;
+ ret = tls_get_write_overhead_ratio();
+ tt_int_op(ret, OP_EQ, 5.0);
+
+ done:
+ (void)0;
+}
+
+static void
+test_tortls_used_v1_handshake(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+
+ // These tests assume both V2 handshake server and client are enabled
+ tls->wasV2Handshake = 0;
+ ret = tor_tls_used_v1_handshake(tls);
+ tt_int_op(ret, OP_EQ, 1);
+
+ tls->wasV2Handshake = 1;
+ ret = tor_tls_used_v1_handshake(tls);
+ tt_int_op(ret, OP_EQ, 0);
+
+ done:
+ tor_free(tls);
+}
+
+static void
+test_tortls_dn_indicates_v3_cert(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ X509_NAME *name;
+
+ name = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
+ (const unsigned char *)"US", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
+ (const unsigned char *)"Foobar", -1, -1, 0);
+ ret = dn_indicates_v3_cert(name);
+ tt_int_op(ret, OP_EQ, 1);
+
+ X509_NAME_free(name);
+ name = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
+ (const unsigned char *)"US", -1, -1, 0);
+ ret = dn_indicates_v3_cert(name);
+ tt_int_op(ret, OP_EQ, 1);
+
+ X509_NAME_free(name);
+ name = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(name, "commonName", V_ASN1_REAL,
+ (const unsigned char *)"123", -1, -1, 0);
+ ret = dn_indicates_v3_cert(name);
+ tt_int_op(ret, OP_EQ, 0);
+
+ X509_NAME_free(name);
+ name = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"hello.com", -1, -1, 0);
+ ret = dn_indicates_v3_cert(name);
+ tt_int_op(ret, OP_EQ, 1);
+
+ X509_NAME_free(name);
+ name = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"hello.net", -1, -1, 0);
+ ret = dn_indicates_v3_cert(name);
+ tt_int_op(ret, OP_EQ, 0);
+
+ X509_NAME_free(name);
+ name = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"x.s", -1, -1, 0);
+ ret = dn_indicates_v3_cert(name);
+ tt_int_op(ret, OP_EQ, 1);
+
+ done:
+ X509_NAME_free(name);
+}
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_received_v3_certificate(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ X509 *validCert = read_cert_from(validCertString);
+ X509_NAME *subject=NULL, *issuer=NULL;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION));
+
+ ret = tor_tls_received_v3_certificate(tls);
+ tt_int_op(ret, OP_EQ, 0);
+
+ tls->ssl->session->peer = validCert;
+
+ subject = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(subject, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"same.com", -1, -1, 0);
+ X509_set_subject_name(validCert, subject);
+
+ issuer = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(issuer, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"same.com", -1, -1, 0);
+ X509_set_issuer_name(validCert, issuer);
+
+ ret = tor_tls_received_v3_certificate(tls);
+ tt_int_op(ret, OP_EQ, 1);
+
+ X509_NAME_free(subject);
+ subject = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(subject, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"different.net", -1, -1, 0);
+ X509_set_subject_name(validCert, subject);
+
+ ret = tor_tls_received_v3_certificate(tls);
+ tt_int_op(ret, OP_EQ, 1);
+
+ X509_NAME_free(subject);
+ subject = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(subject, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"same.com", -1, -1, 0);
+ X509_set_subject_name(validCert, subject);
+
+ X509_NAME_free(issuer);
+ issuer = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(issuer, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"different.net", -1, -1, 0);
+ X509_set_issuer_name(validCert, issuer);
+
+ ret = tor_tls_received_v3_certificate(tls);
+ tt_int_op(ret, OP_EQ, 1);
+
+ X509_NAME_free(subject);
+ subject = X509_NAME_new();
+ X509_NAME_add_entry_by_txt(subject, "commonName", MBSTRING_ASC,
+ (const unsigned char *)"different2.net", -1, -1, 0);
+ X509_set_subject_name(validCert, subject);
+ ret = tor_tls_received_v3_certificate(tls);
+ tt_int_op(ret, OP_EQ, 0);
+
+ EVP_PKEY *key = X509_get_pubkey(validCert);
+ key->type = 5;
+ ret = tor_tls_received_v3_certificate(tls);
+ tt_int_op(ret, OP_EQ, 1);
+
+ key->type = 6;
+ key->ameth = NULL;
+ ret = tor_tls_received_v3_certificate(tls);
+ tt_int_op(ret, OP_EQ, 1);
+
+ done:
+ X509_NAME_free(subject);
+ X509_NAME_free(issuer);
+ tor_free(tls->ssl->session);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+static void
+test_tortls_get_num_server_handshakes(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+
+ tls->server_handshake_count = 3;
+ ret = tor_tls_get_num_server_handshakes(tls);
+ tt_int_op(ret, OP_EQ, 3);
+
+ done:
+ tor_free(tls);
+}
+
+static void
+test_tortls_server_got_renegotiate(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+
+ tls->got_renegotiate = 1;
+ ret = tor_tls_server_got_renegotiate(tls);
+ tt_int_op(ret, OP_EQ, 1);
+
+ done:
+ tor_free(tls);
+}
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_SSL_SESSION_get_master_key(void *ignored)
+{
+ (void)ignored;
+ size_t ret;
+ tor_tls_t *tls;
+ uint8_t *out;
+ out = tor_malloc_zero(1);
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION));
+ tls->ssl->session->master_key_length = 1;
+
+#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY
+ tls->ssl->session->master_key[0] = 43;
+ ret = SSL_SESSION_get_master_key(tls->ssl->session, out, 0);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_int_op(out[0], OP_EQ, 0);
+
+ ret = SSL_SESSION_get_master_key(tls->ssl->session, out, 1);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_int_op(out[0], OP_EQ, 43);
+
+ done:
+#endif
+ tor_free(tls->ssl->session);
+ tor_free(tls->ssl);
+ tor_free(tls);
+ tor_free(out);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_get_tlssecrets(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ uint8_t *secret_out = tor_malloc_zero(DIGEST256_LEN);;
+ tor_tls_t *tls;
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION));
+ tls->ssl->session->master_key_length = 1;
+ tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE));
+
+ ret = tor_tls_get_tlssecrets(tls, secret_out);
+ tt_int_op(ret, OP_EQ, 0);
+
+ done:
+ tor_free(secret_out);
+ tor_free(tls->ssl->s3);
+ tor_free(tls->ssl->session);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_get_buffer_sizes(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ size_t rbuf_c=-1, rbuf_b=-1, wbuf_c=-1, wbuf_b=-1;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE));
+
+ tls->ssl->s3->rbuf.buf = NULL;
+ tls->ssl->s3->rbuf.len = 1;
+ tls->ssl->s3->rbuf.offset = 0;
+ tls->ssl->s3->rbuf.left = 42;
+
+ tls->ssl->s3->wbuf.buf = NULL;
+ tls->ssl->s3->wbuf.len = 2;
+ tls->ssl->s3->wbuf.offset = 0;
+ tls->ssl->s3->wbuf.left = 43;
+
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+ ret = tor_tls_get_buffer_sizes(NULL, NULL, NULL, NULL, NULL);
+ tt_int_op(ret, OP_EQ, -1);
+#else
+ ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(rbuf_c, OP_EQ, 0);
+ tt_int_op(wbuf_c, OP_EQ, 0);
+ tt_int_op(rbuf_b, OP_EQ, 42);
+ tt_int_op(wbuf_b, OP_EQ, 43);
+
+ tls->ssl->s3->rbuf.buf = tor_malloc_zero(1);
+ tls->ssl->s3->wbuf.buf = tor_malloc_zero(1);
+ ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(rbuf_c, OP_EQ, 1);
+ tt_int_op(wbuf_c, OP_EQ, 2);
+
+#endif
+
+ done:
+ tor_free(tls->ssl->s3->rbuf.buf);
+ tor_free(tls->ssl->s3->wbuf.buf);
+ tor_free(tls->ssl->s3);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+static void
+test_tortls_evaluate_ecgroup_for_tls(void *ignored)
+{
+ (void)ignored;
+ int ret;
+
+ ret = evaluate_ecgroup_for_tls(NULL);
+ tt_int_op(ret, OP_EQ, 1);
+
+ ret = evaluate_ecgroup_for_tls("foobar");
+ tt_int_op(ret, OP_EQ, 0);
+
+ ret = evaluate_ecgroup_for_tls("P256");
+ tt_int_op(ret, OP_EQ, 1);
+
+ ret = evaluate_ecgroup_for_tls("P224");
+ // tt_int_op(ret, OP_EQ, 1); This varies between machines
+
+ done:
+ (void)0;
+}
+
+#ifndef OPENSSL_OPAQUE
+typedef struct cert_pkey_st_local
+{
+ X509 *x509;
+ EVP_PKEY *privatekey;
+ const EVP_MD *digest;
+} CERT_PKEY_local;
+
+typedef struct sess_cert_st_local
+{
+ STACK_OF(X509) *cert_chain;
+ int peer_cert_type;
+ CERT_PKEY_local *peer_key;
+ CERT_PKEY_local peer_pkeys[8];
+ int references;
+} SESS_CERT_local;
+
+static void
+test_tortls_try_to_extract_certs_from_tls(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ X509 *cert = NULL, *id_cert = NULL, *c1 = NULL, *c2 = NULL;
+ SESS_CERT_local *sess = NULL;
+
+ c1 = read_cert_from(validCertString);
+ c2 = read_cert_from(caCertString);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION));
+ sess = tor_malloc_zero(sizeof(SESS_CERT_local));
+ tls->ssl->session->sess_cert = (void *)sess;
+
+ try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert);
+ tt_assert(!cert);
+ tt_assert(!id_cert);
+
+ tls->ssl->session->peer = c1;
+ try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert);
+ tt_assert(cert == c1);
+ tt_assert(!id_cert);
+
+ sess->cert_chain = sk_X509_new_null();
+ try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert);
+ tt_assert(cert == c1);
+ tt_assert(!id_cert);
+
+ sk_X509_push(sess->cert_chain, c1);
+ sk_X509_push(sess->cert_chain, c2);
+ try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert);
+ tt_assert(cert == c1);
+ tt_assert(id_cert);
+
+ done:
+ tor_free(sess);
+ tor_free(tls->ssl->session);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_get_peer_cert(void *ignored)
+{
+ (void)ignored;
+ tor_x509_cert_t *ret;
+ tor_tls_t *tls;
+ X509 *cert = NULL;
+
+ cert = read_cert_from(validCertString);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION));
+
+ ret = tor_tls_get_peer_cert(tls);
+ tt_assert(!ret);
+
+ tls->ssl->session->peer = cert;
+ ret = tor_tls_get_peer_cert(tls);
+ tt_assert(ret);
+ tt_assert(ret->cert == cert);
+
+ done:
+ tor_x509_cert_free(ret);
+ tor_free(tls->ssl->session);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_peer_has_cert(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ X509 *cert = NULL;
+
+ cert = read_cert_from(validCertString);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION));
+
+ ret = tor_tls_peer_has_cert(tls);
+ tt_assert(!ret);
+
+ tls->ssl->session->peer = cert;
+ ret = tor_tls_peer_has_cert(tls);
+ tt_assert(ret);
+
+ done:
+ tor_free(tls->ssl->session);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+static void
+test_tortls_is_server(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ int ret;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->isServer = 1;
+ ret = tor_tls_is_server(tls);
+ tt_int_op(ret, OP_EQ, 1);
+
+ done:
+ tor_free(tls);
+}
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_session_secret_cb(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ SSL_CTX *ctx;
+ STACK_OF(SSL_CIPHER) *ciphers = NULL;
+ SSL_CIPHER *one;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+
+ tls->magic = TOR_TLS_MAGIC;
+
+ ctx = SSL_CTX_new(TLSv1_method());
+ tls->ssl = SSL_new(ctx);
+ SSL_set_ex_data(tls->ssl, tor_tls_object_ex_data_index, tls);
+
+ SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL);
+
+ tor_tls_session_secret_cb(tls->ssl, NULL, NULL, NULL, NULL, NULL);
+ tt_assert(!tls->ssl->tls_session_secret_cb);
+
+ one = get_cipher_by_name("ECDH-RSA-AES256-GCM-SHA384");
+ one->id = 0x00ff;
+ ciphers = sk_SSL_CIPHER_new_null();
+ sk_SSL_CIPHER_push(ciphers, one);
+
+ tls->client_cipher_list_type = 0;
+ tor_tls_session_secret_cb(tls->ssl, NULL, NULL, ciphers, NULL, NULL);
+ tt_assert(!tls->ssl->tls_session_secret_cb);
+
+ done:
+ sk_SSL_CIPHER_free(ciphers);
+ SSL_free(tls->ssl);
+ SSL_CTX_free(ctx);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+/* TODO: It seems block_renegotiation and unblock_renegotiation and
+ * using different blags. This might not be correct */
+static void
+test_tortls_block_renegotiation(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE));
+ tls->ssl->s3->flags = 0x0010;
+
+ tor_tls_block_renegotiation(tls);
+
+ tt_assert(!(SSL_get_options(tls->ssl) & 0x0010));
+
+ done:
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+
+static void
+test_tortls_unblock_renegotiation(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tor_tls_unblock_renegotiation(tls);
+
+ tt_assert(SSL_get_options(tls->ssl) & 0x00040000L);
+
+ done:
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_assert_renegotiation_unblocked(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tor_tls_unblock_renegotiation(tls);
+ tor_tls_assert_renegotiation_unblocked(tls);
+ /* No assertion here - this test will fail if tor_assert is turned on
+ * and things are bad. */
+
+ tor_free(tls);
+}
+#endif
+
+static void
+test_tortls_set_logged_address(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+
+ tor_tls_set_logged_address(tls, "foo bar");
+
+ tt_str_op(tls->address, OP_EQ, "foo bar");
+
+ tor_tls_set_logged_address(tls, "foo bar 2");
+ tt_str_op(tls->address, OP_EQ, "foo bar 2");
+
+ done:
+ tor_free(tls);
+}
+
+#ifndef OPENSSL_OPAQUE
+static void
+example_cb(tor_tls_t *t, void *arg)
+{
+ (void)t;
+ (void)arg;
+}
+
+static void
+test_tortls_set_renegotiate_callback(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ const char *arg = "hello";
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+
+ tor_tls_set_renegotiate_callback(tls, example_cb, (void*)arg);
+ tt_assert(tls->negotiated_callback == example_cb);
+ tt_assert(tls->callback_arg == arg);
+ tt_assert(!tls->got_renegotiate);
+
+ /* Assumes V2_HANDSHAKE_SERVER */
+ tt_assert(tls->ssl->info_callback == tor_tls_server_info_callback);
+
+ tor_tls_set_renegotiate_callback(tls, NULL, (void*)arg);
+ tt_assert(tls->ssl->info_callback == tor_tls_debug_state_callback);
+
+ done:
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static const SSL_CIPHER *
+fake_get_cipher(unsigned ncipher)
+{
+ SSL_CIPHER *fixed = tor_malloc_zero(sizeof(SSL_CIPHER));
+ SSL_CIPHER *fixed2 = tor_malloc_zero(sizeof(SSL_CIPHER));
+ fixed2->id = 0xC00A;
+ switch (ncipher) {
+ case 1:
+ return fixed;
+ case 2:
+ return fixed2;
+ default:
+ return NULL;
+ }
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_find_cipher_by_id(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ SSL *ssl;
+ SSL_CTX *ctx;
+ const SSL_METHOD *m = TLSv1_method();
+ SSL_METHOD *empty_method = tor_malloc_zero(sizeof(SSL_METHOD));
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(m);
+ ssl = SSL_new(ctx);
+
+ ret = find_cipher_by_id(ssl, NULL, 0xC00A);
+ tt_int_op(ret, OP_EQ, 1);
+
+ ret = find_cipher_by_id(ssl, m, 0xC00A);
+ tt_int_op(ret, OP_EQ, 1);
+
+ ret = find_cipher_by_id(ssl, m, 0xFFFF);
+ tt_int_op(ret, OP_EQ, 0);
+
+ ret = find_cipher_by_id(ssl, empty_method, 0xC00A);
+ tt_int_op(ret, OP_EQ, 1);
+
+ ret = find_cipher_by_id(ssl, empty_method, 0xFFFF);
+#ifdef HAVE_SSL_CIPHER_FIND
+ tt_int_op(ret, OP_EQ, 0);
+#else
+ tt_int_op(ret, OP_EQ, 1);
+#endif
+
+ empty_method->get_cipher = fake_get_cipher;
+ ret = find_cipher_by_id(ssl, empty_method, 0xC00A);
+ tt_int_op(ret, OP_EQ, 1);
+
+ empty_method->get_cipher = m->get_cipher;
+ empty_method->num_ciphers = m->num_ciphers;
+ ret = find_cipher_by_id(ssl, empty_method, 0xC00A);
+ tt_int_op(ret, OP_EQ, 1);
+
+ empty_method->get_cipher = fake_get_cipher;
+ empty_method->num_ciphers = m->num_ciphers;
+ ret = find_cipher_by_id(ssl, empty_method, 0xC00A);
+ tt_int_op(ret, OP_EQ, 1);
+
+ empty_method->num_ciphers = fake_num_ciphers;
+ ret = find_cipher_by_id(ssl, empty_method, 0xC00A);
+#ifdef HAVE_SSL_CIPHER_FIND
+ tt_int_op(ret, OP_EQ, 1);
+#else
+ tt_int_op(ret, OP_EQ, 0);
+#endif
+
+ done:
+ tor_free(empty_method);
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_debug_state_callback(void *ignored)
+{
+ (void)ignored;
+ SSL *ssl;
+ char *buf = tor_malloc_zero(1000);
+ int n;
+
+ int previous_log = setup_capture_of_logs(LOG_DEBUG);
+
+ ssl = tor_malloc_zero(sizeof(SSL));
+
+ tor_tls_debug_state_callback(ssl, 32, 45);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ n = snprintf(buf, 1000, "SSL %p is now in state unknown"
+ " state [type=32,val=45].\n", ssl);
+ buf[n]='\0';
+ if (strcasecmp(mock_saved_log_at(0), buf))
+ tt_str_op(mock_saved_log_at(0), OP_EQ, buf);
+
+ done:
+ teardown_capture_of_logs(previous_log);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_server_info_callback(void *ignored)
+{
+ (void)ignored;
+ tor_tls_t *tls;
+ SSL_CTX *ctx;
+ SSL *ssl;
+ int previous_log = setup_capture_of_logs(LOG_WARN);
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(TLSv1_method());
+ ssl = SSL_new(ctx);
+
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->magic = TOR_TLS_MAGIC;
+ tls->ssl = ssl;
+
+ tor_tls_server_info_callback(NULL, 0, 0);
+
+ SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_A);
+ mock_clean_saved_logs();
+ tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Couldn't look up the tls for an SSL*. How odd!\n");
+
+ SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_B);
+ mock_clean_saved_logs();
+ tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Couldn't look up the tls for an SSL*. How odd!\n");
+
+ SSL_set_state(ssl, 99);
+ mock_clean_saved_logs();
+ tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 0);
+
+ SSL_set_ex_data(tls->ssl, tor_tls_object_ex_data_index, tls);
+ SSL_set_state(ssl, SSL3_ST_SW_SRVR_HELLO_B);
+ tls->negotiated_callback = 0;
+ tls->server_handshake_count = 120;
+ tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0);
+ tt_int_op(tls->server_handshake_count, OP_EQ, 121);
+
+ tls->server_handshake_count = 127;
+ tls->negotiated_callback = (void *)1;
+ tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0);
+ tt_int_op(tls->server_handshake_count, OP_EQ, 127);
+ tt_int_op(tls->got_renegotiate, OP_EQ, 1);
+
+ tls->ssl->session = SSL_SESSION_new();
+ tls->wasV2Handshake = 0;
+ tor_tls_server_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 0);
+ tt_int_op(tls->wasV2Handshake, OP_EQ, 0);
+
+ done:
+ teardown_capture_of_logs(previous_log);
+ tor_free(ssl);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static int fixed_ssl_read_result_index;
+static int fixed_ssl_read_result[5];
+static int fixed_ssl_shutdown_result;
+
+static int
+fixed_ssl_read(SSL *s, void *buf, int len)
+{
+ (void)s;
+ (void)buf;
+ (void)len;
+ return fixed_ssl_read_result[fixed_ssl_read_result_index++];
+}
+
+static int
+fixed_ssl_shutdown(SSL *s)
+{
+ (void)s;
+ return fixed_ssl_shutdown_result;
+}
+
+static int fixed_ssl_state_to_set;
+static tor_tls_t *fixed_tls;
+
+static int
+setting_version_ssl_shutdown(SSL *s)
+{
+ s->version = SSL2_VERSION;
+ return fixed_ssl_shutdown_result;
+}
+
+static int
+setting_version_and_state_ssl_shutdown(SSL *s)
+{
+ fixed_tls->state = fixed_ssl_state_to_set;
+ s->version = SSL2_VERSION;
+ return fixed_ssl_shutdown_result;
+}
+
+static int
+dummy_handshake_func(SSL *s)
+{
+ (void)s;
+ return 1;
+}
+
+static void
+test_tortls_shutdown(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ SSL_METHOD *method = give_me_a_test_method();
+ int previous_log = setup_capture_of_logs(LOG_WARN);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->ssl->method = method;
+ method->ssl_read = fixed_ssl_read;
+ method->ssl_shutdown = fixed_ssl_shutdown;
+
+ ret = tor_tls_shutdown(tls);
+ tt_int_op(ret, OP_EQ, -9);
+
+ tls->state = TOR_TLS_ST_SENTCLOSE;
+ fixed_ssl_read_result_index = 0;
+ fixed_ssl_read_result[0] = 10;
+ fixed_ssl_read_result[1] = -1;
+ ret = tor_tls_shutdown(tls);
+ tt_int_op(ret, OP_EQ, -9);
+
+ tls->ssl->handshake_func = dummy_handshake_func;
+
+ fixed_ssl_read_result_index = 0;
+ fixed_ssl_read_result[0] = 10;
+ fixed_ssl_read_result[1] = 42;
+ fixed_ssl_read_result[2] = 0;
+ fixed_ssl_shutdown_result = 1;
+ ERR_clear_error();
+ tls->ssl->version = SSL2_VERSION;
+ ret = tor_tls_shutdown(tls);
+ tt_int_op(ret, OP_EQ, TOR_TLS_DONE);
+ tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED);
+
+ fixed_ssl_read_result_index = 0;
+ fixed_ssl_read_result[0] = 10;
+ fixed_ssl_read_result[1] = 42;
+ fixed_ssl_read_result[2] = 0;
+ fixed_ssl_shutdown_result = 0;
+ ERR_clear_error();
+ tls->ssl->version = 0;
+ ret = tor_tls_shutdown(tls);
+ tt_int_op(ret, OP_EQ, TOR_TLS_DONE);
+ tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED);
+
+ fixed_ssl_read_result_index = 0;
+ fixed_ssl_read_result[0] = 10;
+ fixed_ssl_read_result[1] = 42;
+ fixed_ssl_read_result[2] = 0;
+ fixed_ssl_shutdown_result = 0;
+ ERR_clear_error();
+ tls->ssl->version = 0;
+ method->ssl_shutdown = setting_version_ssl_shutdown;
+ ret = tor_tls_shutdown(tls);
+ tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC);
+
+ fixed_ssl_read_result_index = 0;
+ fixed_ssl_read_result[0] = 10;
+ fixed_ssl_read_result[1] = 42;
+ fixed_ssl_read_result[2] = 0;
+ fixed_ssl_shutdown_result = 0;
+ fixed_tls = tls;
+ fixed_ssl_state_to_set = TOR_TLS_ST_GOTCLOSE;
+ ERR_clear_error();
+ tls->ssl->version = 0;
+ method->ssl_shutdown = setting_version_and_state_ssl_shutdown;
+ ret = tor_tls_shutdown(tls);
+ tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC);
+
+ fixed_ssl_read_result_index = 0;
+ fixed_ssl_read_result[0] = 10;
+ fixed_ssl_read_result[1] = 42;
+ fixed_ssl_read_result[2] = 0;
+ fixed_ssl_read_result[3] = -1;
+ fixed_ssl_shutdown_result = 0;
+ fixed_tls = tls;
+ fixed_ssl_state_to_set = 0;
+ ERR_clear_error();
+ tls->ssl->version = 0;
+ method->ssl_shutdown = setting_version_and_state_ssl_shutdown;
+ ret = tor_tls_shutdown(tls);
+ tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC);
+
+ done:
+ teardown_capture_of_logs(previous_log);
+ tor_free(method);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+
+static int negotiated_callback_called;
+
+static void
+negotiated_callback_setter(tor_tls_t *t, void *arg)
+{
+ (void)t;
+ (void)arg;
+ negotiated_callback_called++;
+}
+
+static void
+test_tortls_read(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ char buf[100];
+ SSL_METHOD *method = give_me_a_test_method();
+ int previous_log = setup_capture_of_logs(LOG_WARN);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->state = TOR_TLS_ST_OPEN;
+
+ ret = tor_tls_read(tls, buf, 10);
+ tt_int_op(ret, OP_EQ, -9);
+
+ /* These tests assume that V2_HANDSHAKE_SERVER is set */
+ tls->ssl->handshake_func = dummy_handshake_func;
+ tls->ssl->method = method;
+ method->ssl_read = fixed_ssl_read;
+ fixed_ssl_read_result_index = 0;
+ fixed_ssl_read_result[0] = 42;
+ tls->state = TOR_TLS_ST_OPEN;
+ ERR_clear_error();
+ ret = tor_tls_read(tls, buf, 10);
+ tt_int_op(ret, OP_EQ, 42);
+
+ tls->state = TOR_TLS_ST_OPEN;
+ tls->got_renegotiate = 1;
+ fixed_ssl_read_result_index = 0;
+ ERR_clear_error();
+ ret = tor_tls_read(tls, buf, 10);
+ tt_int_op(tls->got_renegotiate, OP_EQ, 0);
+
+ tls->state = TOR_TLS_ST_OPEN;
+ tls->got_renegotiate = 1;
+ negotiated_callback_called = 0;
+ tls->negotiated_callback = negotiated_callback_setter;
+ fixed_ssl_read_result_index = 0;
+ ERR_clear_error();
+ ret = tor_tls_read(tls, buf, 10);
+ tt_int_op(negotiated_callback_called, OP_EQ, 1);
+
+ fixed_ssl_read_result_index = 0;
+ fixed_ssl_read_result[0] = 0;
+ tls->ssl->version = SSL2_VERSION;
+ ERR_clear_error();
+ ret = tor_tls_read(tls, buf, 10);
+ tt_int_op(ret, OP_EQ, TOR_TLS_CLOSE);
+ tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_CLOSED);
+
+ // TODO: fill up
+
+ done:
+ teardown_capture_of_logs(previous_log);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+
+static int fixed_ssl_write_result;
+
+static int
+fixed_ssl_write(SSL *s, const void *buf, int len)
+{
+ (void)s;
+ (void)buf;
+ (void)len;
+ return fixed_ssl_write_result;
+}
+
+static void
+test_tortls_write(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ SSL_METHOD *method = give_me_a_test_method();
+ char buf[100];
+ int previous_log = setup_capture_of_logs(LOG_WARN);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = tor_malloc_zero(sizeof(SSL));
+ tls->state = TOR_TLS_ST_OPEN;
+
+ ret = tor_tls_write(tls, buf, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ ret = tor_tls_write(tls, buf, 10);
+ tt_int_op(ret, OP_EQ, -9);
+
+ tls->ssl->method = method;
+ tls->wantwrite_n = 1;
+ ret = tor_tls_write(tls, buf, 10);
+ tt_int_op(tls->wantwrite_n, OP_EQ, 0);
+
+ method->ssl_write = fixed_ssl_write;
+ tls->ssl->handshake_func = dummy_handshake_func;
+ fixed_ssl_write_result = 1;
+ ERR_clear_error();
+ ret = tor_tls_write(tls, buf, 10);
+ tt_int_op(ret, OP_EQ, 1);
+
+ fixed_ssl_write_result = -1;
+ ERR_clear_error();
+ tls->ssl->rwstate = SSL_READING;
+ SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL);
+ SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_READ;
+ ret = tor_tls_write(tls, buf, 10);
+ tt_int_op(ret, OP_EQ, TOR_TLS_WANTREAD);
+
+ ERR_clear_error();
+ tls->ssl->rwstate = SSL_READING;
+ SSL_set_bio(tls->ssl, BIO_new(BIO_s_mem()), NULL);
+ SSL_get_rbio(tls->ssl)->flags = BIO_FLAGS_WRITE;
+ ret = tor_tls_write(tls, buf, 10);
+ tt_int_op(ret, OP_EQ, TOR_TLS_WANTWRITE);
+
+ done:
+ teardown_capture_of_logs(previous_log);
+ tor_free(tls->ssl);
+ tor_free(tls);
+}
+
+static int fixed_ssl_renegotiate_result;
+
+static int
+fixed_ssl_renegotiate(SSL *s)
+{
+ (void) s;
+ return fixed_ssl_renegotiate_result;
+}
+
+static void
+test_tortls_renegotiate(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ SSL_CTX *ctx;
+ SSL_METHOD *method = give_me_a_test_method();
+ int previous_log = setup_capture_of_logs(LOG_WARN);
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(TLSv1_method());
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = SSL_new(ctx);
+ tls->state = TOR_TLS_ST_OPEN;
+
+ ret = tor_tls_renegotiate(tls);
+ tt_int_op(ret, OP_EQ, -9);
+
+ tls->ssl->method = method;
+ method->ssl_renegotiate = fixed_ssl_renegotiate;
+ fixed_ssl_renegotiate_result = 0;
+ ERR_clear_error();
+ ret = tor_tls_renegotiate(tls);
+ tt_int_op(ret, OP_EQ, -9);
+
+ ERR_clear_error();
+ tls->ssl->handshake_func = dummy_handshake_func;
+ tls->state = TOR_TLS_ST_RENEGOTIATE;
+ ret = tor_tls_renegotiate(tls);
+ tt_int_op(ret, OP_EQ, TOR_TLS_DONE);
+
+ ERR_clear_error();
+ tls->state = TOR_TLS_ST_OPEN;
+ fixed_ssl_renegotiate_result = -1;
+ ret = tor_tls_renegotiate(tls);
+ tt_int_op(ret, OP_EQ, -9);
+
+ done:
+ teardown_capture_of_logs(previous_log);
+ SSL_free(tls->ssl);
+ SSL_CTX_free(ctx);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static int fixed_ssl_accept_result;
+static int fixed_ssl_connect_result;
+
+static int
+setting_error_ssl_accept(SSL *ssl)
+{
+ (void)ssl;
+ ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99);
+ ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99);
+ return fixed_ssl_accept_result;
+}
+
+static int
+setting_error_ssl_connect(SSL *ssl)
+{
+ (void)ssl;
+ ERR_put_error(ERR_LIB_BN, 2, -1, "somewhere.c", 99);
+ ERR_put_error(ERR_LIB_SYS, 2, -1, "somewhere.c", 99);
+ return fixed_ssl_connect_result;
+}
+
+static int
+fixed_ssl_accept(SSL *ssl)
+{
+ (void) ssl;
+ return fixed_ssl_accept_result;
+}
+
+static void
+test_tortls_handshake(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ SSL_CTX *ctx;
+ SSL_METHOD *method = give_me_a_test_method();
+ int previous_log = setup_capture_of_logs(LOG_INFO);
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(TLSv1_method());
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = SSL_new(ctx);
+ tls->state = TOR_TLS_ST_HANDSHAKE;
+
+ ret = tor_tls_handshake(tls);
+ tt_int_op(ret, OP_EQ, -9);
+
+ tls->isServer = 1;
+ tls->state = TOR_TLS_ST_HANDSHAKE;
+ ret = tor_tls_handshake(tls);
+ tt_int_op(ret, OP_EQ, -9);
+
+ tls->ssl->method = method;
+ method->ssl_accept = fixed_ssl_accept;
+ fixed_ssl_accept_result = 2;
+ ERR_clear_error();
+ tls->state = TOR_TLS_ST_HANDSHAKE;
+ ret = tor_tls_handshake(tls);
+ tt_int_op(tls->state, OP_EQ, TOR_TLS_ST_OPEN);
+
+ method->ssl_accept = setting_error_ssl_accept;
+ fixed_ssl_accept_result = 1;
+ ERR_clear_error();
+ mock_clean_saved_logs();
+ tls->state = TOR_TLS_ST_HANDSHAKE;
+ ret = tor_tls_handshake(tls);
+ tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 2);
+ /* This fails on jessie. Investigate why! */
+#if 0
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "TLS error while handshaking: (null) (in bignum routines:"
+ "(null):SSLv3 write client hello B)\n");
+ tt_str_op(mock_saved_log_at(1), OP_EQ,
+ "TLS error while handshaking: (null) (in system library:"
+ "connect:SSLv3 write client hello B)\n");
+#endif
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+ tt_int_op(mock_saved_severity_at(1), OP_EQ, LOG_INFO);
+
+ tls->isServer = 0;
+ method->ssl_connect = setting_error_ssl_connect;
+ fixed_ssl_connect_result = 1;
+ ERR_clear_error();
+ mock_clean_saved_logs();
+ tls->state = TOR_TLS_ST_HANDSHAKE;
+ ret = tor_tls_handshake(tls);
+ tt_int_op(ret, OP_EQ, TOR_TLS_ERROR_MISC);
+ tt_int_op(mock_saved_log_number(), OP_EQ, 2);
+#if 0
+ /* See above */
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "TLS error while handshaking: "
+ "(null) (in bignum routines:(null):SSLv3 write client hello B)\n");
+ tt_str_op(mock_saved_log_at(1), OP_EQ, "TLS error while handshaking: "
+ "(null) (in system library:connect:SSLv3 write client hello B)\n");
+#endif
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
+ tt_int_op(mock_saved_severity_at(1), OP_EQ, LOG_WARN);
+
+ done:
+ teardown_capture_of_logs(previous_log);
+ SSL_free(tls->ssl);
+ SSL_CTX_free(ctx);
+ tor_free(tls);
+}
+#endif
+
+#ifndef OPENSSL_OPAQUE
+static void
+test_tortls_finish_handshake(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_t *tls;
+ SSL_CTX *ctx;
+ SSL_METHOD *method = give_me_a_test_method();
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ X509 *c1 = read_cert_from(validCertString);
+ X509 *c2 = read_cert_from(caCertString);
+
+ ctx = SSL_CTX_new(method);
+
+ tls = tor_malloc_zero(sizeof(tor_tls_t));
+ tls->ssl = SSL_new(ctx);
+ tls->state = TOR_TLS_ST_OPEN;
+
+ ret = tor_tls_finish_handshake(tls);
+ tt_int_op(ret, OP_EQ, 0);
+
+ tls->isServer = 1;
+ tls->wasV2Handshake = 0;
+ ret = tor_tls_finish_handshake(tls);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tls->wasV2Handshake, OP_EQ, 1);
+
+ tls->wasV2Handshake = 1;
+ ret = tor_tls_finish_handshake(tls);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tls->wasV2Handshake, OP_EQ, 1);
+
+ tls->wasV2Handshake = 1;
+ tls->ssl->session = SSL_SESSION_new();
+ ret = tor_tls_finish_handshake(tls);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tls->wasV2Handshake, OP_EQ, 0);
+
+ tls->isServer = 0;
+
+ SESS_CERT_local *sess = tor_malloc_zero(sizeof(SESS_CERT_local));
+ tls->ssl->session->sess_cert = (void *)sess;
+ sess->cert_chain = sk_X509_new_null();
+ sk_X509_push(sess->cert_chain, c1);
+ tls->ssl->session->peer = c1;
+ tls->wasV2Handshake = 0;
+ ret = tor_tls_finish_handshake(tls);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tls->wasV2Handshake, OP_EQ, 1);
+
+ tls->ssl->session->peer = c2;
+ tls->wasV2Handshake = 1;
+ ret = tor_tls_finish_handshake(tls);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tls->wasV2Handshake, OP_EQ, 0);
+
+ sk_X509_push(sess->cert_chain, c2);
+ tls->wasV2Handshake = 1;
+ ret = tor_tls_finish_handshake(tls);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tls->wasV2Handshake, OP_EQ, 0);
+
+ method->num_ciphers = fake_num_ciphers;
+ ret = tor_tls_finish_handshake(tls);
+ tt_int_op(ret, OP_EQ, -9);
+
+ done:
+ SSL_CTX_free(ctx);
+ tor_free(tls);
+}
+#endif
+
+static int fixed_crypto_pk_new_result_index;
+static crypto_pk_t *fixed_crypto_pk_new_result[5];
+
+static crypto_pk_t *
+fixed_crypto_pk_new(void)
+{
+ return fixed_crypto_pk_new_result[fixed_crypto_pk_new_result_index++];
+}
+
+#ifndef OPENSSL_OPAQUE
+static int fixed_crypto_pk_generate_key_with_bits_result_index;
+static int fixed_crypto_pk_generate_key_with_bits_result[5];
+static int fixed_tor_tls_create_certificate_result_index;
+static X509 *fixed_tor_tls_create_certificate_result[5];
+static int fixed_tor_x509_cert_new_result_index;
+static tor_x509_cert_t *fixed_tor_x509_cert_new_result[5];
+
+static int
+fixed_crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits)
+{
+ (void)env;
+ (void)bits;
+ return fixed_crypto_pk_generate_key_with_bits_result[
+ fixed_crypto_pk_generate_key_with_bits_result_index++];
+}
+
+static X509 *
+fixed_tor_tls_create_certificate(crypto_pk_t *rsa,
+ crypto_pk_t *rsa_sign,
+ const char *cname,
+ const char *cname_sign,
+ unsigned int cert_lifetime)
+{
+ (void)rsa;
+ (void)rsa_sign;
+ (void)cname;
+ (void)cname_sign;
+ (void)cert_lifetime;
+ return fixed_tor_tls_create_certificate_result[
+ fixed_tor_tls_create_certificate_result_index++];
+}
+
+static tor_x509_cert_t *
+fixed_tor_x509_cert_new(X509 *x509_cert)
+{
+ (void) x509_cert;
+ return fixed_tor_x509_cert_new_result[
+ fixed_tor_x509_cert_new_result_index++];
+}
+
+static void
+test_tortls_context_new(void *ignored)
+{
+ (void)ignored;
+ tor_tls_context_t *ret;
+ crypto_pk_t *pk1, *pk2, *pk3, *pk4, *pk5, *pk6, *pk7, *pk8, *pk9, *pk10,
+ *pk11, *pk12, *pk13, *pk14, *pk15, *pk16, *pk17, *pk18;
+
+ pk1 = crypto_pk_new();
+ pk2 = crypto_pk_new();
+ pk3 = crypto_pk_new();
+ pk4 = crypto_pk_new();
+ pk5 = crypto_pk_new();
+ pk6 = crypto_pk_new();
+ pk7 = crypto_pk_new();
+ pk8 = crypto_pk_new();
+ pk9 = crypto_pk_new();
+ pk10 = crypto_pk_new();
+ pk11 = crypto_pk_new();
+ pk12 = crypto_pk_new();
+ pk13 = crypto_pk_new();
+ pk14 = crypto_pk_new();
+ pk15 = crypto_pk_new();
+ pk16 = crypto_pk_new();
+ pk17 = crypto_pk_new();
+ pk18 = crypto_pk_new();
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = NULL;
+ MOCK(crypto_pk_new, fixed_crypto_pk_new);
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ MOCK(crypto_pk_generate_key_with_bits,
+ fixed_crypto_pk_generate_key_with_bits);
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk1;
+ fixed_crypto_pk_new_result[1] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result[0] = -1;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk2;
+ fixed_crypto_pk_new_result[1] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result[0] = 0;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk3;
+ fixed_crypto_pk_new_result[1] = pk4;
+ fixed_crypto_pk_new_result[2] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result[0] = 0;
+ fixed_crypto_pk_generate_key_with_bits_result[1] = -1;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ MOCK(tor_tls_create_certificate, fixed_tor_tls_create_certificate);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk5;
+ fixed_crypto_pk_new_result[1] = pk6;
+ fixed_crypto_pk_new_result[2] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ fixed_crypto_pk_generate_key_with_bits_result[1] = 0;
+ fixed_tor_tls_create_certificate_result_index = 0;
+ fixed_tor_tls_create_certificate_result[0] = NULL;
+ fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk7;
+ fixed_crypto_pk_new_result[1] = pk8;
+ fixed_crypto_pk_new_result[2] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ fixed_tor_tls_create_certificate_result_index = 0;
+ fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[1] = NULL;
+ fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk9;
+ fixed_crypto_pk_new_result[1] = pk10;
+ fixed_crypto_pk_new_result[2] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ fixed_tor_tls_create_certificate_result_index = 0;
+ fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[2] = NULL;
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ MOCK(tor_x509_cert_new, fixed_tor_x509_cert_new);
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk11;
+ fixed_crypto_pk_new_result[1] = pk12;
+ fixed_crypto_pk_new_result[2] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ fixed_tor_tls_create_certificate_result_index = 0;
+ fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_x509_cert_new_result_index = 0;
+ fixed_tor_x509_cert_new_result[0] = NULL;
+ fixed_tor_x509_cert_new_result[1] = NULL;
+ fixed_tor_x509_cert_new_result[2] = NULL;
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk13;
+ fixed_crypto_pk_new_result[1] = pk14;
+ fixed_crypto_pk_new_result[2] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ fixed_tor_tls_create_certificate_result_index = 0;
+ fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_x509_cert_new_result_index = 0;
+ fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ fixed_tor_x509_cert_new_result[1] = NULL;
+ fixed_tor_x509_cert_new_result[2] = NULL;
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk15;
+ fixed_crypto_pk_new_result[1] = pk16;
+ fixed_crypto_pk_new_result[2] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ fixed_tor_tls_create_certificate_result_index = 0;
+ fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_x509_cert_new_result_index = 0;
+ fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ fixed_tor_x509_cert_new_result[1] = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ fixed_tor_x509_cert_new_result[2] = NULL;
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = pk17;
+ fixed_crypto_pk_new_result[1] = pk18;
+ fixed_crypto_pk_new_result[2] = NULL;
+ fixed_crypto_pk_generate_key_with_bits_result_index = 0;
+ fixed_tor_tls_create_certificate_result_index = 0;
+ fixed_tor_tls_create_certificate_result[0] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[1] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_tls_create_certificate_result[2] = tor_malloc_zero(sizeof(X509));
+ fixed_tor_x509_cert_new_result_index = 0;
+ fixed_tor_x509_cert_new_result[0] = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ fixed_tor_x509_cert_new_result[1] = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ fixed_tor_x509_cert_new_result[2] = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ ret = tor_tls_context_new(NULL, 0, 0, 0);
+ tt_assert(!ret);
+
+ done:
+ UNMOCK(tor_x509_cert_new);
+ UNMOCK(tor_tls_create_certificate);
+ UNMOCK(crypto_pk_generate_key_with_bits);
+ UNMOCK(crypto_pk_new);
+}
+#endif
+
+static int fixed_crypto_pk_get_evp_pkey_result_index = 0;
+static EVP_PKEY *fixed_crypto_pk_get_evp_pkey_result[5];
+static int fixed_crypto_rand_result;
+
+static EVP_PKEY *
+fixed_crypto_pk_get_evp_pkey_(crypto_pk_t *env, int private)
+{
+ (void) env;
+ (void) private;
+ return fixed_crypto_pk_get_evp_pkey_result[
+ fixed_crypto_pk_get_evp_pkey_result_index++];
+}
+
+static int
+fixed_crypto_rand(char *to, size_t n)
+{
+ (void)to;
+ (void)n;
+ return fixed_crypto_rand_result;
+}
+
+static void
+test_tortls_create_certificate(void *ignored)
+{
+ (void)ignored;
+ X509 *ret;
+ crypto_pk_t *pk1, *pk2;
+
+ pk1 = crypto_pk_new();
+ pk2 = crypto_pk_new();
+
+ MOCK(crypto_pk_get_evp_pkey_, fixed_crypto_pk_get_evp_pkey_);
+ fixed_crypto_pk_get_evp_pkey_result_index = 0;
+ fixed_crypto_pk_get_evp_pkey_result[0] = NULL;
+ ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_get_evp_pkey_result_index = 0;
+ fixed_crypto_pk_get_evp_pkey_result[0] = tor_malloc_zero(sizeof(EVP_PKEY));
+ fixed_crypto_pk_get_evp_pkey_result[1] = NULL;
+ ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1);
+ tt_assert(!ret);
+
+ fixed_crypto_pk_get_evp_pkey_result_index = 0;
+ fixed_crypto_pk_get_evp_pkey_result[0] = tor_malloc_zero(sizeof(EVP_PKEY));
+ fixed_crypto_pk_get_evp_pkey_result[1] = tor_malloc_zero(sizeof(EVP_PKEY));
+ ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1);
+ tt_assert(!ret);
+
+ MOCK(crypto_rand, fixed_crypto_rand);
+ fixed_crypto_rand_result = -1;
+ fixed_crypto_pk_get_evp_pkey_result_index = 0;
+ fixed_crypto_pk_get_evp_pkey_result[0] = tor_malloc_zero(sizeof(EVP_PKEY));
+ fixed_crypto_pk_get_evp_pkey_result[1] = tor_malloc_zero(sizeof(EVP_PKEY));
+ ret = tor_tls_create_certificate(pk1, pk2, "hello", "hello2", 1);
+ tt_assert(!ret);
+
+ done:
+ UNMOCK(crypto_rand);
+ UNMOCK(crypto_pk_get_evp_pkey_);
+}
+
+static void
+test_tortls_cert_new(void *ignored)
+{
+ (void)ignored;
+ tor_x509_cert_t *ret;
+ X509 *cert = read_cert_from(validCertString);
+
+ ret = tor_x509_cert_new(NULL);
+ tt_assert(!ret);
+
+ ret = tor_x509_cert_new(cert);
+ tt_assert(ret);
+
+ X509_get_pubkey(cert)->type = EVP_PKEY_DSA;
+ ret = tor_x509_cert_new(cert);
+ tt_assert(ret);
+
+#ifndef OPENSSL_OPAQUE
+ cert->cert_info = NULL;
+ ret = tor_x509_cert_new(cert);
+ tt_assert(ret);
+#endif
+
+ done:
+ (void)0;
+}
+
+static void
+test_tortls_cert_is_valid(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_x509_cert_t *cert = NULL, *scert;
+
+ scert = tor_malloc_zero(sizeof(tor_x509_cert_t));
+ ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ cert = tor_x509_cert_new(read_cert_from(validCertString));
+ scert = tor_x509_cert_new(read_cert_from(caCertString));
+ ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, 0);
+ tt_int_op(ret, OP_EQ, 1);
+
+#ifndef OPENSSL_OPAQUE
+ cert = tor_x509_cert_new(read_cert_from(validCertString));
+ scert = tor_x509_cert_new(read_cert_from(caCertString));
+ cert->cert->cert_info->validity->notAfter =
+ ASN1_TIME_set(NULL, time(NULL)-1000000);
+ ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ cert = tor_x509_cert_new(read_cert_from(validCertString));
+ scert = tor_x509_cert_new(read_cert_from(caCertString));
+ cert->cert->cert_info->key = NULL;
+ ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, 1);
+ tt_int_op(ret, OP_EQ, 0);
+#endif
+
+ cert = tor_x509_cert_new(read_cert_from(validCertString));
+ scert = tor_x509_cert_new(read_cert_from(caCertString));
+ BN_one(EVP_PKEY_get1_RSA(X509_get_pubkey(cert->cert))->n);
+ ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, 1);
+ tt_int_op(ret, OP_EQ, 0);
+
+ cert = tor_x509_cert_new(read_cert_from(validCertString));
+ scert = tor_x509_cert_new(read_cert_from(caCertString));
+ X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC;
+ ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, 1);
+ tt_int_op(ret, OP_EQ, 0);
+
+ cert = tor_x509_cert_new(read_cert_from(validCertString));
+ scert = tor_x509_cert_new(read_cert_from(caCertString));
+ X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC;
+ ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, 0);
+ tt_int_op(ret, OP_EQ, 1);
+
+ cert = tor_x509_cert_new(read_cert_from(validCertString));
+ scert = tor_x509_cert_new(read_cert_from(caCertString));
+ X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC;
+ X509_get_pubkey(cert->cert)->ameth = NULL;
+ ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ done:
+ (void)0;
+}
+
+static void
+test_tortls_context_init_one(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ tor_tls_context_t *old = NULL;
+
+ MOCK(crypto_pk_new, fixed_crypto_pk_new);
+
+ fixed_crypto_pk_new_result_index = 0;
+ fixed_crypto_pk_new_result[0] = NULL;
+ ret = tor_tls_context_init_one(&old, NULL, 0, 0, 0);
+ tt_int_op(ret, OP_EQ, -1);
+
+ done:
+ UNMOCK(crypto_pk_new);
+}
+
+#define LOCAL_TEST_CASE(name, flags) \
+ { #name, test_tortls_##name, (flags), NULL, NULL }
+
+#ifdef OPENSSL_OPAQUE
+#define INTRUSIVE_TEST_CASE(name, flags) \
+ { #name, NULL, TT_SKIP, NULL, NULL }
+#else
+#define INTRUSIVE_TEST_CASE(name, flags) LOCAL_TEST_CASE(name, flags)
+#endif
+
+struct testcase_t tortls_tests[] = {
+ LOCAL_TEST_CASE(errno_to_tls_error, 0),
+ LOCAL_TEST_CASE(err_to_string, 0),
+ LOCAL_TEST_CASE(tor_tls_new, 0),
+ LOCAL_TEST_CASE(tor_tls_get_error, 0),
+ LOCAL_TEST_CASE(get_state_description, TT_FORK),
+ LOCAL_TEST_CASE(get_by_ssl, TT_FORK),
+ LOCAL_TEST_CASE(allocate_tor_tls_object_ex_data_index, TT_FORK),
+ LOCAL_TEST_CASE(log_one_error, TT_FORK),
+ INTRUSIVE_TEST_CASE(get_error, TT_FORK),
+ LOCAL_TEST_CASE(always_accept_verify_cb, 0),
+ INTRUSIVE_TEST_CASE(x509_cert_free, 0),
+ LOCAL_TEST_CASE(x509_cert_get_id_digests, 0),
+ INTRUSIVE_TEST_CASE(cert_matches_key, 0),
+ INTRUSIVE_TEST_CASE(cert_get_key, 0),
+ LOCAL_TEST_CASE(get_my_client_auth_key, TT_FORK),
+ LOCAL_TEST_CASE(get_my_certs, TT_FORK),
+ INTRUSIVE_TEST_CASE(get_ciphersuite_name, 0),
+ INTRUSIVE_TEST_CASE(classify_client_ciphers, 0),
+ LOCAL_TEST_CASE(client_is_using_v2_ciphers, 0),
+ INTRUSIVE_TEST_CASE(verify, 0),
+ INTRUSIVE_TEST_CASE(check_lifetime, 0),
+ INTRUSIVE_TEST_CASE(get_pending_bytes, 0),
+ LOCAL_TEST_CASE(get_forced_write_size, 0),
+ LOCAL_TEST_CASE(get_write_overhead_ratio, TT_FORK),
+ LOCAL_TEST_CASE(used_v1_handshake, TT_FORK),
+ LOCAL_TEST_CASE(dn_indicates_v3_cert, 0),
+ INTRUSIVE_TEST_CASE(received_v3_certificate, 0),
+ LOCAL_TEST_CASE(get_num_server_handshakes, 0),
+ LOCAL_TEST_CASE(server_got_renegotiate, 0),
+ INTRUSIVE_TEST_CASE(SSL_SESSION_get_master_key, 0),
+ INTRUSIVE_TEST_CASE(get_tlssecrets, 0),
+ INTRUSIVE_TEST_CASE(get_buffer_sizes, 0),
+ LOCAL_TEST_CASE(evaluate_ecgroup_for_tls, 0),
+ INTRUSIVE_TEST_CASE(try_to_extract_certs_from_tls, 0),
+ INTRUSIVE_TEST_CASE(get_peer_cert, 0),
+ INTRUSIVE_TEST_CASE(peer_has_cert, 0),
+ INTRUSIVE_TEST_CASE(shutdown, 0),
+ INTRUSIVE_TEST_CASE(renegotiate, 0),
+ INTRUSIVE_TEST_CASE(finish_handshake, 0),
+ INTRUSIVE_TEST_CASE(handshake, 0),
+ INTRUSIVE_TEST_CASE(write, 0),
+ INTRUSIVE_TEST_CASE(read, 0),
+ INTRUSIVE_TEST_CASE(server_info_callback, 0),
+ LOCAL_TEST_CASE(is_server, 0),
+ INTRUSIVE_TEST_CASE(assert_renegotiation_unblocked, 0),
+ INTRUSIVE_TEST_CASE(block_renegotiation, 0),
+ INTRUSIVE_TEST_CASE(unblock_renegotiation, 0),
+ INTRUSIVE_TEST_CASE(set_renegotiate_callback, 0),
+ LOCAL_TEST_CASE(set_logged_address, 0),
+ INTRUSIVE_TEST_CASE(find_cipher_by_id, 0),
+ INTRUSIVE_TEST_CASE(session_secret_cb, 0),
+ INTRUSIVE_TEST_CASE(debug_state_callback, 0),
+ INTRUSIVE_TEST_CASE(context_new, 0),
+ LOCAL_TEST_CASE(create_certificate, 0),
+ LOCAL_TEST_CASE(cert_new, 0),
+ LOCAL_TEST_CASE(cert_is_valid, 0),
+ LOCAL_TEST_CASE(context_init_one, 0),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c
index 7be67438f5..705dfcf605 100644
--- a/src/test/test_util_format.c
+++ b/src/test/test_util_format.c
@@ -44,30 +44,23 @@ test_util_format_base64_encode(void *ignored)
res = base64_encode(dst, 1000, src, 256, 0);
tt_int_op(res, OP_EQ, 344);
- tt_str_op(dst, OP_EQ,
- "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8g"
- "ISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BB"
- "QkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFi"
- "Y2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKD"
- "hIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOk"
- "paanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TF"
- "xsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm"
- "5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==");
+ tt_str_op(dst, OP_EQ, "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh"
+ "8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH"
+ "SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3"
+ "BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeY"
+ "mZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wM"
+ "HCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp"
+ "6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==");
res = base64_encode(dst, 1000, src, 256, BASE64_ENCODE_MULTILINE);
tt_int_op(res, OP_EQ, 350);
tt_str_op(dst, OP_EQ,
- "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8g"
- "ISIjJCUmJygpKissLS4v\n"
- "MDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9Q"
- "UVJTVFVWV1hZWltcXV5f\n"
- "YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+A"
- "gYKDhIWGh4iJiouMjY6P\n"
- "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+w"
- "sbKztLW2t7i5uru8vb6/\n"
- "wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g"
- "4eLj5OXm5+jp6uvs7e7v\n"
- "8PHy8/T19vf4+fr7/P3+/w==\n");
+ "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v\n"
+ "MDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f\n"
+ "YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P\n"
+ "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/\n"
+ "wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v\n"
+ "8PHy8/T19vf4+fr7/P3+/w==\n");
res = base64_encode(dst, 1000, src+1, 255, BASE64_ENCODE_MULTILINE);
tt_int_op(res, OP_EQ, 346);
@@ -137,6 +130,16 @@ test_util_format_base64_decode_nopad(void *ignored)
res = base64_decode_nopad(dst, 1, src, 5);
tt_int_op(res, OP_EQ, -1);
+ const char *s = "SGVsbG8gd29ybGQ";
+ res = base64_decode_nopad(dst, 1000, s, strlen(s));
+ tt_int_op(res, OP_EQ, 11);
+ tt_mem_op(dst, OP_EQ, "Hello world", 11);
+
+ s = "T3BhIG11bmRv";
+ res = base64_decode_nopad(dst, 9, s, strlen(s));
+ tt_int_op(res, OP_EQ, 9);
+ tt_mem_op(dst, OP_EQ, "Opa mundo", 9);
+
res = base64_decode_nopad(real_dst, 10, real_src, 10);
tt_int_op(res, OP_EQ, 7);
tt_mem_op(real_dst, OP_EQ, expected, 7);
@@ -172,6 +175,21 @@ test_util_format_base64_decode(void *ignored)
res = base64_decode(dst, SIZE_T_CEILING+1, src, 10);
tt_int_op(res, OP_EQ, -1);
+ const char *s = "T3BhIG11bmRv";
+ res = base64_decode(dst, 9, s, strlen(s));
+ tt_int_op(res, OP_EQ, 9);
+ tt_mem_op(dst, OP_EQ, "Opa mundo", 9);
+
+ memset(dst, 0, 1000);
+ res = base64_decode(dst, 100, s, strlen(s));
+ tt_int_op(res, OP_EQ, 9);
+ tt_mem_op(dst, OP_EQ, "Opa mundo", 9);
+
+ s = "SGVsbG8gd29ybGQ=";
+ res = base64_decode(dst, 100, s, strlen(s));
+ tt_int_op(res, OP_EQ, 11);
+ tt_mem_op(dst, OP_EQ, "Hello world", 11);
+
res = base64_decode(real_dst, 10, real_src, 10);
tt_int_op(res, OP_EQ, 7);
tt_mem_op(real_dst, OP_EQ, expected, 7);
@@ -210,6 +228,19 @@ test_util_format_base16_decode(void *ignored)
res = base16_decode(dst, SIZE_T_CEILING+2, src, 10);
tt_int_op(res, OP_EQ, -1);
+ res = base16_decode(dst, 1000, "", 0);
+ tt_int_op(res, OP_EQ, 0);
+
+ res = base16_decode(dst, 1000, "aabc", 4);
+ tt_int_op(res, OP_EQ, 0);
+ tt_mem_op(dst, OP_EQ, "\xaa\xbc", 2);
+
+ res = base16_decode(dst, 1000, "aabcd", 6);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base16_decode(dst, 1000, "axxx", 4);
+ tt_int_op(res, OP_EQ, -1);
+
res = base16_decode(real_dst, 10, real_src, 14);
tt_int_op(res, OP_EQ, 0);
tt_mem_op(real_dst, OP_EQ, expected, 7);
@@ -222,9 +253,10 @@ test_util_format_base16_decode(void *ignored)
struct testcase_t util_format_tests[] = {
{ "base64_encode", test_util_format_base64_encode, 0, NULL, NULL },
- { "base64_decode_nopad", test_util_format_base64_decode_nopad,
- 0, NULL, NULL },
+ { "base64_decode_nopad", test_util_format_base64_decode_nopad, 0,
+ NULL, NULL },
{ "base64_decode", test_util_format_base64_decode, 0, NULL, NULL },
{ "base16_decode", test_util_format_base16_decode, 0, NULL, NULL },
END_OF_TESTCASES
};
+
diff --git a/src/test/test_zero_length_keys.sh b/src/test/test_zero_length_keys.sh
new file mode 100755
index 0000000000..f85edb68db
--- /dev/null
+++ b/src/test/test_zero_length_keys.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Check that tor regenerates keys when key files are zero-length
+
+exitcode=0
+
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -z || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -d || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/or/tor" -e || exitcode=1
+
+exit ${exitcode}
diff --git a/src/test/test_zero_length_keys.sh.in b/src/test/test_zero_length_keys.sh.in
deleted file mode 100644
index d1492d5e20..0000000000
--- a/src/test/test_zero_length_keys.sh.in
+++ /dev/null
@@ -1,10 +0,0 @@
-#!@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/vote_descriptors.inc b/src/test/vote_descriptors.inc
new file mode 100644
index 0000000000..c5ce21f744
--- /dev/null
+++ b/src/test/vote_descriptors.inc
@@ -0,0 +1,94 @@
+const char* VOTE_BODY_V3 =
+"network-status-version 3\n"
+"vote-status vote\n"
+"consensus-methods 13 14 15 16 17 18 19 20 21\n"
+"published 2015-09-02 19:34:15\n"
+"valid-after 2015-09-02 19:50:55\n"
+"fresh-until 2015-09-02 20:07:38\n"
+"valid-until 2015-09-02 20:24:15\n"
+"voting-delay 100 250\n"
+"client-versions 0.1.2.14,0.1.2.17\n"
+"server-versions 0.1.2.10,0.1.2.15,0.1.2.16\n"
+"known-flags Authority Exit Fast Guard MadeOfCheese MadeOfTin Running Stable V2Dir Valid\n"
+"flag-thresholds stable-uptime=0 stable-mtbf=0 fast-speed=0 guard-wfu=0.000% guard-tk=0 guard-bw-inc-exits=0 guard-bw-exc-exits=0 enough-mtbf=0 ignoring-advertised-bws=0\n"
+"params circuitwindow=80 foo=660\n"
+"dir-source Voter3 D867ACF56A9D229B35C25F0090BC9867E906BE69 3.4.5.6 3.4.5.6 80 9000\n"
+"contact voter@example.com\n"
+"legacy-dir-key 4141414141414141414141414141414141414141\n"
+"dir-key-certificate-version 3\n"
+"fingerprint D867ACF56A9D229B35C25F0090BC9867E906BE69\n"
+"dir-key-published 2008-12-12 18:07:24\n"
+"dir-key-expires 2009-12-12 18:07:24\n"
+"dir-identity-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIIBigKCAYEAveMpKlw8oD1YqFqpJchuwSR82BDhutbqgHiez3QO9FmzOctJpV+Y\n"
+"mpTYIJLS/qC+4GBKFF1VK0C4SoBrS3zri0qdXdE+vBGcyrxrjMklpxoqSKRY2011\n"
+"4eqYPghKlo5RzuqteBclGCHyNxWjUJeRKDWgvh+U/gr2uYM6fRm5q0fCzg4aECE7\n"
+"VP6fDGZrMbQI8jHpiMSoC9gkUASNEa6chLInlnP8/H5qUEW4TB9CN/q095pefuwL\n"
+"P+F+1Nz5hnM7fa5XmeMB8iM4RriUmOQlLBZgpQBMpEfWMIPcR9F1Gh3MxERqqUcH\n"
+"tmij+IZdeXg9OkCXykcabaYIhZD3meErn9Tax4oA/THduLfgli9zM0ExwzH1OooN\n"
+"L8rIcJ+2eBo3bQiQUbdYW71sl9w7nSPtircbJUa1mUvWYLPWQxFliPiQSetgJLMj\n"
+"VQqtPmV2hvN2Xk3lLfJO50qMTK7w7Gsaw8UtV4YDM1Hcjp/hQaIB1xfwhXgl+eUU\n"
+"btUa4c+cUTjHAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"dir-signing-key\n"
+"-----BEGIN RSA PUBLIC KEY-----\n"
+"MIGJAoGBALPSUInyuEu6NV3NjozplaniIEBzQXEjv1x9/+mqnwZABpYVmuy9A8nx\n"
+"eoyY3sZFsnYwNW/IZjAgG23pEmevu3F+L4myMjjaa6ORl3MgRYQ4gmuFqpefrGdm\n"
+"ywRCleh2JerkQ4VxOuq10dn/abITzLyaZzMw30KXWp5pxKXOLtxFAgMBAAE=\n"
+"-----END RSA PUBLIC KEY-----\n"
+"dir-key-crosscert\n"
+"-----BEGIN ID SIGNATURE-----\n"
+"FTBJNR/Hlt4T53yUMp1r/QCSMCpkHJCbYBT0R0pvYqhqFfYN5qHRSICRXaFFImIF\n"
+"0DGWmwRza6DxPKNzkm5/b7I0de9zJW1jNNdQAQK5xppAtQcAafRdu8cBonnmh9KX\n"
+"k1NrAK/X00FYywju3yl/SxCn1GddVNkHYexEudmJMPM=\n"
+"-----END ID SIGNATURE-----\n"
+"dir-key-certification\n"
+"-----BEGIN SIGNATURE-----\n"
+"pjWguLFBfELZDc6DywL6Do21SCl7LcutfpM92MEn4WYeSNcTXNR6lRX7reOEJk4e\n"
+"NwEaMt+Hl7slgeR5wjnW3OmMmRPZK9bquNWbfD+sAOV9bRFZTpXIdleAQFPlwvMF\n"
+"z/Gzwspzn4i2Yh6hySShrctMmW8YL3OM8LsBXzBhp/rG2uHlsxmIsc13DA6HWt61\n"
+"ffY72uNE6KckDGsQ4wPGP9q69y6g+X+TNio1KPbsILbePv6EjbO+rS8FiS4njPlg\n"
+"SPYry1RaUvxzxTkswIzdE1tjJrUiqpbWlTGxrH9N4OszoLm45Pc784KLULrjKIoi\n"
+"Q+vRsGrcMBAa+kDowWU6H1ryKR7KOhzRTcf2uqLE/W3ezaRwmOG+ETmoVFwbhk2X\n"
+"OlbXEM9fWP+INvFkr6Z93VYL2jGkCjV7e3xXmre/Lb92fUcYi6t5dwzfV8gJnIoG\n"
+"eCHd0K8NrQK0ipVk/7zcPDKOPeo9Y5aj/f6X/pDHtb+Dd5sT+l82G/Tqy4DIYUYR\n"
+"-----END SIGNATURE-----\n"
+"r router2 AwMDAwMDAwMDAwMDAwMDAwMDAwM Tk5OTk5OTk5OTk5OTk5OTk5OTk4 2015-09-02 19:09:15 153.0.136.1 443 8000\n"
+"s Running V2Dir\n"
+"v 0.1.2.14\n"
+"w Bandwidth=30 Measured=30\n"
+"p reject 1-65535\n"
+"id ed25519 none\n"
+"m 9,10,11,12,13,14,15,16,17 sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa0\n"
+"r router1 BQUFBQUFBQUFBQUFBQUFBQUFBQU TU1NTU1NTU1NTU1NTU1NTU1NTU0 2015-09-02 19:17:35 153.0.153.1 443 0\n"
+"a [1:2:3::4]:4711\n"
+"s Exit Fast Guard Running Stable Valid\n"
+"v 0.2.0.5\n"
+"w Bandwidth=120 Measured=120\n"
+"p reject 1-65535\n"
+"id ed25519 none\n"
+"m 9,10,11,12,13,14,15,16,17 sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa1\n"
+"r router3 MzMzMzMzMzMzMzMzMzMzMzMzMzM T09PT09PT09PT09PT09PT09PT08 2015-09-02 19:17:35 170.0.153.1 400 9999\n"
+"s Authority Exit Fast Guard Running Stable V2Dir Valid\n"
+"v 0.1.0.3\n"
+"w Bandwidth=120\n"
+"p reject 1-65535\n"
+"id ed25519 none\n"
+"m 9,10,11,12,13,14,15,16,17 "
+"sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa2\n"
+"r router4 NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ Ly8vLy8vLy8vLy8vLy8vLy8vLy8 2015-09-02 19:17:35 192.0.2.3 500 1999\n"
+"s Running V2Dir\n"
+"v 0.1.6.3\n"
+"w Bandwidth=30\n"
+"p reject 1-65535\n"
+"id ed25519 none\n"
+"m 9,10,11,12,13,14,15,16,17 sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa3\n"
+"directory-footer\n"
+"directory-signature D867ACF56A9D229B35C25F0090BC9867E906BE69 CBF56A83368A5150F1A9AAADAFB4D77F8C4170E2\n"
+"-----BEGIN SIGNATURE-----\n"
+"AHiWcHe+T3XbnlQqvqSAk6RY3XmEy1+hM2u9Xk6BNi7BpQkEQM1f0vzRpgn5Dnf2\n"
+"TXQWGUq9Z7jdSVnzWT3xqPA4zjw6eZkj+DKUtwq+oEDZGlf8eHTFmr0NAWfwZbk9\n"
+"NAjbMTUXUP37N2XAZwkoCWwFCrrfMwXrL7OhZbj7ifo=\n"
+"-----END SIGNATURE-----\n";
+