aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/include.am2
-rw-r--r--src/test/rend_test_helpers.c16
-rw-r--r--src/test/rend_test_helpers.h1
-rw-r--r--src/test/test.c1
-rw-r--r--src/test/test.h1
-rw-r--r--src/test/test_connection.c93
-rw-r--r--src/test/test_connection.h13
-rw-r--r--src/test/test_helpers.c96
-rw-r--r--src/test/test_helpers.h9
-rw-r--r--src/test/test_hs_client.c286
-rw-r--r--src/test/test_hs_service.c94
-rw-r--r--src/test/test_rendcache.c16
12 files changed, 514 insertions, 114 deletions
diff --git a/src/test/include.am b/src/test/include.am
index 29ba1ce7c9..e7a2e0278b 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -115,6 +115,7 @@ src_test_test_SOURCES = \
src/test/test_extorport.c \
src/test/test_hs.c \
src/test/test_hs_service.c \
+ src/test/test_hs_client.c \
src/test/test_hs_intropoint.c \
src/test/test_handles.c \
src/test/test_hs_cache.c \
@@ -270,6 +271,7 @@ noinst_HEADERS+= \
src/test/test.h \
src/test/test_helpers.h \
src/test/test_dir_common.h \
+ src/test/test_connection.h \
src/test/test_descriptors.inc \
src/test/example_extrainfo.inc \
src/test/failing_routerdescs.inc \
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
index f7880046fb..095bfecf21 100644
--- a/src/test/rend_test_helpers.c
+++ b/src/test/rend_test_helpers.c
@@ -71,3 +71,19 @@ create_descriptor(rend_service_descriptor_t **generated, char **service_id,
crypto_pk_free(pk2);
}
+rend_data_t *
+mock_rend_data(const char *onion_address)
+{
+ rend_data_v2_t *v2_data = tor_malloc_zero(sizeof(*v2_data));
+ rend_data_t *rend_query = &v2_data->base_;
+ rend_query->version = 2;
+
+ strlcpy(v2_data->onion_address, onion_address,
+ sizeof(v2_data->onion_address));
+ v2_data->auth_type = REND_NO_AUTH;
+ rend_query->hsdirs_fp = smartlist_new();
+ smartlist_add(rend_query->hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa",
+ DIGEST_LEN));
+ return rend_query;
+}
+
diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h
index 486adba436..6f0ef114de 100644
--- a/src/test/rend_test_helpers.h
+++ b/src/test/rend_test_helpers.h
@@ -10,6 +10,7 @@ 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);
+rend_data_t *mock_rend_data(const char *onion_address);
#endif
diff --git a/src/test/test.c b/src/test/test.c
index 68f5f90fd7..31b3db3a4f 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1215,6 +1215,7 @@ struct testgroup_t testgroups[] = {
{ "hs_cache/", hs_cache },
{ "hs_descriptor/", hs_descriptor },
{ "hs_service/", hs_service_tests },
+ { "hs_client/", hs_client_tests },
{ "hs_intropoint/", hs_intropoint_tests },
{ "introduce/", introduce_tests },
{ "keypin/", keypin_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 6abaf39e6f..4de0da99fb 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -209,6 +209,7 @@ extern struct testcase_t hs_tests[];
extern struct testcase_t hs_cache[];
extern struct testcase_t hs_descriptor[];
extern struct testcase_t hs_service_tests[];
+extern struct testcase_t hs_client_tests[];
extern struct testcase_t hs_intropoint_tests[];
extern struct testcase_t introduce_tests[];
extern struct testcase_t keypin_tests[];
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index 7e5193b203..f2529026f9 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -17,9 +17,8 @@
#include "rendcache.h"
#include "directory.h"
-static void test_conn_lookup_addr_helper(const char *address,
- int family,
- tor_addr_t *addr);
+#include "test_connection.h"
+#include "test_helpers.h"
static void * test_conn_get_basic_setup(const struct testcase_t *tc);
static int test_conn_get_basic_teardown(const struct testcase_t *tc,
@@ -62,48 +61,7 @@ static int test_conn_get_rsrc_teardown(const struct testcase_t *tc,
#define TEST_CONN_UNATTACHED_STATE (AP_CONN_STATE_CIRCUIT_WAIT)
#define TEST_CONN_ATTACHED_STATE (AP_CONN_STATE_CONNECT_WAIT)
-#define TEST_CONN_FD_INIT 50
-static int mock_connection_connect_sockaddr_called = 0;
-static int fake_socket_number = TEST_CONN_FD_INIT;
-
-static int
-mock_connection_connect_sockaddr(connection_t *conn,
- const struct sockaddr *sa,
- socklen_t sa_len,
- const struct sockaddr *bindaddr,
- socklen_t bindaddr_len,
- int *socket_error)
-{
- (void)sa_len;
- (void)bindaddr;
- (void)bindaddr_len;
-
- tor_assert(conn);
- tor_assert(sa);
- tor_assert(socket_error);
-
- mock_connection_connect_sockaddr_called++;
-
- conn->s = fake_socket_number++;
- tt_assert(SOCKET_OK(conn->s));
- /* We really should call tor_libevent_initialize() here. Because we don't,
- * we are relying on other parts of the code not checking if the_event_base
- * (and therefore event->ev_base) is NULL. */
- tt_assert(connection_add_connecting(conn) == 0);
-
- done:
- /* Fake "connected" status */
- return 1;
-}
-
-static int
-fake_close_socket(evutil_socket_t sock)
-{
- (void)sock;
- return 0;
-}
-
-static void
+void
test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr)
{
int rv = 0;
@@ -122,51 +80,6 @@ test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr)
tor_addr_make_null(addr, TEST_CONN_FAMILY);
}
-static connection_t *
-test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose)
-{
- connection_t *conn = NULL;
- tor_addr_t addr;
- int socket_err = 0;
- int in_progress = 0;
-
- MOCK(connection_connect_sockaddr,
- mock_connection_connect_sockaddr);
- MOCK(tor_close_socket, fake_close_socket);
-
- init_connection_lists();
-
- conn = connection_new(type, TEST_CONN_FAMILY);
- tt_assert(conn);
-
- test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
- tt_assert(!tor_addr_is_null(&addr));
-
- tor_addr_copy_tight(&conn->addr, &addr);
- conn->port = TEST_CONN_PORT;
- mock_connection_connect_sockaddr_called = 0;
- in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr,
- TEST_CONN_PORT, &socket_err);
- tt_assert(mock_connection_connect_sockaddr_called == 1);
- tt_assert(!socket_err);
- tt_assert(in_progress == 0 || in_progress == 1);
-
- /* fake some of the attributes so the connection looks OK */
- conn->state = state;
- conn->purpose = purpose;
- assert_connection_ok(conn, time(NULL));
-
- UNMOCK(connection_connect_sockaddr);
- UNMOCK(tor_close_socket);
- return conn;
-
- /* On failure */
- done:
- UNMOCK(connection_connect_sockaddr);
- UNMOCK(tor_close_socket);
- return NULL;
-}
-
static void *
test_conn_get_basic_setup(const struct testcase_t *tc)
{
diff --git a/src/test/test_connection.h b/src/test/test_connection.h
new file mode 100644
index 0000000000..392783b53b
--- /dev/null
+++ b/src/test/test_connection.h
@@ -0,0 +1,13 @@
+/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/** 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_PORT (12345)
+#define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345"
+#define TEST_CONN_FD_INIT 50
+
+void test_conn_lookup_addr_helper(const char *address,
+ int family, tor_addr_t *addr);
+
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 9fada5a675..22d9de3f5b 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -7,9 +7,14 @@
*/
#define ROUTERLIST_PRIVATE
+#define CONNECTION_PRIVATE
+#define MAIN_PRIVATE
+
#include "orconfig.h"
#include "or.h"
+#include "connection.h"
+#include "main.h"
#include "relay.h"
#include "routerlist.h"
#include "nodelist.h"
@@ -17,6 +22,7 @@
#include "test.h"
#include "test_helpers.h"
+#include "test_connection.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
DISABLE_GCC_WARNING(overlength-strings)
@@ -143,3 +149,93 @@ mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
return tor_addr_lookup__real(name, family, out);
}
+/*********** Helper funcs for making new connections/streams *****************/
+
+/* Helper for test_conn_get_connection() */
+static int
+fake_close_socket(evutil_socket_t sock)
+{
+ (void)sock;
+ return 0;
+}
+
+static int mock_connection_connect_sockaddr_called = 0;
+static int fake_socket_number = TEST_CONN_FD_INIT;
+
+/* Helper for test_conn_get_connection() */
+static int
+mock_connection_connect_sockaddr(connection_t *conn,
+ const struct sockaddr *sa,
+ socklen_t sa_len,
+ const struct sockaddr *bindaddr,
+ socklen_t bindaddr_len,
+ int *socket_error)
+{
+ (void)sa_len;
+ (void)bindaddr;
+ (void)bindaddr_len;
+
+ tor_assert(conn);
+ tor_assert(sa);
+ tor_assert(socket_error);
+
+ mock_connection_connect_sockaddr_called++;
+
+ conn->s = fake_socket_number++;
+ tt_assert(SOCKET_OK(conn->s));
+ /* We really should call tor_libevent_initialize() here. Because we don't,
+ * we are relying on other parts of the code not checking if the_event_base
+ * (and therefore event->ev_base) is NULL. */
+ tt_assert(connection_add_connecting(conn) == 0);
+
+ done:
+ /* Fake "connected" status */
+ return 1;
+}
+
+/** Create and return a new connection/stream */
+connection_t *
+test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose)
+{
+ connection_t *conn = NULL;
+ tor_addr_t addr;
+ int socket_err = 0;
+ int in_progress = 0;
+
+ MOCK(connection_connect_sockaddr,
+ mock_connection_connect_sockaddr);
+ MOCK(tor_close_socket, fake_close_socket);
+
+ init_connection_lists();
+
+ conn = connection_new(type, TEST_CONN_FAMILY);
+ tt_assert(conn);
+
+ test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
+ tt_assert(!tor_addr_is_null(&addr));
+
+ tor_addr_copy_tight(&conn->addr, &addr);
+ conn->port = TEST_CONN_PORT;
+ mock_connection_connect_sockaddr_called = 0;
+ in_progress = connection_connect(conn, TEST_CONN_ADDRESS_PORT, &addr,
+ TEST_CONN_PORT, &socket_err);
+ tt_assert(mock_connection_connect_sockaddr_called == 1);
+ tt_assert(!socket_err);
+ tt_assert(in_progress == 0 || in_progress == 1);
+
+ /* fake some of the attributes so the connection looks OK */
+ conn->state = state;
+ conn->purpose = purpose;
+ assert_connection_ok(conn, time(NULL));
+
+ UNMOCK(connection_connect_sockaddr);
+ UNMOCK(tor_close_socket);
+ return conn;
+
+ /* On failure */
+ done:
+ UNMOCK(connection_connect_sockaddr);
+ UNMOCK(tor_close_socket);
+ return NULL;
+}
+
diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h
index 4621631cc1..96a4b594eb 100644
--- a/src/test/test_helpers.h
+++ b/src/test/test_helpers.h
@@ -1,9 +1,11 @@
-/* Copyright (c) 2014-2017, The Tor Project, Inc. */
+/* Copyright (c) 2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_HELPERS_H
#define TOR_TEST_HELPERS_H
+#include "or.h"
+
const char *get_yesterday_date_str(void);
circuit_t * dummy_origin_circuit_new(int num_cells);
@@ -20,7 +22,10 @@ void connection_write_to_buf_mock(const char *string, size_t len,
int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
uint16_t family, tor_addr_t *out);
+connection_t *test_conn_get_connection(uint8_t state,
+ uint8_t type, uint8_t purpose);
+
extern const char TEST_DESCRIPTORS[];
-#endif
+#endif /* TOR_TEST_HELPERS_H */
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
new file mode 100644
index 0000000000..77fee88eda
--- /dev/null
+++ b/src/test/test_hs_client.c
@@ -0,0 +1,286 @@
+/* Copyright (c) 2016-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_hs_client.c
+ * \brief Test prop224 HS client functionality.
+ */
+
+#define CRYPTO_PRIVATE
+#define MAIN_PRIVATE
+#define TOR_CHANNEL_INTERNAL_
+#define CIRCUITBUILD_PRIVATE
+#define CIRCUITLIST_PRIVATE
+#define CONNECTION_PRIVATE
+
+#include "test.h"
+#include "test_helpers.h"
+#include "log_test_helpers.h"
+#include "rend_test_helpers.h"
+
+#include "config.h"
+#include "crypto.h"
+#include "channeltls.h"
+
+#include "hs_circuit.h"
+#include "hs_ident.h"
+#include "circuitlist.h"
+#include "circuitbuild.h"
+#include "connection.h"
+#include "connection_edge.h"
+
+static int
+mock_connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
+{
+ (void) ap_conn;
+ return 0;
+}
+
+/* Test helper function: Setup a circuit and a stream with the same hidden
+ * service destination, and put them in <b>circ_out</b> and
+ * <b>conn_out</b>. Make the stream wait for circuits to be established to the
+ * hidden service. */
+static int
+helper_get_circ_and_stream_for_test(origin_circuit_t **circ_out,
+ connection_t **conn_out,
+ int is_legacy)
+{
+ int retval;
+ channel_tls_t *n_chan=NULL;
+ rend_data_t *conn_rend_data = NULL;
+ origin_circuit_t *or_circ = NULL;
+ connection_t *conn = NULL;
+ ed25519_public_key_t service_pk;
+
+ /* Make a dummy connection stream and make it wait for our circuit */
+ conn = test_conn_get_connection(AP_CONN_STATE_CIRCUIT_WAIT,
+ CONN_TYPE_AP /* ??? */,
+ 0);
+ if (is_legacy) {
+ /* Legacy: Setup rend_data of stream */
+ char service_id[REND_SERVICE_ID_LEN_BASE32+1] = {0};
+ TO_EDGE_CONN(conn)->rend_data = mock_rend_data(service_id);
+ conn_rend_data = TO_EDGE_CONN(conn)->rend_data;
+ } else {
+ /* prop224: Setup hs conn identifier on the stream */
+ ed25519_secret_key_t sk;
+ tt_int_op(0, OP_EQ, ed25519_secret_key_generate(&sk, 0));
+ tt_int_op(0, OP_EQ, ed25519_public_key_generate(&service_pk, &sk));
+
+ /* Setup hs_conn_identifier of stream */
+ TO_EDGE_CONN(conn)->hs_ident = hs_ident_edge_conn_new(&service_pk);
+ }
+
+ /* Make it wait for circuit */
+ connection_ap_mark_as_pending_circuit(TO_ENTRY_CONN(conn));
+
+ /* This is needed to silence a BUG warning from
+ connection_edge_update_circuit_isolation() */
+ TO_ENTRY_CONN(conn)->original_dest_address =
+ tor_strdup(TO_ENTRY_CONN(conn)->socks_request->address);
+
+ /****************************************************/
+
+ /* Now make dummy circuit */
+ or_circ = origin_circuit_new();
+
+ or_circ->base_.purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
+
+ or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ or_circ->build_state->is_internal = 1;
+
+ if (is_legacy) {
+ /* Legacy: Setup rend data and final cpath */
+ or_circ->build_state->pending_final_cpath =
+ tor_malloc_zero(sizeof(crypt_path_t));
+ or_circ->build_state->pending_final_cpath->magic = CRYPT_PATH_MAGIC;
+ or_circ->build_state->pending_final_cpath->rend_dh_handshake_state =
+ crypto_dh_new(DH_TYPE_REND);
+ tt_assert(
+ or_circ->build_state->pending_final_cpath->rend_dh_handshake_state);
+ retval = crypto_dh_generate_public(
+ or_circ->build_state->pending_final_cpath->rend_dh_handshake_state);
+ tt_int_op(retval, ==, 0);
+ or_circ->rend_data = rend_data_dup(conn_rend_data);
+ } else {
+ /* prop224: Setup hs ident on the circuit */
+ or_circ->hs_ident = hs_ident_circuit_new(&service_pk,
+ HS_IDENT_CIRCUIT_RENDEZVOUS);
+ }
+
+ TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN;
+
+ /* fake n_chan */
+ n_chan = tor_malloc_zero(sizeof(channel_tls_t));
+ n_chan->base_.global_identifier = 1;
+ or_circ->base_.n_chan = &(n_chan->base_);
+
+ *circ_out = or_circ;
+ *conn_out = conn;
+
+ return 0;
+
+ done:
+ /* something failed */
+ return -1;
+}
+
+/* Test: Ensure that setting up legacy e2e rendezvous circuits works
+ * correctly. */
+static void
+test_e2e_rend_circuit_setup_legacy(void *arg)
+{
+ int retval;
+ origin_circuit_t *or_circ = NULL;
+ connection_t *conn = NULL;
+
+ (void) arg;
+
+ /** In this test we create a v2 legacy HS stream and a circuit with the same
+ * hidden service destination. We make the stream wait for circuits to be
+ * established to the hidden service, and then we complete the circuit using
+ * the hs_circuit_setup_e2e_rend_circ_legacy_client() function. We then
+ * check that the end-to-end cpath was setup correctly and that the stream
+ * was attached to the circuit as expected. */
+
+ MOCK(connection_ap_handshake_send_begin,
+ mock_connection_ap_handshake_send_begin);
+
+ /* Setup */
+ retval = helper_get_circ_and_stream_for_test( &or_circ, &conn, 1);
+ tt_int_op(retval, OP_EQ, 0);
+ tt_assert(or_circ);
+ tt_assert(conn);
+
+ /* Check number of hops */
+ retval = cpath_get_n_hops(&or_circ->cpath);
+ tt_int_op(retval, ==, 0);
+
+ /* Check that our stream is not attached on any circuits */
+ tt_assert(!TO_EDGE_CONN(conn)->on_circuit);
+
+ /********************************************** */
+
+ /* Make a good RENDEZVOUS1 cell body because it needs to pass key exchange
+ * digest verification... */
+ uint8_t rend_cell_body[DH_KEY_LEN+DIGEST_LEN] = {2};
+ {
+ char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN];
+ crypto_dh_t *dh_state =
+ or_circ->build_state->pending_final_cpath->rend_dh_handshake_state;
+ /* compute and overwrite digest of cell body with the right value */
+ retval = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh_state,
+ (char*)rend_cell_body, DH_KEY_LEN,
+ keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN);
+ tt_int_op(retval, OP_GT, 0);
+ memcpy(rend_cell_body+DH_KEY_LEN, keys, DIGEST_LEN);
+ }
+
+ /* Setup the circuit */
+ retval = hs_circuit_setup_e2e_rend_circ_legacy_client(or_circ,
+ rend_cell_body);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /**********************************************/
+
+ /* See that a hop was added to the circuit's cpath */
+ retval = cpath_get_n_hops(&or_circ->cpath);
+ tt_int_op(retval, OP_EQ, 1);
+
+ /* Check the digest algo */
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest),
+ OP_EQ, DIGEST_SHA1);
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest),
+ OP_EQ, DIGEST_SHA1);
+ tt_assert(or_circ->cpath->f_crypto);
+ tt_assert(or_circ->cpath->b_crypto);
+
+ /* Ensure that circ purpose was changed */
+ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED);
+
+ /* Test that stream got attached */
+ tt_ptr_op(TO_EDGE_CONN(conn)->on_circuit, OP_EQ, TO_CIRCUIT(or_circ));
+
+ done:
+ connection_free_(conn);
+ tor_free(TO_CIRCUIT(or_circ)->n_chan);
+ circuit_free(TO_CIRCUIT(or_circ));
+}
+
+/* Test: Ensure that setting up v3 rendezvous circuits works correctly. */
+static void
+test_e2e_rend_circuit_setup(void *arg)
+{
+ uint8_t ntor_key_seed[DIGEST256_LEN] = {0};
+ origin_circuit_t *or_circ;
+ int retval;
+ connection_t *conn = NULL;
+
+ (void) arg;
+
+ /** In this test we create a prop224 v3 HS stream and a circuit with the same
+ * hidden service destination. We make the stream wait for circuits to be
+ * established to the hidden service, and then we complete the circuit using
+ * the hs_circuit_setup_e2e_rend_circ() function. We then check that the
+ * end-to-end cpath was setup correctly and that the stream was attached to
+ * the circuit as expected. */
+
+ MOCK(connection_ap_handshake_send_begin,
+ mock_connection_ap_handshake_send_begin);
+
+ /* Setup */
+ retval = helper_get_circ_and_stream_for_test( &or_circ, &conn, 0);
+ tt_int_op(retval, OP_EQ, 0);
+ tt_assert(or_circ);
+ tt_assert(conn);
+
+ /* Check number of hops: There should be no hops yet to this circ */
+ retval = cpath_get_n_hops(&or_circ->cpath);
+ tt_int_op(retval, ==, 0);
+ tt_assert(!or_circ->cpath);
+
+ /* Check that our stream is not attached on any circuits */
+ tt_assert(!TO_EDGE_CONN(conn)->on_circuit);
+
+ /**********************************************/
+
+ /* Setup the circuit */
+ retval = hs_circuit_setup_e2e_rend_circ(or_circ,
+ ntor_key_seed, sizeof(ntor_key_seed),
+ 0);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /**********************************************/
+
+ /* See that a hop was added to the circuit's cpath */
+ retval = cpath_get_n_hops(&or_circ->cpath);
+ tt_int_op(retval, OP_EQ, 1);
+
+ /* Check that the crypt path has prop224 algorithm parameters */
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest),
+ OP_EQ, DIGEST_SHA3_256);
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest),
+ OP_EQ, DIGEST_SHA3_256);
+ tt_assert(or_circ->cpath->f_crypto);
+ tt_assert(or_circ->cpath->b_crypto);
+
+ /* Ensure that circ purpose was changed */
+ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED);
+
+ /* Test that stream got attached */
+ tt_ptr_op(TO_EDGE_CONN(conn)->on_circuit, OP_EQ, TO_CIRCUIT(or_circ));
+
+ done:
+ connection_free_(conn);
+ tor_free(TO_CIRCUIT(or_circ)->n_chan);
+ circuit_free(TO_CIRCUIT(or_circ));
+}
+
+struct testcase_t hs_client_tests[] = {
+ { "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy,
+ TT_FORK, NULL, NULL },
+ { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup,
+ TT_FORK, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index fcfb3b992d..17772f1df0 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -6,20 +6,34 @@
* \brief Test hidden service functionality.
*/
+#define CIRCUITBUILD_PRIVATE
+#define CIRCUITLIST_PRIVATE
+#define CONNECTION_PRIVATE
+#define CRYPTO_PRIVATE
#define HS_COMMON_PRIVATE
-#define HS_SERVICE_PRIVATE
#define HS_INTROPOINT_PRIVATE
+#define MAIN_PRIVATE
+#define TOR_CHANNEL_INTERNAL_
#include "test.h"
#include "log_test_helpers.h"
-#include "crypto.h"
-
-#include "hs/cell_establish_intro.h"
+#include "rend_test_helpers.h"
+
+#include "or.h"
+#include "channeltls.h"
+#include "circuitbuild.h"
+#include "circuitlist.h"
+#include "circuituse.h"
+#include "config.h"
+#include "connection.h"
+#include "hs_circuit.h"
#include "hs_common.h"
-#include "hs_service.h"
+#include "hs_ident.h"
#include "hs_intropoint.h"
-
#include "hs_ntor.h"
+#include "hs_service.h"
+#include "main.h"
+#include "rendservice.h"
/** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we
* parse it from the receiver side. */
@@ -235,6 +249,72 @@ test_time_period(void *arg)
;
}
+/* Test: Ensure that setting up rendezvous circuits works correctly. */
+static void
+test_e2e_rend_circuit_setup(void *arg)
+{
+ ed25519_public_key_t service_pk;
+ origin_circuit_t *or_circ;
+ int retval;
+
+ /** In this test we create a v3 prop224 service-side rendezvous circuit.
+ * We simulate an HS ntor key exchange with a client, and check that
+ * the circuit was setup correctly and is ready to accept rendezvous data */
+
+ (void) arg;
+
+ /* Now make dummy circuit */
+ {
+ or_circ = origin_circuit_new();
+
+ or_circ->base_.purpose = CIRCUIT_PURPOSE_S_CONNECT_REND;
+
+ or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ or_circ->build_state->is_internal = 1;
+
+ /* prop224: Setup hs conn identifier on the stream */
+ ed25519_secret_key_t sk;
+ tt_int_op(0, OP_EQ, ed25519_secret_key_generate(&sk, 0));
+ tt_int_op(0, OP_EQ, ed25519_public_key_generate(&service_pk, &sk));
+
+ or_circ->hs_ident = hs_ident_circuit_new(&service_pk,
+ HS_IDENT_CIRCUIT_RENDEZVOUS);
+
+ TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN;
+ }
+
+ /* Check number of hops */
+ retval = cpath_get_n_hops(&or_circ->cpath);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Setup the circuit: do the ntor key exchange */
+ {
+ uint8_t ntor_key_seed[DIGEST256_LEN] = {2};
+ retval = hs_circuit_setup_e2e_rend_circ(or_circ,
+ ntor_key_seed, sizeof(ntor_key_seed),
+ 1);
+ tt_int_op(retval, OP_EQ, 0);
+ }
+
+ /* See that a hop was added to the circuit's cpath */
+ retval = cpath_get_n_hops(&or_circ->cpath);
+ tt_int_op(retval, OP_EQ, 1);
+
+ /* Check the digest algo */
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->f_digest),
+ OP_EQ, DIGEST_SHA3_256);
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->b_digest),
+ OP_EQ, DIGEST_SHA3_256);
+ tt_assert(or_circ->cpath->f_crypto);
+ tt_assert(or_circ->cpath->b_crypto);
+
+ /* Ensure that circ purpose was changed */
+ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED);
+
+ done:
+ circuit_free(TO_CIRCUIT(or_circ));
+}
+
struct testcase_t hs_service_tests[] = {
{ "gen_establish_intro_cell", test_gen_establish_intro_cell, TT_FORK,
NULL, NULL },
@@ -244,6 +324,8 @@ struct testcase_t hs_service_tests[] = {
NULL, NULL },
{ "time_period", test_time_period, TT_FORK,
NULL, NULL },
+ { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK,
+ NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c
index feba8f664e..c1c178930a 100644
--- a/src/test/test_rendcache.c
+++ b/src/test/test_rendcache.c
@@ -21,22 +21,6 @@ static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + \
REND_CACHE_MAX_SKEW + 60);
static const int TIME_IN_THE_FUTURE = REND_CACHE_MAX_SKEW + 60;
-static rend_data_t *
-mock_rend_data(const char *onion_address)
-{
- rend_data_v2_t *v2_data = tor_malloc_zero(sizeof(*v2_data));
- rend_data_t *rend_query = &v2_data->base_;
- rend_query->version = 2;
-
- strlcpy(v2_data->onion_address, onion_address,
- sizeof(v2_data->onion_address));
- v2_data->auth_type = REND_NO_AUTH;
- rend_query->hsdirs_fp = smartlist_new();
- smartlist_add(rend_query->hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa",
- DIGEST_LEN));
- return rend_query;
-}
-
static void
test_rend_cache_lookup_entry(void *data)
{