aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2020-01-06 13:41:20 -0500
committerNick Mathewson <nickm@torproject.org>2020-01-06 13:41:20 -0500
commit1b63eea66cbb8793a3cff05de8d856ce3b93fc17 (patch)
tree2cf4f6ff12522ed24a610b3acab0b107f73b1977 /src/test
parent9276c07a916e4dc3b159c95c578e43be102f26e6 (diff)
parent14d781fff6bd88c4e0cd5b741629c3e79c8612d9 (diff)
downloadtor-1b63eea66cbb8793a3cff05de8d856ce3b93fc17.tar.gz
tor-1b63eea66cbb8793a3cff05de8d856ce3b93fc17.zip
Merge branch 'haxxpop/tcp_proxy_squashed' into tcp_proxy_squshed_and_merged
Diffstat (limited to 'src/test')
-rw-r--r--src/test/include.am1
-rw-r--r--src/test/test.c1
-rw-r--r--src/test/test.h1
-rw-r--r--src/test/test_config.c47
-rw-r--r--src/test/test_connection.c96
-rw-r--r--src/test/test_connection.h1
-rw-r--r--src/test/test_helpers.c81
-rw-r--r--src/test/test_helpers.h3
-rw-r--r--src/test/test_options.c9
-rw-r--r--src/test/test_proto_haproxy.c66
10 files changed, 300 insertions, 6 deletions
diff --git a/src/test/include.am b/src/test/include.am
index 94352c8644..3433e848ea 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -190,6 +190,7 @@ src_test_test_SOURCES += \
src/test/test_process_descs.c \
src/test/test_prob_distr.c \
src/test/test_procmon.c \
+ src/test/test_proto_haproxy.c \
src/test/test_proto_http.c \
src/test/test_proto_misc.c \
src/test/test_protover.c \
diff --git a/src/test/test.c b/src/test/test.c
index 292082d4fb..f0409f0dce 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -739,6 +739,7 @@ struct testgroup_t testgroups[] = {
{ "prob_distr/", prob_distr_tests },
{ "procmon/", procmon_tests },
{ "process/", process_tests },
+ { "proto/haproxy/", proto_haproxy_tests },
{ "proto/http/", proto_http_tests },
{ "proto/misc/", proto_misc_tests },
{ "protover/", protover_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 45c22d70f7..d0728a2d88 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -262,6 +262,7 @@ extern struct testcase_t slow_stochastic_prob_distr_tests[];
extern struct testcase_t procmon_tests[];
extern struct testcase_t process_tests[];
extern struct testcase_t process_descs_tests[];
+extern struct testcase_t proto_haproxy_tests[];
extern struct testcase_t proto_http_tests[];
extern struct testcase_t proto_misc_tests[];
extern struct testcase_t protover_tests[];
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 8f705da7e0..fb6958565c 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -676,6 +676,52 @@ transport_is_needed_mock(const char *transport_name)
return transport_is_needed_mock_return;
}
+static void
+test_config_parse_tcp_proxy_line(void *arg)
+{
+ (void)arg;
+
+ int ret;
+ char *msg = NULL;
+ or_options_t *options = get_options_mutable();
+
+ /* Bad TCPProxy line - too short. */
+ ret = parse_tcp_proxy_line("haproxy", options, &msg);
+ /* Return error. */
+ tt_int_op(ret, OP_EQ, -1);
+ /* Correct error message. */
+ tt_str_op(msg, OP_EQ, "TCPProxy has no address/port. Please fix.");
+ /* Free error message. */
+ tor_free(msg);
+
+ /* Bad TCPProxy line - unsupported protocol. */
+ ret = parse_tcp_proxy_line("unsupported 95.216.163.36:443", options, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ, "TCPProxy protocol is not supported. Currently the "
+ "only supported protocol is 'haproxy'. Please fix.");
+ tor_free(msg);
+
+ /* Bad TCPProxy line - unparsable address/port. */
+ ret = parse_tcp_proxy_line("haproxy 95.216.163.36/443", options, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ, "TCPProxy address/port failed to parse or resolve. "
+ "Please fix.");
+ tor_free(msg);
+
+ /* Good TCPProxy line - ipv4. */
+ ret = parse_tcp_proxy_line("haproxy 95.216.163.36:443", options, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(options->TCPProxyProtocol, OP_EQ, TCP_PROXY_PROTOCOL_HAPROXY);
+ /* Correct the address. */
+ tt_assert(tor_addr_eq_ipv4h(&options->TCPProxyAddr, 0x5fd8a324));
+ tt_int_op(options->TCPProxyPort, OP_EQ, 443);
+ tor_free(msg);
+
+ done:
+ ;
+}
+
/**
* Test parsing for the ClientTransportPlugin and ServerTransportPlugin config
* options.
@@ -6129,6 +6175,7 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(parse_bridge_line, 0),
CONFIG_TEST(parse_transport_options_line, 0),
CONFIG_TEST(parse_transport_plugin_line, TT_FORK),
+ CONFIG_TEST(parse_tcp_proxy_line, TT_FORK),
CONFIG_TEST(check_or_create_data_subdir, TT_FORK),
CONFIG_TEST(write_to_data_subdir, TT_FORK),
CONFIG_TEST(fix_my_family, 0),
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index 0d28276702..7369981284 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -10,6 +10,7 @@
#include "core/or/or.h"
#include "test/test.h"
+#include "app/config/or_options_st.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "feature/hs/hs_common.h"
@@ -312,6 +313,25 @@ test_conn_download_status_teardown(const struct testcase_t *tc, void *arg)
return rv;
}
+static void *
+test_conn_proxy_connect_setup(const struct testcase_t *tc)
+{
+ return test_conn_get_proxy_or_connection(*(unsigned int *)tc->setup_data);
+}
+
+static int
+test_conn_proxy_connect_teardown(const struct testcase_t *tc, void *arg)
+{
+ (void)tc;
+ or_connection_t *conn = arg;
+
+ tt_assert(conn);
+ assert_connection_ok(&conn->base_, time(NULL));
+
+ done:
+ return 1;
+}
+
/* Like connection_ap_make_link(), but does much less */
static connection_t *
test_conn_get_linked_connection(connection_t *l_conn, uint8_t state)
@@ -360,6 +380,10 @@ static struct testcase_setup_t test_conn_download_status_st = {
test_conn_download_status_setup, test_conn_download_status_teardown
};
+static struct testcase_setup_t test_conn_proxy_connect_st = {
+ test_conn_proxy_connect_setup, test_conn_proxy_connect_teardown
+};
+
static void
test_conn_get_basic(void *arg)
{
@@ -788,6 +812,64 @@ test_conn_download_status(void *arg)
/* the teardown function removes all the connections in the global list*/;
}
+static void
+test_conn_https_proxy_connect(void *arg)
+{
+ size_t sz;
+ char *buf = NULL;
+ or_connection_t *conn = arg;
+
+ MOCK(connection_or_change_state, mock_connection_or_change_state);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_HTTPS_WANT_CONNECT_OK);
+
+ buf = buf_get_contents(conn->base_.outbuf, &sz);
+ tt_str_op(buf, OP_EQ, "CONNECT 127.0.0.1:12345 HTTP/1.0\r\n\r\n");
+
+ done:
+ UNMOCK(connection_or_change_state);
+ tor_free(buf);
+}
+
+static int handshake_start_called = 0;
+
+static int
+handshake_start(or_connection_t *conn, int receiving)
+{
+ (void)receiving;
+
+ tor_assert(conn);
+
+ handshake_start_called = 1;
+ return 0;
+}
+
+static void
+test_conn_haproxy_proxy_connect(void *arg)
+{
+ size_t sz;
+ char *buf = NULL;
+ or_connection_t *conn = arg;
+
+ MOCK(connection_or_change_state, mock_connection_or_change_state);
+ MOCK(connection_tls_start_handshake, handshake_start);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_HAPROXY_WAIT_FOR_FLUSH);
+
+ buf = buf_get_contents(conn->base_.outbuf, &sz);
+ tt_str_op(buf, OP_EQ, "PROXY TCP4 0.0.0.0 127.0.0.1 0 12345\r\n");
+
+ connection_or_finished_flushing(conn);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_CONNECTED);
+ tt_int_op(handshake_start_called, OP_EQ, 1);
+
+ done:
+ UNMOCK(connection_or_change_state);
+ UNMOCK(connection_tls_start_handshake);
+ tor_free(buf);
+}
+
static node_t test_node;
static node_t *
@@ -890,14 +972,24 @@ test_failed_orconn_tracker(void *arg)
{ #name "_" #arg, test_conn_##name, fork, &setup, (void *)arg }
#endif /* !defined(COCCI) */
+static const unsigned int PROXY_CONNECT_ARG = PROXY_CONNECT;
+static const unsigned int PROXY_HAPROXY_ARG = PROXY_HAPROXY;
+
struct testcase_t connection_tests[] = {
CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st),
CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st),
CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st),
- CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
+
+ CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
test_conn_download_status_st, FLAV_MICRODESC),
- CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
+ CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
test_conn_download_status_st, FLAV_NS),
+
+ CONNECTION_TESTCASE_ARG(https_proxy_connect, TT_FORK,
+ test_conn_proxy_connect_st, &PROXY_CONNECT_ARG),
+ CONNECTION_TESTCASE_ARG(haproxy_proxy_connect, TT_FORK,
+ test_conn_proxy_connect_st, &PROXY_HAPROXY_ARG),
+
//CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
{ "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_connection.h b/src/test/test_connection.h
index 40121e6d38..9efe31ebc6 100644
--- a/src/test/test_connection.h
+++ b/src/test/test_connection.h
@@ -7,6 +7,7 @@
/** Some constants used by test_connection and helpers */
#define TEST_CONN_FAMILY (AF_INET)
#define TEST_CONN_ADDRESS "127.0.0.1"
+#define TEST_CONN_ADDRESS_2 "127.0.0.2"
#define TEST_CONN_PORT (12345)
#define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345"
#define TEST_CONN_FD_INIT 50
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 29743a0d15..31bf1fcc2a 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -9,6 +9,7 @@
#define ROUTERLIST_PRIVATE
#define CONFIG_PRIVATE
#define CONNECTION_PRIVATE
+#define CONNECTION_OR_PRIVATE
#define MAINLOOP_PRIVATE
#include "orconfig.h"
@@ -19,6 +20,7 @@
#include "lib/confmgt/confmgt.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/mainloop/mainloop.h"
#include "feature/nodelist/nodelist.h"
@@ -33,6 +35,7 @@
#include "core/or/cell_st.h"
#include "core/or/connection_st.h"
+#include "core/or/or_connection_st.h"
#include "feature/nodelist/node_st.h"
#include "core/or/origin_circuit_st.h"
#include "feature/nodelist/routerlist_st.h"
@@ -194,6 +197,14 @@ fake_close_socket(tor_socket_t sock)
return 0;
}
+/* Helper for test_conn_get_proxy_or_connection() */
+void
+mock_connection_or_change_state(or_connection_t *conn, uint8_t state)
+{
+ tor_assert(conn);
+ conn->base_.state = state;
+}
+
static int mock_connection_connect_sockaddr_called = 0;
static int fake_socket_number = TEST_CONN_FD_INIT;
@@ -228,6 +239,76 @@ mock_connection_connect_sockaddr(connection_t *conn,
return 1;
}
+or_connection_t *
+test_conn_get_proxy_or_connection(unsigned int proxy_type)
+{
+ or_connection_t *conn = NULL;
+ tor_addr_t dst_addr;
+ tor_addr_t proxy_addr;
+ int socket_err = 0;
+ int in_progress = 0;
+
+ MOCK(connection_connect_sockaddr,
+ mock_connection_connect_sockaddr);
+ MOCK(connection_write_to_buf_impl_,
+ connection_write_to_buf_mock);
+ MOCK(connection_or_change_state,
+ mock_connection_or_change_state);
+ MOCK(tor_close_socket, fake_close_socket);
+
+ tor_init_connection_lists();
+
+ conn = or_connection_new(CONN_TYPE_OR, TEST_CONN_FAMILY);
+ tt_assert(conn);
+
+ /* Set up a destination address. */
+ test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY,
+ &dst_addr);
+ tt_assert(!tor_addr_is_null(&dst_addr));
+
+ conn->proxy_type = proxy_type;
+ conn->base_.proxy_state = PROXY_INFANT;
+
+ tor_addr_copy_tight(&conn->base_.addr, &dst_addr);
+ conn->base_.address = tor_addr_to_str_dup(&dst_addr);
+ conn->base_.port = TEST_CONN_PORT;
+
+ /* Set up a proxy address. */
+ test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY,
+ &proxy_addr);
+ tt_assert(!tor_addr_is_null(&proxy_addr));
+
+ conn->base_.state = OR_CONN_STATE_CONNECTING;
+
+ mock_connection_connect_sockaddr_called = 0;
+ in_progress = connection_connect(TO_CONN(conn), TEST_CONN_ADDRESS_PORT,
+ &proxy_addr, TEST_CONN_PORT, &socket_err);
+ tt_int_op(mock_connection_connect_sockaddr_called, OP_EQ, 1);
+ tt_assert(!socket_err);
+ tt_assert(in_progress == 0 || in_progress == 1);
+
+ assert_connection_ok(TO_CONN(conn), time(NULL));
+
+ in_progress = connection_or_finished_connecting(conn);
+ tt_int_op(in_progress, OP_EQ, 0);
+
+ assert_connection_ok(TO_CONN(conn), time(NULL));
+
+ UNMOCK(connection_connect_sockaddr);
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(connection_or_change_state);
+ UNMOCK(tor_close_socket);
+ return conn;
+
+ /* On failure */
+ done:
+ UNMOCK(connection_connect_sockaddr);
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(connection_or_change_state);
+ UNMOCK(tor_close_socket);
+ return NULL;
+}
+
/** Create and return a new connection/stream */
connection_t *
test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose)
diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h
index d82072bb34..d5a5417983 100644
--- a/src/test/test_helpers.h
+++ b/src/test/test_helpers.h
@@ -26,6 +26,9 @@ char *buf_get_contents(buf_t *buf, size_t *sz_out);
int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
uint16_t family, tor_addr_t *out);
+void mock_connection_or_change_state(or_connection_t *conn, uint8_t state);
+
+or_connection_t *test_conn_get_proxy_or_connection(unsigned int proxy_type);
connection_t *test_conn_get_connection(uint8_t state,
uint8_t type, uint8_t purpose);
or_options_t *helper_parse_options(const char *conf);
diff --git a/src/test/test_options.c b/src/test/test_options.c
index b99ae78932..ce05eb01f7 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -2807,7 +2807,7 @@ test_options_validate__proxy(void *ignored)
ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "You have configured more than one proxy type. "
- "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)");
tor_free(msg);
free_options_test_data(tdata);
@@ -2815,9 +2815,10 @@ test_options_validate__proxy(void *ignored)
mock_clean_saved_logs();
ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
- expect_log_msg("HTTPProxy configured, but no SOCKS "
- "proxy or HTTPS proxy configured. Watch out: this configuration "
- "will proxy unencrypted directory connections only.\n");
+ expect_log_msg("HTTPProxy configured, but no SOCKS proxy, "
+ "HTTPS proxy, or any other TCP proxy configured. Watch out: "
+ "this configuration will proxy unencrypted directory "
+ "connections only.\n");
tor_free(msg);
free_options_test_data(tdata);
diff --git a/src/test/test_proto_haproxy.c b/src/test/test_proto_haproxy.c
new file mode 100644
index 0000000000..653bf67e23
--- /dev/null
+++ b/src/test/test_proto_haproxy.c
@@ -0,0 +1,66 @@
+/* Copyright (c) 2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_proto_haproxy.c
+ * \brief Tests for our HAProxy protocol parser code
+ */
+
+#define PROTO_HAPROXY_PRIVATE
+
+#include "test/test.h"
+#include "core/proto/proto_haproxy.h"
+#include "test/log_test_helpers.h"
+
+static void
+test_format_proxy_header_line(void *arg)
+{
+ tor_addr_t addr;
+ tor_addr_port_t *addr_port = NULL;
+ char *output = NULL;
+
+ (void) arg;
+
+ /* IPv4 address. */
+ tor_addr_parse(&addr, "192.168.1.2");
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ tt_str_op(output, OP_EQ, "PROXY TCP4 0.0.0.0 192.168.1.2 0 8000\r\n");
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ /* IPv6 address. */
+ tor_addr_parse(&addr, "123:45:6789::5005:11");
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ tt_str_op(output, OP_EQ, "PROXY TCP6 :: 123:45:6789::5005:11 0 8000\r\n");
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ /* UNIX socket address. */
+ memset(&addr, 0, sizeof(addr));
+ addr.family = AF_UNIX;
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ /* If it's not an IPv4 or IPv6 address, haproxy_format_proxy_header_line
+ * must return NULL. */
+ tt_ptr_op(output, OP_EQ, NULL);
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ done:
+ tor_free(addr_port);
+ tor_free(output);
+}
+
+struct testcase_t proto_haproxy_tests[] = {
+ { "format_proxy_header_line", test_format_proxy_header_line, 0, NULL, NULL },
+
+ END_OF_TESTCASES
+};