#define CIRCUITBUILD_PRIVATE
#define CIRCUITLIST_PRIVATE
#define ENTRYNODES_PRIVATE
#include "core/or/or.h"
#include "test/test.h"
#include "test/test_helpers.h"
#include "test/log_test_helpers.h"
#define CONFIG_PRIVATE
#include "app/config/config.h"
#include "core/or/channel.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/onion.h"
#include "core/or/cell_st.h"
#include "core/or/cpath_build_state_st.h"
#include "core/or/extend_info_st.h"
#include "core/or/origin_circuit_st.h"
#include "core/or/or_circuit_st.h"
#include "feature/client/entrynodes.h"
#include "feature/nodelist/nodelist.h"
#include "feature/relay/circuitbuild_relay.h"
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
#include "feature/nodelist/node_st.h"
static smartlist_t dummy_nodes;
static extend_info_t dummy_ei;
static int
mock_count_acceptable_nodes(const smartlist_t *nodes, int direct)
{
(void)nodes;
return direct ? 1 : DEFAULT_ROUTE_LEN + 1;
}
static void
test_new_route_len_noexit(void *arg)
{
int r;
(void)arg;
MOCK(count_acceptable_nodes, mock_count_acceptable_nodes);
r = new_route_len(CIRCUIT_PURPOSE_C_GENERAL, NULL, &dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
r = new_route_len(CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT, NULL, &dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
r = new_route_len(CIRCUIT_PURPOSE_S_CONNECT_REND, NULL, &dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
done:
UNMOCK(count_acceptable_nodes);
}
static void
test_new_route_len_unsafe_exit(void *arg)
{
int r;
(void)arg;
MOCK(count_acceptable_nodes, mock_count_acceptable_nodes);
r = new_route_len(CIRCUIT_PURPOSE_C_GENERAL, &dummy_ei, &dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN + 1, OP_EQ, r);
r = new_route_len(CIRCUIT_PURPOSE_C_INTRODUCING, &dummy_ei, &dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN + 1, OP_EQ, r);
r = new_route_len(CIRCUIT_PURPOSE_S_CONNECT_REND, &dummy_ei, &dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN + 1, OP_EQ, r);
done:
UNMOCK(count_acceptable_nodes);
}
static void
test_new_route_len_safe_exit(void *arg)
{
int r;
(void)arg;
MOCK(count_acceptable_nodes, mock_count_acceptable_nodes);
r = new_route_len(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, &dummy_ei,
&dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
r = new_route_len(CIRCUIT_PURPOSE_TESTING, &dummy_ei, &dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN, OP_EQ, r);
done:
UNMOCK(count_acceptable_nodes);
}
static void
test_new_route_len_unhandled_exit(void *arg)
{
int r;
(void)arg;
#ifdef ALL_BUGS_ARE_FATAL
#if !defined(__COVERITY__) && !defined(__clang_analyzer__)
tt_skip();
#endif
#endif
MOCK(count_acceptable_nodes, mock_count_acceptable_nodes);
tor_capture_bugs_(1);
setup_full_capture_of_logs(LOG_WARN);
r = new_route_len(CIRCUIT_PURPOSE_CONTROLLER, &dummy_ei, &dummy_nodes);
tt_int_op(DEFAULT_ROUTE_LEN + 1, OP_EQ, r);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(exit_ei && !known_purpose)");
expect_single_log_msg_containing("Unhandled purpose");
expect_single_log_msg_containing("with a chosen exit; assuming routelen");
done:
teardown_capture_of_logs();
tor_end_capture_bugs_();
UNMOCK(count_acceptable_nodes);
}
static void
test_upgrade_from_guard_wait(void *arg)
{
circuit_t *circ = NULL;
origin_circuit_t *orig_circ = NULL;
entry_guard_t *guard = NULL;
smartlist_t *list = NULL;
(void) arg;
circ = dummy_origin_circuit_new(0);
orig_circ = TO_ORIGIN_CIRCUIT(circ);
tt_assert(orig_circ);
orig_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
circuit_set_state(circ, CIRCUIT_STATE_GUARD_WAIT);
guard = tor_malloc_zero(sizeof(*guard));
guard->in_selection = get_guard_selection_info();
orig_circ->guard_state =
circuit_guard_state_new(guard, GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD,
NULL);
circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
tt_int_op(circ->marked_for_close, OP_NE, 0);
list = circuit_find_circuits_to_upgrade_from_guard_wait();
tt_assert(!list);
done:
smartlist_free(list);
circuit_free(circ);
entry_guard_free_(guard);
}
static int server = 0;
static int
mock_server_mode(const or_options_t *options)
{
(void)options;
return server;
}
static void
test_circuit_extend_state_valid(void *arg)
{
(void)arg;
circuit_t *circ = tor_malloc_zero(sizeof(circuit_t));
server = 0;
MOCK(server_mode, mock_server_mode);
setup_full_capture_of_logs(LOG_INFO);
server = 0;
tt_int_op(circuit_extend_state_valid_helper(NULL), OP_EQ, -1);
expect_log_msg("Got an extend cell, but running as a client. Closing.\n");
mock_clean_saved_logs();
#ifndef ALL_BUGS_ARE_FATAL
tor_capture_bugs_(1);
server = 1;
tt_int_op(circuit_extend_state_valid_helper(NULL), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!circ))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
#endif
server = 1;
tt_int_op(circuit_extend_state_valid_helper(circ), OP_EQ, 0);
mock_clean_saved_logs();
server = 0;
tt_int_op(circuit_extend_state_valid_helper(circ), OP_EQ, -1);
expect_log_msg("Got an extend cell, but running as a client. Closing.\n");
mock_clean_saved_logs();
circ->n_chan = tor_malloc_zero(sizeof(channel_t));
server = 1;
tt_int_op(circuit_extend_state_valid_helper(circ), OP_EQ, -1);
expect_log_msg("n_chan already set. Bug/attack. Closing.\n");
mock_clean_saved_logs();
tor_free(circ->n_chan);
circ->n_hop = tor_malloc_zero(sizeof(extend_info_t));
server = 1;
tt_int_op(circuit_extend_state_valid_helper(circ), OP_EQ, -1);
expect_log_msg("conn to next hop already launched. Bug/attack. Closing.\n");
mock_clean_saved_logs();
tor_free(circ->n_hop);
done:
tor_end_capture_bugs_();
teardown_capture_of_logs();
UNMOCK(server_mode);
server = 0;
tor_free(circ->n_chan);
tor_free(circ->n_hop);
tor_free(circ);
}
static node_t *mocked_node = NULL;
static const node_t *
mock_node_get_by_id(const char *identity_digest)
{
(void)identity_digest;
return mocked_node;
}
static int mocked_supports_ed25519_link_authentication = 0;
static int
mock_node_supports_ed25519_link_authentication(const node_t *node,
int compatible_with_us)
{
(void)node;
(void)compatible_with_us;
return mocked_supports_ed25519_link_authentication;
}
static ed25519_public_key_t * mocked_ed25519_id = NULL;
static const ed25519_public_key_t *
mock_node_get_ed25519_id(const node_t *node)
{
(void)node;
return mocked_ed25519_id;
}
static void
test_circuit_extend_add_ed25519(void *arg)
{
(void)arg;
extend_cell_t *ec = tor_malloc_zero(sizeof(extend_cell_t));
extend_cell_t *old_ec = tor_malloc_zero(sizeof(extend_cell_t));
extend_cell_t *zero_ec = tor_malloc_zero(sizeof(extend_cell_t));
node_t *fake_node = tor_malloc_zero(sizeof(node_t));
ed25519_public_key_t *fake_ed25519_id = NULL;
fake_ed25519_id = tor_malloc_zero(sizeof(ed25519_public_key_t));
MOCK(node_get_by_id, mock_node_get_by_id);
MOCK(node_supports_ed25519_link_authentication,
mock_node_supports_ed25519_link_authentication);
MOCK(node_get_ed25519_id, mock_node_get_ed25519_id);
setup_full_capture_of_logs(LOG_INFO);
#ifndef ALL_BUGS_ARE_FATAL
tor_capture_bugs_(1);
tt_int_op(circuit_extend_add_ed25519_helper(NULL), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!ec))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
#endif
memcpy(old_ec, ec, sizeof(extend_cell_t));
tt_int_op(circuit_extend_add_ed25519_helper(ec), OP_EQ, -1);
expect_log_msg(
"Client asked me to extend without specifying an id_digest.\n");
tt_mem_op(ec, OP_EQ, old_ec, sizeof(extend_cell_t));
mock_clean_saved_logs();
memset(ec->node_id, 0xAA, sizeof(ec->node_id));
memcpy(old_ec, ec, sizeof(extend_cell_t));
tt_int_op(circuit_extend_add_ed25519_helper(ec), OP_EQ, 0);
tt_mem_op(&ec->ed_pubkey, OP_EQ, &zero_ec->ed_pubkey, sizeof(ec->ed_pubkey));
tt_mem_op(ec, OP_EQ, old_ec, sizeof(extend_cell_t));
mock_clean_saved_logs();
memset(ec->node_id, 0xAA, sizeof(ec->node_id));
memcpy(old_ec, ec, sizeof(extend_cell_t));
mocked_node = fake_node;
mocked_supports_ed25519_link_authentication = 1;
tt_int_op(circuit_extend_add_ed25519_helper(ec), OP_EQ, 0);
tt_mem_op(&ec->ed_pubkey, OP_EQ, &zero_ec->ed_pubkey, sizeof(ec->ed_pubkey));
tt_mem_op(ec, OP_EQ, old_ec, sizeof(extend_cell_t));
mock_clean_saved_logs();
mocked_node = NULL;
mocked_supports_ed25519_link_authentication = 0;
mocked_ed25519_id = NULL;
memset(fake_ed25519_id, 0x00, sizeof(ed25519_public_key_t));
memset(ec->node_id, 0xAA, sizeof(ec->node_id));
memcpy(old_ec, ec, sizeof(extend_cell_t));
mocked_supports_ed25519_link_authentication = 1;
memset(fake_ed25519_id, 0xEE, sizeof(ed25519_public_key_t));
mocked_ed25519_id = fake_ed25519_id;
tt_int_op(circuit_extend_add_ed25519_helper(ec), OP_EQ, 0);
tt_mem_op(&ec->ed_pubkey, OP_EQ, &zero_ec->ed_pubkey, sizeof(ec->ed_pubkey));
tt_mem_op(ec, OP_EQ, old_ec, sizeof(extend_cell_t));
mock_clean_saved_logs();
mocked_node = NULL;
mocked_supports_ed25519_link_authentication = 0;
mocked_ed25519_id = NULL;
memset(fake_ed25519_id, 0x00, sizeof(ed25519_public_key_t));
memset(ec->node_id, 0xAA, sizeof(ec->node_id));
memcpy(old_ec, ec, sizeof(extend_cell_t));
mocked_node = fake_node;
memset(fake_ed25519_id, 0xEE, sizeof(ed25519_public_key_t));
mocked_ed25519_id = fake_ed25519_id;
tt_int_op(circuit_extend_add_ed25519_helper(ec), OP_EQ, 0);
tt_mem_op(&ec->ed_pubkey, OP_EQ, &zero_ec->ed_pubkey, sizeof(ec->ed_pubkey));
tt_mem_op(ec, OP_EQ, old_ec, sizeof(extend_cell_t));
mock_clean_saved_logs();
mocked_node = NULL;
mocked_supports_ed25519_link_authentication = 0;
mocked_ed25519_id = NULL;
memset(fake_ed25519_id, 0x00, sizeof(ed25519_public_key_t));
memset(ec->node_id, 0xAA, sizeof(ec->node_id));
memcpy(old_ec, ec, sizeof(extend_cell_t));
mocked_node = fake_node;
mocked_supports_ed25519_link_authentication = 1;
memset(fake_ed25519_id, 0xEE, sizeof(ed25519_public_key_t));
mocked_ed25519_id = fake_ed25519_id;
tt_int_op(circuit_extend_add_ed25519_helper(ec), OP_EQ, 0);
tt_mem_op(&ec->ed_pubkey, OP_EQ, fake_ed25519_id, sizeof(ec->ed_pubkey));
memcpy(&ec->ed_pubkey, &old_ec->ed_pubkey, sizeof(ec->ed_pubkey));
tt_mem_op(ec, OP_EQ, old_ec, sizeof(extend_cell_t));
mock_clean_saved_logs();
mocked_node = NULL;
mocked_supports_ed25519_link_authentication = 0;
mocked_ed25519_id = NULL;
memset(fake_ed25519_id, 0x00, sizeof(ed25519_public_key_t));
memset(ec->node_id, 0xAA, sizeof(ec->node_id));
memcpy(old_ec, ec, sizeof(extend_cell_t));
mocked_node = fake_node;
mocked_supports_ed25519_link_authentication = 1;
memset(fake_ed25519_id, 0x00, sizeof(ed25519_public_key_t));
mocked_ed25519_id = fake_ed25519_id;
tt_int_op(circuit_extend_add_ed25519_helper(ec), OP_EQ, 0);
tt_mem_op(&ec->ed_pubkey, OP_EQ, fake_ed25519_id, sizeof(ec->ed_pubkey));
memcpy(&ec->ed_pubkey, &old_ec->ed_pubkey, sizeof(ec->ed_pubkey));
tt_mem_op(ec, OP_EQ, old_ec, sizeof(extend_cell_t));
mock_clean_saved_logs();
mocked_node = NULL;
mocked_supports_ed25519_link_authentication = 0;
mocked_ed25519_id = NULL;
memset(fake_ed25519_id, 0x00, sizeof(ed25519_public_key_t));
done:
UNMOCK(node_get_by_id);
UNMOCK(node_supports_ed25519_link_authentication);
UNMOCK(node_get_ed25519_id);
tor_end_capture_bugs_();
teardown_capture_of_logs();
tor_free(ec);
tor_free(old_ec);
tor_free(zero_ec);
tor_free(fake_ed25519_id);
tor_free(fake_node);
}
static or_options_t *mocked_options = NULL;
static const or_options_t *
mock_get_options(void)
{
return mocked_options;
}
#define PUBLIC_IPV4 "1.2.3.4"
#define INTERNAL_IPV4 "0.0.0.1"
#define PUBLIC_IPV6 "1234::cdef"
#define INTERNAL_IPV6 "::1"
#define VALID_PORT 0x1234
static void
test_circuit_extend_lspec_valid(void *arg)
{
(void)arg;
extend_cell_t *ec = tor_malloc_zero(sizeof(extend_cell_t));
channel_t *p_chan = tor_malloc_zero(sizeof(channel_t));
or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t));
circuit_t *circ = TO_CIRCUIT(or_circ);
or_options_t *fake_options = options_new();
MOCK(get_options, mock_get_options);
mocked_options = fake_options;
setup_full_capture_of_logs(LOG_INFO);
#ifndef ALL_BUGS_ARE_FATAL
tor_capture_bugs_(1);
tt_int_op(circuit_extend_lspec_valid_helper(NULL, circ), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!ec))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
tor_capture_bugs_(1);
tt_int_op(circuit_extend_lspec_valid_helper(ec, NULL), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!circ))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
tor_capture_bugs_(1);
tt_int_op(circuit_extend_lspec_valid_helper(NULL, NULL), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_GE, 0);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_LE, 2);
tor_end_capture_bugs_();
mock_clean_saved_logs();
#endif
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend to a zero destination port "
"or unspecified address '[scrubbed]'.\n");
mock_clean_saved_logs();
fake_options->SafeLogging_ = SAFELOG_SCRUB_NONE;
tor_addr_parse(&ec->orport_ipv4.addr, PUBLIC_IPV4);
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend to a zero destination port "
"or IPv4 address '1.2.3.4:0'.\n");
mock_clean_saved_logs();
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
ec->orport_ipv4.port = VALID_PORT;
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend to a zero destination port "
"or IPv4 address '0.0.0.0:4660'.\n");
mock_clean_saved_logs();
ec->orport_ipv4.port = 0;
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
tor_addr_parse(&ec->orport_ipv4.addr, INTERNAL_IPV4);
ec->orport_ipv4.port = VALID_PORT;
fake_options->ExtendAllowPrivateAddresses = 0;
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend "
"to a private IPv4 address '0.0.0.1'.\n");
mock_clean_saved_logs();
fake_options->ExtendAllowPrivateAddresses = 0;
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
tor_addr_parse(&ec->orport_ipv6.addr, PUBLIC_IPV6);
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend to a zero destination port "
"or IPv6 address '[1234::cdef]:0'.\n");
mock_clean_saved_logs();
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
ec->orport_ipv6.port = VALID_PORT;
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend to a zero destination port "
"or IPv6 address '[::]:4660'.\n");
mock_clean_saved_logs();
ec->orport_ipv4.port = 0;
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
tor_addr_parse(&ec->orport_ipv6.addr, INTERNAL_IPV6);
ec->orport_ipv6.port = VALID_PORT;
fake_options->ExtendAllowPrivateAddresses = 0;
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend "
"to a private IPv6 address '[::1]'.\n");
mock_clean_saved_logs();
fake_options->ExtendAllowPrivateAddresses = 0;
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
tor_addr_parse(&ec->orport_ipv4.addr, INTERNAL_IPV4);
ec->orport_ipv4.port = VALID_PORT;
tor_addr_parse(&ec->orport_ipv6.addr, INTERNAL_IPV6);
ec->orport_ipv6.port = VALID_PORT;
fake_options->ExtendAllowPrivateAddresses = 0;
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend "
"to a private IPv4 address '0.0.0.1'.\n");
expect_log_msg("Client asked me to extend "
"to a private IPv6 address '[::1]'.\n");
mock_clean_saved_logs();
fake_options->ExtendAllowPrivateAddresses = 0;
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
#ifndef ALL_BUGS_ARE_FATAL
tor_addr_parse(&ec->orport_ipv4.addr, INTERNAL_IPV4);
ec->orport_ipv4.port = VALID_PORT;
tor_addr_parse(&ec->orport_ipv6.addr, INTERNAL_IPV6);
ec->orport_ipv6.port = VALID_PORT;
fake_options->ExtendAllowPrivateAddresses = 1;
tor_capture_bugs_(1);
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(circ->magic != 0x98ABC04Fu))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
fake_options->ExtendAllowPrivateAddresses = 0;
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
tor_addr_parse(&ec->orport_ipv4.addr, INTERNAL_IPV4);
ec->orport_ipv4.port = VALID_PORT;
fake_options->ExtendAllowPrivateAddresses = 1;
tor_capture_bugs_(1);
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_GE, 0);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_LE, 1);
tor_end_capture_bugs_();
mock_clean_saved_logs();
fake_options->ExtendAllowPrivateAddresses = 0;
#endif
or_circ->base_.magic = OR_CIRCUIT_MAGIC;
#ifndef ALL_BUGS_ARE_FATAL
fake_options->ExtendAllowPrivateAddresses = 1;
tor_capture_bugs_(1);
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!p_chan))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
fake_options->ExtendAllowPrivateAddresses = 0;
tor_addr_parse(&ec->orport_ipv4.addr, PUBLIC_IPV4);
fake_options->ExtendAllowPrivateAddresses = 0;
tor_capture_bugs_(1);
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_GE, 0);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_LE, 1);
tor_end_capture_bugs_();
mock_clean_saved_logs();
fake_options->ExtendAllowPrivateAddresses = 0;
tor_addr_make_null(&ec->orport_ipv4.addr, AF_INET);
ec->orport_ipv4.port = 0x0000;
#endif
tor_addr_parse(&ec->orport_ipv4.addr, PUBLIC_IPV4);
ec->orport_ipv4.port = VALID_PORT;
or_circ->p_chan = p_chan;
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend back to the previous hop.\n");
mock_clean_saved_logs();
memset(ec->node_id, 0xAA, sizeof(ec->node_id));
memset(p_chan->identity_digest, 0xAA, sizeof(p_chan->identity_digest));
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend back to the previous hop.\n");
mock_clean_saved_logs();
memset(ec->node_id, 0, sizeof(ec->node_id));
memset(p_chan->identity_digest, 0, sizeof(p_chan->identity_digest));
memset(ec->node_id, 0xAA, sizeof(ec->node_id));
memset(p_chan->identity_digest, 0xBB, sizeof(p_chan->identity_digest));
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, 0);
mock_clean_saved_logs();
tor_addr_parse(&ec->orport_ipv4.addr, INTERNAL_IPV4);
ec->orport_ipv4.port = VALID_PORT;
tor_addr_parse(&ec->orport_ipv6.addr, PUBLIC_IPV6);
ec->orport_ipv6.port = VALID_PORT;
fake_options->ExtendAllowPrivateAddresses = 0;
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, 0);
expect_log_msg("Client asked me to extend "
"to a private IPv4 address '0.0.0.1'.\n");
mock_clean_saved_logs();
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
tor_addr_parse(&ec->orport_ipv4.addr, PUBLIC_IPV4);
ec->orport_ipv4.port = VALID_PORT;
tor_addr_parse(&ec->orport_ipv6.addr, INTERNAL_IPV6);
ec->orport_ipv6.port = VALID_PORT;
fake_options->ExtendAllowPrivateAddresses = 0;
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, 0);
expect_log_msg("Client asked me to extend "
"to a private IPv6 address '[::1]'.\n");
mock_clean_saved_logs();
tor_addr_port_make_null_ap(&ec->orport_ipv4, AF_INET);
tor_addr_port_make_null_ap(&ec->orport_ipv6, AF_INET6);
tor_addr_parse(&ec->orport_ipv4.addr, PUBLIC_IPV4);
ec->orport_ipv4.port = VALID_PORT;
tor_addr_parse(&ec->orport_ipv6.addr, PUBLIC_IPV6);
ec->orport_ipv6.port = VALID_PORT;
memset(&ec->ed_pubkey, 0xEE, sizeof(ec->ed_pubkey));
memset(&p_chan->ed25519_identity, 0xEE, sizeof(p_chan->ed25519_identity));
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, -1);
expect_log_msg("Client asked me to extend back to the previous hop "
"(by Ed25519 ID).\n");
mock_clean_saved_logs();
memset(&ec->ed_pubkey, 0, sizeof(ec->ed_pubkey));
memset(&p_chan->ed25519_identity, 0, sizeof(p_chan->ed25519_identity));
memset(&ec->ed_pubkey, 0xDD, sizeof(ec->ed_pubkey));
memset(&p_chan->ed25519_identity, 0xEE, sizeof(p_chan->ed25519_identity));
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, 0);
mock_clean_saved_logs();
memset(&ec->ed_pubkey, 0, sizeof(ec->ed_pubkey));
memset(&p_chan->ed25519_identity, 0, sizeof(p_chan->ed25519_identity));
memset(&ec->ed_pubkey, 0xDD, sizeof(ec->ed_pubkey));
memset(&p_chan->ed25519_identity, 0x00, sizeof(p_chan->ed25519_identity));
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, 0);
mock_clean_saved_logs();
memset(&ec->ed_pubkey, 0, sizeof(ec->ed_pubkey));
memset(&p_chan->ed25519_identity, 0, sizeof(p_chan->ed25519_identity));
memset(&ec->ed_pubkey, 0x00, sizeof(ec->ed_pubkey));
memset(&p_chan->ed25519_identity, 0xEE, sizeof(p_chan->ed25519_identity));
tt_int_op(circuit_extend_lspec_valid_helper(ec, circ), OP_EQ, 0);
mock_clean_saved_logs();
memset(&ec->ed_pubkey, 0, sizeof(ec->ed_pubkey));
memset(&p_chan->ed25519_identity, 0, sizeof(p_chan->ed25519_identity));
memset(ec->node_id, 0, sizeof(ec->node_id));
memset(p_chan->identity_digest, 0, sizeof(p_chan->identity_digest));
tor_addr_make_null(&ec->orport_ipv4.addr, AF_UNSPEC);
ec->orport_ipv4.port = 0;
or_circ->p_chan = NULL;
done:
tor_end_capture_bugs_();
teardown_capture_of_logs();
UNMOCK(get_options);
or_options_free(fake_options);
mocked_options = NULL;
tor_free(ec);
tor_free(or_circ);
tor_free(p_chan);
}
static bool can_extend_over_ipv6_result = false;
static int mock_router_can_extend_over_ipv6_calls = 0;
static bool
mock_router_can_extend_over_ipv6(const or_options_t *options)
{
(void)options;
mock_router_can_extend_over_ipv6_calls++;
return can_extend_over_ipv6_result;
}
static void
test_circuit_choose_ip_ap_for_extend(void *arg)
{
(void)arg;
tor_addr_port_t ipv4_ap;
tor_addr_port_t ipv6_ap;
tor_addr_parse(&ipv4_ap.addr, PUBLIC_IPV4);
ipv4_ap.port = VALID_PORT;
tor_addr_parse(&ipv6_ap.addr, PUBLIC_IPV6);
ipv6_ap.port = VALID_PORT;
or_options_t *fake_options = options_new();
MOCK(get_options, mock_get_options);
mocked_options = fake_options;
MOCK(router_can_extend_over_ipv6,
mock_router_can_extend_over_ipv6);
can_extend_over_ipv6_result = true;
mock_router_can_extend_over_ipv6_calls = 0;
can_extend_over_ipv6_result = true;
mock_router_can_extend_over_ipv6_calls = 0;
tt_ptr_op(circuit_choose_ip_ap_for_extend(NULL, NULL), OP_EQ, NULL);
tt_int_op(mock_router_can_extend_over_ipv6_calls, OP_EQ, 1);
can_extend_over_ipv6_result = false;
mock_router_can_extend_over_ipv6_calls = 0;
tt_ptr_op(circuit_choose_ip_ap_for_extend(NULL, NULL), OP_EQ, NULL);
tt_int_op(mock_router_can_extend_over_ipv6_calls, OP_EQ, 1);
can_extend_over_ipv6_result = true;
mock_router_can_extend_over_ipv6_calls = 0;
tt_ptr_op(circuit_choose_ip_ap_for_extend(&ipv4_ap, NULL), OP_EQ, &ipv4_ap);
tt_int_op(mock_router_can_extend_over_ipv6_calls, OP_EQ, 1);
can_extend_over_ipv6_result = false;
mock_router_can_extend_over_ipv6_calls = 0;
tt_ptr_op(circuit_choose_ip_ap_for_extend(&ipv4_ap, NULL), OP_EQ, &ipv4_ap);
tt_int_op(mock_router_can_extend_over_ipv6_calls, OP_EQ, 1);
can_extend_over_ipv6_result = true;
mock_router_can_extend_over_ipv6_calls = 0;
tt_ptr_op(circuit_choose_ip_ap_for_extend(NULL, &ipv6_ap), OP_EQ, &ipv6_ap);
tt_int_op(mock_router_can_extend_over_ipv6_calls, OP_EQ, 1);
can_extend_over_ipv6_result = false;
mock_router_can_extend_over_ipv6_calls = 0;
tt_ptr_op(circuit_choose_ip_ap_for_extend(NULL, &ipv6_ap), OP_EQ, NULL);
tt_int_op(mock_router_can_extend_over_ipv6_calls, OP_EQ, 1);
const tor_addr_port_t *chosen_addr = NULL;
can_extend_over_ipv6_result = true;
mock_router_can_extend_over_ipv6_calls = 0;
chosen_addr = circuit_choose_ip_ap_for_extend(&ipv4_ap, &ipv6_ap);
tt_assert(chosen_addr == &ipv4_ap || chosen_addr == &ipv6_ap);
tt_int_op(mock_router_can_extend_over_ipv6_calls, OP_EQ, 1);
can_extend_over_ipv6_result = false;
mock_router_can_extend_over_ipv6_calls = 0;
tt_ptr_op(circuit_choose_ip_ap_for_extend(&ipv4_ap, &ipv6_ap),
OP_EQ, &ipv4_ap);
tt_int_op(mock_router_can_extend_over_ipv6_calls, OP_EQ, 1);
done:
UNMOCK(get_options);
or_options_free(fake_options);
mocked_options = NULL;
UNMOCK(router_can_extend_over_ipv6);
tor_free(fake_options);
}
static int mock_circuit_close_calls = 0;
static void
mock_circuit_mark_for_close_(circuit_t *circ, int reason,
int line, const char *cfile)
{
(void)circ;
(void)reason;
(void)line;
(void)cfile;
mock_circuit_close_calls++;
}
static int mock_channel_connect_calls = 0;
static channel_t *mock_channel_connect_nchan = NULL;
static channel_t *
mock_channel_connect_for_circuit(const tor_addr_t *addr,
uint16_t port,
const char *id_digest,
const struct ed25519_public_key_t *ed_id)
{
(void)addr;
(void)port;
(void)id_digest;
(void)ed_id;
mock_channel_connect_calls++;
return mock_channel_connect_nchan;
}
static void
test_circuit_open_connection_for_extend(void *arg)
{
const char ip_version = ((const char *)arg)[0];
const bool use_ipv4 = (ip_version == '4' || ip_version == 'd');
const bool use_ipv6 = (ip_version == '6' || ip_version == 'd');
tor_assert(use_ipv4 || use_ipv6);
extend_cell_t *ec = tor_malloc_zero(sizeof(extend_cell_t));
circuit_t *circ = tor_malloc_zero(sizeof(circuit_t));
channel_t *fake_n_chan = tor_malloc_zero(sizeof(channel_t));
or_options_t *fake_options = options_new();
MOCK(get_options, mock_get_options);
mocked_options = fake_options;
MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close_);
mock_circuit_close_calls = 0;
MOCK(channel_connect_for_circuit, mock_channel_connect_for_circuit);
mock_channel_connect_calls = 0;
mock_channel_connect_nchan = NULL;
MOCK(router_can_extend_over_ipv6,
mock_router_can_extend_over_ipv6);
can_extend_over_ipv6_result = true;
setup_full_capture_of_logs(LOG_INFO);
#ifndef ALL_BUGS_ARE_FATAL
mock_circuit_close_calls = 0;
mock_channel_connect_calls = 0;
tor_capture_bugs_(1);
circuit_open_connection_for_extend(ec, NULL, 0);
tt_int_op(mock_circuit_close_calls, OP_EQ, 0);
tt_int_op(mock_channel_connect_calls, OP_EQ, 0);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!circ))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
mock_circuit_close_calls = 0;
mock_channel_connect_calls = 0;
tor_capture_bugs_(1);
circuit_open_connection_for_extend(NULL, circ, 0);
tt_int_op(mock_circuit_close_calls, OP_EQ, 1);
tt_int_op(mock_channel_connect_calls, OP_EQ, 0);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!ec))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
mock_circuit_close_calls = 0;
mock_channel_connect_calls = 0;
tor_capture_bugs_(1);
circuit_open_connection_for_extend(NULL, NULL, 0);
tt_int_op(mock_circuit_close_calls, OP_EQ, 0);
tt_int_op(mock_channel_connect_calls, OP_EQ, 0);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_GE, 0);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_LE, 2);
tor_end_capture_bugs_();
mock_clean_saved_logs();
mock_circuit_close_calls = 0;
mock_channel_connect_calls = 0;
tor_capture_bugs_(1);
circuit_open_connection_for_extend(ec, circ, 0);
tt_int_op(mock_circuit_close_calls, OP_EQ, 1);
tt_int_op(mock_channel_connect_calls, OP_EQ, 0);
tt_ptr_op(circ->n_hop, OP_EQ, NULL);
tt_ptr_op(circ->n_chan_create_cell, OP_EQ, NULL);
tt_int_op(circ->state, OP_EQ, 0);
tor_end_capture_bugs_();
mock_clean_saved_logs();
#endif
if (use_ipv4) {
tor_addr_parse(&ec->orport_ipv4.addr, PUBLIC_IPV4);
ec->orport_ipv4.port = VALID_PORT;
}
if (use_ipv6) {
tor_addr_parse(&ec->orport_ipv6.addr, PUBLIC_IPV6);
ec->orport_ipv6.port = VALID_PORT;
}
mock_circuit_close_calls = 0;
mock_channel_connect_calls = 0;
circuit_open_connection_for_extend(ec, circ, 0);
tt_int_op(mock_circuit_close_calls, OP_EQ, 0);
tt_int_op(mock_channel_connect_calls, OP_EQ, 0);
tt_ptr_op(circ->n_hop, OP_NE, NULL);
tt_ptr_op(circ->n_chan_create_cell, OP_NE, NULL);
tt_int_op(circ->state, OP_EQ, CIRCUIT_STATE_CHAN_WAIT);
mock_clean_saved_logs();
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
circ->state = 0;
mock_circuit_close_calls = 0;
mock_channel_connect_calls = 0;
circuit_open_connection_for_extend(ec, circ, 1);
tt_int_op(mock_circuit_close_calls, OP_EQ, 1);
tt_int_op(mock_channel_connect_calls, OP_EQ, 1);
expect_log_msg("Launching n_chan failed. Closing circuit.\n");
tt_ptr_op(circ->n_hop, OP_NE, NULL);
tt_ptr_op(circ->n_chan_create_cell, OP_NE, NULL);
tt_int_op(circ->state, OP_EQ, CIRCUIT_STATE_CHAN_WAIT);
mock_clean_saved_logs();
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
circ->state = 0;
mock_channel_connect_nchan = fake_n_chan;
mock_circuit_close_calls = 0;
mock_channel_connect_calls = 0;
circuit_open_connection_for_extend(ec, circ, 1);
tt_int_op(mock_circuit_close_calls, OP_EQ, 0);
tt_int_op(mock_channel_connect_calls, OP_EQ, 1);
tt_ptr_op(circ->n_hop, OP_NE, NULL);
tt_ptr_op(circ->n_chan_create_cell, OP_NE, NULL);
tt_int_op(circ->state, OP_EQ, CIRCUIT_STATE_CHAN_WAIT);
mock_clean_saved_logs();
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
circ->state = 0;
mock_channel_connect_nchan = NULL;
done:
tor_end_capture_bugs_();
teardown_capture_of_logs();
UNMOCK(circuit_mark_for_close_);
mock_circuit_close_calls = 0;
UNMOCK(channel_connect_for_circuit);
mock_channel_connect_calls = 0;
UNMOCK(get_options);
or_options_free(fake_options);
mocked_options = NULL;
UNMOCK(router_can_extend_over_ipv6);
tor_free(ec);
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
tor_free(circ);
tor_free(fake_n_chan);
}
static extend_cell_t mock_extend_cell_parse_cell_out;
static int mock_extend_cell_parse_result = 0;
static int mock_extend_cell_parse_calls = 0;
static int
mock_extend_cell_parse(extend_cell_t *cell_out,
const uint8_t command,
const uint8_t *payload_in,
size_t payload_len)
{
(void)command;
(void)payload_in;
(void)payload_len;
mock_extend_cell_parse_calls++;
memcpy(cell_out, &mock_extend_cell_parse_cell_out,
sizeof(extend_cell_t));
return mock_extend_cell_parse_result;
}
static int mock_channel_get_for_extend_calls = 0;
static int mock_channel_get_for_extend_launch_out = 0;
static channel_t *mock_channel_get_for_extend_nchan = NULL;
static channel_t *
mock_channel_get_for_extend(const char *rsa_id_digest,
const ed25519_public_key_t *ed_id,
const tor_addr_t *target_ipv4_addr,
const tor_addr_t *target_ipv6_addr,
const char **msg_out,
int *launch_out)
{
(void)rsa_id_digest;
(void)ed_id;
(void)target_ipv4_addr;
(void)target_ipv6_addr;
tt_ptr_op(msg_out, OP_NE, NULL);
tt_ptr_op(launch_out, OP_NE, NULL);
mock_channel_get_for_extend_calls++;
*msg_out = NULL;
*launch_out = mock_channel_get_for_extend_launch_out;
return mock_channel_get_for_extend_nchan;
done:
return NULL;
}
static const char *
mock_channel_get_canonical_remote_descr(channel_t *chan)
{
(void)chan;
return "mock_channel_get_canonical_remote_descr()";
}
static int mock_circuit_deliver_create_cell_calls = 0;
static int mock_circuit_deliver_create_cell_result = 0;
static int
mock_circuit_deliver_create_cell(circuit_t *circ,
const struct create_cell_t *create_cell,
int relayed)
{
(void)create_cell;
tt_ptr_op(circ, OP_NE, NULL);
tt_ptr_op(circ->n_chan, OP_NE, NULL);
tt_int_op(relayed, OP_EQ, 1);
mock_circuit_deliver_create_cell_calls++;
return mock_circuit_deliver_create_cell_result;
done:
return -1;
}
static void
test_circuit_extend(void *arg)
{
(void)arg;
cell_t *cell = tor_malloc_zero(sizeof(cell_t));
channel_t *p_chan = tor_malloc_zero(sizeof(channel_t));
or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t));
circuit_t *circ = TO_CIRCUIT(or_circ);
channel_t *fake_n_chan = tor_malloc_zero(sizeof(channel_t));
server = 0;
MOCK(server_mode, mock_server_mode);
MOCK(channel_get_canonical_remote_descr,
mock_channel_get_canonical_remote_descr);
setup_full_capture_of_logs(LOG_INFO);
#ifndef ALL_BUGS_ARE_FATAL
tor_capture_bugs_(1);
tt_int_op(circuit_extend(cell, NULL), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!circ))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
tor_capture_bugs_(1);
tt_int_op(circuit_extend(NULL, circ), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!cell))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
tor_capture_bugs_(1);
tt_int_op(circuit_extend(NULL, NULL), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_GE, 0);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_LE, 2);
tor_end_capture_bugs_();
mock_clean_saved_logs();
#endif
server = 0;
tt_int_op(circuit_extend(cell, circ), OP_EQ, -1);
expect_log_msg("Got an extend cell, but running as a client. Closing.\n");
mock_clean_saved_logs();
server = 1;
tt_int_op(circuit_extend(cell, circ), OP_EQ, -1);
expect_log_msg("Can't parse extend cell. Closing circuit.\n");
mock_clean_saved_logs();
MOCK(extend_cell_parse, mock_extend_cell_parse);
memset(&mock_extend_cell_parse_cell_out, 0,
sizeof(mock_extend_cell_parse_cell_out));
mock_extend_cell_parse_result = 0;
mock_extend_cell_parse_calls = 0;
tt_int_op(circuit_extend(cell, circ), OP_EQ, -1);
tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1);
expect_log_msg(
"Client asked me to extend without specifying an id_digest.\n");
mock_clean_saved_logs();
mock_extend_cell_parse_calls = 0;
memset(&mock_extend_cell_parse_cell_out.node_id, 0xAA,
sizeof(mock_extend_cell_parse_cell_out.node_id));
tt_int_op(circuit_extend(cell, circ), OP_EQ, -1);
tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1);
expect_log_msg("Client asked me to extend to a zero destination port "
"or unspecified address '[scrubbed]'.\n");
mock_clean_saved_logs();
mock_extend_cell_parse_calls = 0;
tor_addr_parse(&mock_extend_cell_parse_cell_out.orport_ipv4.addr,
PUBLIC_IPV4);
mock_extend_cell_parse_cell_out.orport_ipv4.port = VALID_PORT;
#ifndef ALL_BUGS_ARE_FATAL
tor_capture_bugs_(1);
tt_int_op(circuit_extend(cell, circ), OP_EQ, -1);
tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(circ->magic != 0x98ABC04Fu))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
mock_extend_cell_parse_calls = 0;
#endif
or_circ->base_.magic = OR_CIRCUIT_MAGIC;
or_circ->p_chan = p_chan;
mock_channel_get_for_extend_calls = 0;
MOCK(channel_get_for_extend, mock_channel_get_for_extend);
mock_channel_get_for_extend_launch_out = 0;
mock_channel_get_for_extend_nchan = NULL;
tt_int_op(circuit_extend(cell, circ), OP_EQ, 0);
tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1);
tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1);
mock_clean_saved_logs();
mock_extend_cell_parse_calls = 0;
mock_channel_get_for_extend_calls = 0;
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
mock_channel_connect_calls = 0;
MOCK(channel_connect_for_circuit, mock_channel_connect_for_circuit);
mock_channel_get_for_extend_launch_out = 1;
mock_channel_get_for_extend_nchan = NULL;
mock_channel_connect_nchan = fake_n_chan;
tt_int_op(circuit_extend(cell, circ), OP_EQ, 0);
tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1);
tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1);
tt_int_op(mock_channel_connect_calls, OP_EQ, 1);
mock_clean_saved_logs();
mock_extend_cell_parse_calls = 0;
mock_channel_get_for_extend_calls = 0;
mock_channel_connect_calls = 0;
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
mock_circuit_deliver_create_cell_calls = 0;
MOCK(circuit_deliver_create_cell, mock_circuit_deliver_create_cell);
mock_channel_get_for_extend_launch_out = 0;
mock_channel_get_for_extend_nchan = fake_n_chan;
mock_channel_connect_nchan = NULL;
mock_circuit_deliver_create_cell_result = 0;
tt_int_op(circuit_extend(cell, circ), OP_EQ, 0);
tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1);
tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1);
tt_int_op(mock_channel_connect_calls, OP_EQ, 0);
tt_int_op(mock_circuit_deliver_create_cell_calls, OP_EQ, 1);
tt_ptr_op(circ->n_chan, OP_EQ, fake_n_chan);
circ->n_chan = NULL;
mock_clean_saved_logs();
mock_extend_cell_parse_calls = 0;
mock_channel_get_for_extend_calls = 0;
mock_channel_connect_calls = 0;
mock_circuit_deliver_create_cell_calls = 0;
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
mock_channel_get_for_extend_launch_out = 0;
mock_channel_get_for_extend_nchan = fake_n_chan;
mock_channel_connect_nchan = NULL;
mock_circuit_deliver_create_cell_result = -1;
tt_int_op(circuit_extend(cell, circ), OP_EQ, -1);
tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1);
tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1);
tt_int_op(mock_channel_connect_calls, OP_EQ, 0);
tt_int_op(mock_circuit_deliver_create_cell_calls, OP_EQ, 1);
tt_ptr_op(circ->n_chan, OP_EQ, fake_n_chan);
circ->n_chan = NULL;
mock_clean_saved_logs();
mock_extend_cell_parse_calls = 0;
mock_channel_get_for_extend_calls = 0;
mock_channel_connect_calls = 0;
mock_circuit_deliver_create_cell_calls = 0;
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
done:
tor_end_capture_bugs_();
teardown_capture_of_logs();
UNMOCK(server_mode);
server = 0;
UNMOCK(channel_get_canonical_remote_descr);
UNMOCK(extend_cell_parse);
memset(&mock_extend_cell_parse_cell_out, 0,
sizeof(mock_extend_cell_parse_cell_out));
mock_extend_cell_parse_result = 0;
mock_extend_cell_parse_calls = 0;
UNMOCK(channel_get_for_extend);
mock_channel_get_for_extend_calls = 0;
mock_channel_get_for_extend_launch_out = 0;
mock_channel_get_for_extend_nchan = NULL;
UNMOCK(channel_connect_for_circuit);
mock_channel_connect_calls = 0;
mock_channel_connect_nchan = NULL;
UNMOCK(circuit_deliver_create_cell);
mock_circuit_deliver_create_cell_calls = 0;
mock_circuit_deliver_create_cell_result = 0;
tor_free(cell);
tor_free(circ->n_hop);
tor_free(circ->n_chan_create_cell);
tor_free(or_circ);
tor_free(p_chan);
tor_free(fake_n_chan);
}
static void
test_onionskin_answer(void *arg)
{
(void)arg;
created_cell_t *created_cell = tor_malloc_zero(sizeof(created_cell_t));
or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t));
char keys[CPATH_KEY_MATERIAL_LEN] = {0};
uint8_t rend_circ_nonce[DIGEST_LEN] = {0};
setup_full_capture_of_logs(LOG_INFO);
#ifndef ALL_BUGS_ARE_FATAL
tor_capture_bugs_(1);
tt_int_op(onionskin_answer(NULL, created_cell,
keys, CPATH_KEY_MATERIAL_LEN,
rend_circ_nonce), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!circ))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
tor_capture_bugs_(1);
tt_int_op(onionskin_answer(or_circ, NULL,
keys, CPATH_KEY_MATERIAL_LEN,
rend_circ_nonce), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!created_cell))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
tor_capture_bugs_(1);
tt_int_op(onionskin_answer(or_circ, created_cell,
NULL, CPATH_KEY_MATERIAL_LEN,
rend_circ_nonce), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!keys))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
tor_capture_bugs_(1);
tt_int_op(onionskin_answer(or_circ, created_cell,
keys, CPATH_KEY_MATERIAL_LEN,
NULL), OP_EQ, -1);
tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1);
tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ,
"!(ASSERT_PREDICT_UNLIKELY_(!rend_circ_nonce))");
tor_end_capture_bugs_();
mock_clean_saved_logs();
#endif
tt_int_op(onionskin_answer(or_circ, created_cell,
keys, CPATH_KEY_MATERIAL_LEN,
rend_circ_nonce), OP_EQ, -1);
expect_log_msg("couldn't format created cell (type=0, len=0).\n");
mock_clean_saved_logs();
done:
tor_end_capture_bugs_();
teardown_capture_of_logs();
tor_free(created_cell);
tor_free(or_circ);
}
#define TEST(name, flags, setup, cleanup) \
{ #name, test_ ## name, flags, setup, cleanup }
#define TEST_NEW_ROUTE_LEN(name, flags) \
{ #name, test_new_route_len_ ## name, flags, NULL, NULL }
#define TEST_CIRCUIT(name, flags) \
{ #name, test_circuit_ ## name, flags, NULL, NULL }
#ifndef COCCI
#define TEST_CIRCUIT_PASSTHROUGH(name, flags, arg) \
{ #name "/" arg, test_circuit_ ## name, flags, \
&passthrough_setup, (void *)(arg) }
#endif
struct testcase_t circuitbuild_tests[] = {
TEST_NEW_ROUTE_LEN(noexit, 0),
TEST_NEW_ROUTE_LEN(safe_exit, 0),
TEST_NEW_ROUTE_LEN(unsafe_exit, 0),
TEST_NEW_ROUTE_LEN(unhandled_exit, 0),
TEST(upgrade_from_guard_wait, TT_FORK, &helper_pubsub_setup, NULL),
TEST_CIRCUIT(extend_state_valid, TT_FORK),
TEST_CIRCUIT(extend_add_ed25519, TT_FORK),
TEST_CIRCUIT(extend_lspec_valid, TT_FORK),
TEST_CIRCUIT(choose_ip_ap_for_extend, 0),
TEST_CIRCUIT_PASSTHROUGH(open_connection_for_extend, TT_FORK, "4"),
TEST_CIRCUIT_PASSTHROUGH(open_connection_for_extend, TT_FORK, "6"),
TEST_CIRCUIT_PASSTHROUGH(open_connection_for_extend, TT_FORK, "dual-stack"),
TEST_CIRCUIT(extend, TT_FORK),
TEST(onionskin_answer, TT_FORK, NULL, NULL),
END_OF_TESTCASES
};