Merge branch 'maint-0.4.5' into release-0.4.5

This commit is contained in:
David Goulet
2021-10-19 10:29:20 -04:00
14 changed files with 75 additions and 470 deletions
+8
View File
@@ -0,0 +1,8 @@
o Major feature (onion service v2):
- Tor does NOT allow anymore to create v2 services, to connect as a client
to a v2 service and for a relay to be a v2 HSDir or introduction point.
This effectively disable onion service version 2 tor wide. Closes 40476.
- The control port command HSFETCH and HSPOST don't allow version 2 as well.
It is also not possible to create a v2 service with ADD_ONION.
- See https://blog.torproject.org/v2-deprecation-timeline for details on
how to transition from v2 to v3.
+4 -13
View File
@@ -1636,12 +1636,12 @@ consider_plaintext_ports(entry_connection_t *conn, uint16_t port)
* The possible recognized forms are (where true is returned):
*
* If address is of the form "y.onion" with a well-formed handle y:
* Put a NUL after y, lower-case it, and return ONION_V2_HOSTNAME or
* ONION_V3_HOSTNAME depending on the HS version.
* Put a NUL after y, lower-case it, and return ONION_V3_HOSTNAME
* depending on the HS version.
*
* If address is of the form "x.y.onion" with a well-formed handle x:
* Drop "x.", put a NUL after y, lower-case it, and return
* ONION_V2_HOSTNAME or ONION_V3_HOSTNAME depending on the HS version.
* ONION_V3_HOSTNAME depending on the HS version.
*
* If address is of the form "y.onion" with a badly-formed handle y:
* Return BAD_HOSTNAME and log a message.
@@ -1691,14 +1691,6 @@ parse_extended_hostname(char *address, hostname_type_t *type_out)
if (q != address) {
memmove(address, q, strlen(q) + 1 /* also get \0 */);
}
/* v2 onion address check. */
if (strlen(query) == REND_SERVICE_ID_LEN_BASE32) {
*type_out = ONION_V2_HOSTNAME;
if (rend_valid_v2_service_id(query)) {
goto success;
}
goto failed;
}
/* v3 onion address check. */
if (strlen(query) == HS_SERVICE_ADDR_LEN_BASE32) {
@@ -1718,8 +1710,7 @@ parse_extended_hostname(char *address, hostname_type_t *type_out)
failed:
/* otherwise, return to previous state and return 0 */
*s = '.';
const bool is_onion = (*type_out == ONION_V2_HOSTNAME) ||
(*type_out == ONION_V3_HOSTNAME);
const bool is_onion = (*type_out == ONION_V3_HOSTNAME);
log_warn(LD_APP, "Invalid %shostname %s; rejecting",
is_onion ? "onion " : "",
safe_str_client(address));
+12 -20
View File
@@ -1443,10 +1443,8 @@ handle_control_hsfetch(control_connection_t *conn,
const control_cmd_args_t *args)
{
char digest[DIGEST_LEN], *desc_id = NULL;
char *desc_id = NULL;
smartlist_t *hsdirs = NULL;
static const char *v2_str = "v2-";
const size_t v2_str_len = strlen(v2_str);
rend_data_t *rend_query = NULL;
ed25519_public_key_t v3_pk;
uint32_t version;
@@ -1454,20 +1452,7 @@ handle_control_hsfetch(control_connection_t *conn,
/* Extract the first argument (either HSAddress or DescID). */
const char *arg1 = smartlist_get(args->args, 0);
/* Test if it's an HS address without the .onion part. */
if (rend_valid_v2_service_id(arg1)) {
hsaddress = arg1;
version = HS_VERSION_TWO;
} else if (strcmpstart(arg1, v2_str) == 0 &&
rend_valid_descriptor_id(arg1 + v2_str_len) &&
base32_decode(digest, sizeof(digest), arg1 + v2_str_len,
REND_DESC_ID_V2_LEN_BASE32) ==
sizeof(digest)) {
/* We have a well formed version 2 descriptor ID. Keep the decoded value
* of the id. */
desc_id = digest;
version = HS_VERSION_TWO;
} else if (hs_address_is_valid(arg1)) {
if (hs_address_is_valid(arg1)) {
hsaddress = arg1;
version = HS_VERSION_THREE;
hs_parse_address(hsaddress, &v3_pk, NULL, NULL);
@@ -1590,6 +1575,11 @@ handle_control_hspost(control_connection_t *conn,
goto done;
}
/* As for HSFETCH, we no longer support v2 on the network and so we stop
* right now. Code is not removed in order to minimize the merge forward
* conflicts. */
goto done;
/* From this point on, it is only v2. */
/* parse it. */
@@ -1662,11 +1652,13 @@ add_onion_helper_add_service(int hs_version,
tor_assert(port_cfgs);
tor_assert(address_out);
/* Version 2 is disabled. */
(void) auth_type;
(void) auth_clients;
switch (hs_version) {
case HS_VERSION_TWO:
ret = rend_service_add_ephemeral(pk->v2, port_cfgs, max_streams,
max_streams_close_circuit, auth_type,
auth_clients, address_out);
ret = RSAE_INTERNAL;
break;
case HS_VERSION_THREE:
ret = hs_service_add_ephemeral(pk->v3, port_cfgs, max_streams,
+3 -58
View File
@@ -356,8 +356,6 @@ static int handle_get_descriptor(dir_connection_t *conn,
const get_handler_args_t *args);
static int handle_get_keys(dir_connection_t *conn,
const get_handler_args_t *args);
static int handle_get_hs_descriptor_v2(dir_connection_t *conn,
const get_handler_args_t *args);
static int handle_get_robots(dir_connection_t *conn,
const get_handler_args_t *args);
static int handle_get_networkstatus_bridges(dir_connection_t *conn,
@@ -376,7 +374,6 @@ static const url_table_ent_t url_table[] = {
{ "/tor/server/", 1, handle_get_descriptor },
{ "/tor/extra/", 1, handle_get_descriptor },
{ "/tor/keys/", 1, handle_get_keys },
{ "/tor/rendezvous2/", 1, handle_get_hs_descriptor_v2 },
{ "/tor/hs/3/", 1, handle_get_hs_descriptor_v3 },
{ "/tor/robots.txt", 0, handle_get_robots },
{ "/tor/networkstatus-bridges", 0, handle_get_networkstatus_bridges },
@@ -1350,45 +1347,7 @@ handle_get_keys(dir_connection_t *conn, const get_handler_args_t *args)
return 0;
}
/** Helper function for GET /tor/rendezvous2/
*/
static int
handle_get_hs_descriptor_v2(dir_connection_t *conn,
const get_handler_args_t *args)
{
const char *url = args->url;
if (connection_dir_is_encrypted(conn)) {
/* Handle v2 rendezvous descriptor fetch request. */
const char *descp;
const char *query = url + strlen("/tor/rendezvous2/");
if (rend_valid_descriptor_id(query)) {
log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
safe_str(escaped(query)));
switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
case 1: /* valid */
write_http_response_header(conn, strlen(descp), NO_METHOD, 0);
connection_buf_add(descp, strlen(descp), TO_CONN(conn));
break;
case 0: /* well-formed but not present */
write_short_http_response(conn, 404, "Not found");
break;
case -1: /* not well-formed */
write_short_http_response(conn, 400, "Bad request");
break;
}
} else { /* not well-formed */
write_short_http_response(conn, 400, "Bad request");
}
goto done;
} else {
/* Not encrypted! */
write_short_http_response(conn, 404, "Not found");
}
done:
return 0;
}
/** Helper function for GET `/tor/hs/3/...`. Only for version 3.
/** Helper function for GET /tor/hs/3/... Only for version 3.
*/
STATIC int
handle_get_hs_descriptor_v3(dir_connection_t *conn,
@@ -1611,6 +1570,8 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
char *url = NULL;
const or_options_t *options = get_options();
(void) body_len;
log_debug(LD_DIRSERV,"Received POST command.");
conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
@@ -1629,22 +1590,6 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
}
log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
/* Handle v2 rendezvous service publish request. */
if (connection_dir_is_encrypted(conn) &&
!strcmpstart(url,"/tor/rendezvous2/publish")) {
if (rend_cache_store_v2_desc_as_dir(body) < 0) {
log_warn(LD_REND, "Rejected v2 rend descriptor (body size %d) from %s.",
(int)body_len,
connection_describe_peer(TO_CONN(conn)));
write_short_http_response(conn, 400,
"Invalid v2 service descriptor rejected");
} else {
write_short_http_response(conn, 200, "Service descriptor (v2) stored");
log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
}
goto done;
}
/* Handle HS descriptor publish request. We force an anonymous connection
* (which also tests for encrypted). We do not allow single-hop client to
* post a descriptor onto an HSDir. */
+1 -1
View File
@@ -25,7 +25,7 @@ struct ed25519_keypair_t;
/** Version 3 of the protocol (prop224). */
#define HS_VERSION_THREE 3
/** Earliest version we support. */
#define HS_VERSION_MIN HS_VERSION_TWO
#define HS_VERSION_MIN HS_VERSION_THREE
/** Latest version we support. */
#define HS_VERSION_MAX HS_VERSION_THREE
+6 -2
View File
@@ -179,8 +179,12 @@ static bool
check_value_oob(int i, const char *name, int low, int high)
{
if (i < low || i > high) {
log_warn(LD_CONFIG, "%s must be between %d and %d, not %d.",
name, low, high, i);
if (low == high) {
log_warn(LD_CONFIG, "%s must be %d, not %d.", name, low, i);
} else {
log_warn(LD_CONFIG, "%s must be between %d and %d, not %d.",
name, low, high, i);
}
return true;
}
return false;
+2 -1
View File
@@ -514,7 +514,8 @@ hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request,
switch (first_byte) {
case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0:
case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1:
return rend_mid_establish_intro_legacy(circ, request, request_len);
/* Don't accept version 2 introduction anymore. */
goto err;
case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519:
return handle_establish_intro(circ, request, request_len);
default:
+6 -7
View File
@@ -74,22 +74,21 @@ TESTS += src/test/test-slow src/test/test-memwipe \
# run a quick test or two
# this test only uses IPv4
TEST_CHUTNEY_FLAVOR_QUICK = bridges+hs-v23
TEST_CHUTNEY_FLAVOR_QUICK = bridges+hs-v3
# only run if we can ping6 ::1 (localhost)
TEST_CHUTNEY_FLAVOR_QUICK_IPV6 = single-onion-v23-ipv6-md
TEST_CHUTNEY_FLAVOR_QUICK_IPV6 = single-onion-v3-ipv6-md
# run a basic set of tests, which only use IPv4
TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-v23-min single-onion-v23
TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-v3-min single-onion-v3
# only run if we can ping ::1 (localhost)
TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-v23-ipv6-md \
single-onion-v23-ipv6-md
TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-v3-ipv6 single-onion-v3-ipv6-md
# only run if we can find a stable (or simply another) version of tor
TEST_CHUTNEY_FLAVORS_MIXED = mixed+hs-v23
TEST_CHUTNEY_FLAVORS_MIXED = mixed+hs-v3
# only run if IPv6 and mixed networks are run
TEST_CHUTNEY_FLAVORS_IPV6_MIXED = mixed+hs-v23-ipv6
TEST_CHUTNEY_FLAVORS_IPV6_MIXED = mixed+hs-v3-ipv6
### This is a lovely feature, but it requires automake >= 1.12, and Tor
### doesn't require that yet.
+2 -73
View File
@@ -309,7 +309,7 @@ test_dir_handle_get_rendezvous2_on_encrypted_conn_with_invalid_desc_id(
fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
NULL, NULL, 1, 0);
tt_str_op(header, OP_EQ, BAD_REQUEST);
tt_str_op(header, OP_EQ, NOT_FOUND);
done:
UNMOCK(connection_write_to_buf_impl_);
@@ -342,7 +342,7 @@ test_dir_handle_get_rendezvous2_on_encrypted_conn_not_well_formed(void *data)
fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
NULL, NULL, 1, 0);
tt_str_op(header, OP_EQ, BAD_REQUEST);
tt_str_op(header, OP_EQ, NOT_FOUND);
done:
UNMOCK(connection_write_to_buf_impl_);
@@ -395,76 +395,6 @@ dhg_tests_router_get_my_routerinfo(void)
return mock_routerinfo;
}
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);
MOCK(router_get_my_routerinfo,
dhg_tests_router_get_my_routerinfo);
rend_cache_init();
/* 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, 0);
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
DIGEST_LEN);
conn = new_dir_conn();
// connection is encrypted
TO_CONN(conn)->linked = 1;
tt_assert(connection_dir_is_encrypted(conn));
tor_snprintf(req, sizeof(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"));
tor_snprintf(buff, sizeof(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_);
UNMOCK(router_get_my_routerinfo);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
tor_free(body);
rend_encoded_v2_service_descriptor_free(desc_holder);
tor_free(service_id);
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)
@@ -2938,7 +2868,6 @@ struct testcase_t dir_handle_get_tests[] = {
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),
-41
View File
@@ -728,46 +728,6 @@ test_entryconn_rewrite_mapaddress_automap_onion4(void *arg)
test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 0, 1);
}
/** Test that rewrite functions can handle v2 addresses */
static void
test_entryconn_rewrite_onion_v2(void *arg)
{
int retval;
entry_connection_t *conn = arg;
(void) arg;
rend_cache_init();
/* Make a SOCKS request */
conn->socks_request->command = SOCKS_COMMAND_CONNECT;
strlcpy(conn->socks_request->address,
"pqeed46efnwmfuid.onion",
sizeof(conn->socks_request->address));
/* Make an onion connection using the SOCKS request */
conn->entry_cfg.onion_traffic = 1;
ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_SOCKS_WAIT;
tt_assert(!ENTRY_TO_EDGE_CONN(conn)->rend_data);
/* Handle SOCKS and rewrite! */
retval = connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL);
tt_int_op(retval, OP_EQ, 0);
/* Check connection state after rewrite */
tt_int_op(ENTRY_TO_CONN(conn)->state, OP_EQ, AP_CONN_STATE_RENDDESC_WAIT);
/* check that the address got rewritten */
tt_str_op(conn->socks_request->address, OP_EQ,
"pqeed46efnwmfuid");
/* check that HS information got attached to the connection */
tt_assert(ENTRY_TO_EDGE_CONN(conn)->rend_data);
tt_assert(!ENTRY_TO_EDGE_CONN(conn)->hs_ident);
done:
rend_cache_free_all();
/* 'conn' is cleaned by handler */
}
/** Test that rewrite functions can handle v3 onion addresses */
static void
test_entryconn_rewrite_onion_v3(void *arg)
@@ -830,7 +790,6 @@ struct testcase_t entryconn_tests[] = {
REWRITE(rewrite_mapaddress_automap_onion2),
REWRITE(rewrite_mapaddress_automap_onion3),
REWRITE(rewrite_mapaddress_automap_onion4),
REWRITE(rewrite_onion_v2),
REWRITE(rewrite_onion_v3),
END_OF_TESTCASES
+6 -9
View File
@@ -803,9 +803,8 @@ test_parse_extended_hostname(void *arg)
tt_assert(!parse_extended_hostname(address1, &type));
tt_int_op(type, OP_EQ, BAD_HOSTNAME);
tt_assert(parse_extended_hostname(address2, &type));
tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
tt_str_op(address2, OP_EQ, "aaaaaaaaaaaaaaaa");
tt_assert(!parse_extended_hostname(address2, &type));
tt_int_op(type, OP_EQ, BAD_HOSTNAME);
tt_assert(parse_extended_hostname(address3, &type));
tt_int_op(type, OP_EQ, EXIT_HOSTNAME);
@@ -813,13 +812,11 @@ test_parse_extended_hostname(void *arg)
tt_assert(parse_extended_hostname(address4, &type));
tt_int_op(type, OP_EQ, NORMAL_HOSTNAME);
tt_assert(parse_extended_hostname(address5, &type));
tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
tt_str_op(address5, OP_EQ, "abcdefghijklmnop");
tt_assert(!parse_extended_hostname(address5, &type));
tt_int_op(type, OP_EQ, BAD_HOSTNAME);
tt_assert(parse_extended_hostname(address6, &type));
tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
tt_str_op(address6, OP_EQ, "abcdefghijklmnop");
tt_assert(!parse_extended_hostname(address6, &type));
tt_int_op(type, OP_EQ, BAD_HOSTNAME);
tt_assert(!parse_extended_hostname(address7, &type));
tt_int_op(type, OP_EQ, BAD_HOSTNAME);
+24 -177
View File
@@ -49,7 +49,19 @@ test_invalid_service(void *arg)
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceVersion must be between 2 and 3");
expect_log_msg_containing("HiddenServiceVersion must be 3, not 1");
teardown_capture_of_logs();
}
/* Version 2 not accepted anymore. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceVersion must be 3, not 2");
teardown_capture_of_logs();
}
@@ -57,7 +69,7 @@ test_invalid_service(void *arg)
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServiceAllowUnknownPorts 2\n"; /* Should be 0 or 1. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
@@ -72,7 +84,7 @@ test_invalid_service(void *arg)
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServiceDirGroupReadable 2\n"; /* Should be 0 or 1. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
@@ -87,7 +99,7 @@ test_invalid_service(void *arg)
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServiceMaxStreamsCloseCircuit 2\n"; /* Should be 0 or 1. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
@@ -102,7 +114,7 @@ test_invalid_service(void *arg)
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 80\n"
"HiddenServiceMaxStreams 65536\n"; /* One too many. */
setup_full_capture_of_logs(LOG_WARN);
@@ -117,10 +129,10 @@ test_invalid_service(void *arg)
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 80\n"
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 81\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
@@ -134,7 +146,7 @@ test_invalid_service(void *arg)
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 65536\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
@@ -147,7 +159,7 @@ test_invalid_service(void *arg)
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 80 127.0.0.1 8000\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
@@ -160,7 +172,7 @@ test_invalid_service(void *arg)
/* Out of order directives. */
{
const char *conf =
"HiddenServiceVersion 2\n"
"HiddenServiceVersion 3\n"
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServicePort 80\n";
setup_full_capture_of_logs(LOG_WARN);
@@ -182,18 +194,12 @@ test_valid_service(void *arg)
(void) arg;
/* Mix of v2 and v3. Still valid. */
/* v3. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80\n"
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 81\n"
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 82\n";
"HiddenServicePort 81\n";
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, 0);
}
@@ -202,127 +208,6 @@ test_valid_service(void *arg)
;
}
static void
test_invalid_service_v2(void *arg)
{
int validate_only = 1, ret;
(void) arg;
/* Try with a missing port configuration. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, validate_only);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("with no ports configured.");
teardown_capture_of_logs();
}
/* Too many introduction points. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80\n"
"HiddenServiceNumIntroductionPoints 11\n"; /* One too many. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, validate_only);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceNumIntroductionPoints must "
"be between 0 and 10, not 11.");
teardown_capture_of_logs();
}
/* Too little introduction points. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80\n"
"HiddenServiceNumIntroductionPoints -1\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, validate_only);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("Could not parse "
"HiddenServiceNumIntroductionPoints: "
"Integer -1 is malformed or out of bounds.");
teardown_capture_of_logs();
}
/* Bad authorized client type. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80\n"
"HiddenServiceAuthorizeClient blah alice,bob\n"; /* blah is no good. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, validate_only);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceAuthorizeClient contains "
"unrecognized auth-type");
teardown_capture_of_logs();
}
done:
;
}
static void
test_valid_service_v2(void *arg)
{
int ret;
(void) arg;
mock_hostname_resolver();
/* Valid complex configuration. Basic client authorization. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80\n"
"HiddenServicePort 22 localhost:22\n"
#ifdef HAVE_SYS_UN_H
"HiddenServicePort 42 unix:/path/to/socket\n"
#endif
"HiddenServiceAuthorizeClient basic alice,bob,eve\n"
"HiddenServiceAllowUnknownPorts 1\n"
"HiddenServiceMaxStreams 42\n"
"HiddenServiceMaxStreamsCloseCircuit 0\n"
"HiddenServiceDirGroupReadable 1\n"
"HiddenServiceNumIntroductionPoints 7\n";
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, 0);
}
/* Valid complex configuration. Stealth client authorization. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 65535\n"
"HiddenServicePort 22 1.1.1.1:22\n"
#ifdef HAVE_SYS_UN_H
"HiddenServicePort 9000 unix:/path/to/socket\n"
#endif
"HiddenServiceAuthorizeClient stealth charlie,romeo\n"
"HiddenServiceAllowUnknownPorts 0\n"
"HiddenServiceMaxStreams 42\n"
"HiddenServiceMaxStreamsCloseCircuit 0\n"
"HiddenServiceDirGroupReadable 1\n"
"HiddenServiceNumIntroductionPoints 8\n";
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, 0);
}
done:
unmock_hostname_resolver();
}
static void
test_invalid_service_v3(void *arg)
{
@@ -372,22 +257,6 @@ test_invalid_service_v3(void *arg)
teardown_capture_of_logs();
}
/* v2-specific HiddenServiceAuthorizeClient set. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 3\n"
"HiddenServiceAuthorizeClient stealth client1\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, validate_only);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("Hidden service option "
"HiddenServiceAuthorizeClient is incompatible "
"with version 3 of service in "
"/tmp/tor-test-hs-RANDOM/hs1");
teardown_capture_of_logs();
}
done:
;
}
@@ -438,22 +307,6 @@ test_valid_service_v3(void *arg)
tt_int_op(ret, OP_EQ, 0);
}
/* Mix of v2 and v3. Still valid. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80\n"
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 81\n"
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 82\n";
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, 0);
}
done:
unmock_hostname_resolver();
}
@@ -611,12 +464,6 @@ struct testcase_t hs_config_tests[] = {
{ "valid_service", test_valid_service, TT_FORK,
NULL, NULL },
/* Test case only for version 2. */
{ "invalid_service_v2", test_invalid_service_v2, TT_FORK,
NULL, NULL },
{ "valid_service_v2", test_valid_service_v2, TT_FORK,
NULL, NULL },
/* Test case only for version 3. */
{ "invalid_service_v3", test_invalid_service_v3, TT_FORK,
NULL, NULL },
-64
View File
@@ -517,42 +517,6 @@ helper_establish_intro_v3(or_circuit_t *intro_circ)
return cell;
}
/* Helper function: Send a well-formed v2 ESTABLISH_INTRO cell to
* <b>intro_circ</b>. Return the public key advertised in the cell. */
static crypto_pk_t *
helper_establish_intro_v2(or_circuit_t *intro_circ)
{
crypto_pk_t *key1 = NULL;
int retval;
uint8_t cell_body[RELAY_PAYLOAD_SIZE];
ssize_t cell_len = 0;
char circ_nonce[DIGEST_LEN] = {0};
tt_assert(intro_circ);
/* Prepare the circuit for the incoming ESTABLISH_INTRO */
crypto_rand(circ_nonce, sizeof(circ_nonce));
helper_prepare_circ_for_intro(intro_circ, circ_nonce);
/* Send legacy establish_intro */
key1 = pk_generate(0);
/* Use old circ_nonce why not */
cell_len = rend_service_encode_establish_intro_cell(
(char*)cell_body,
sizeof(cell_body), key1,
circ_nonce);
tt_int_op(cell_len, OP_GT, 0);
/* Receive legacy establish_intro */
retval = hs_intro_received_establish_intro(intro_circ,
cell_body, (size_t) cell_len);
tt_int_op(retval, OP_EQ, 0);
done:
return key1;
}
/* Helper function: test circuitmap free_all function outside of
* test_intro_point_registration to prevent Coverity from seeing a
* double free if the assertion hypothetically fails.
@@ -576,16 +540,12 @@ test_circuitmap_free_all(void)
static void
test_intro_point_registration(void *arg)
{
int retval;
hs_circuitmap_ht *the_hs_circuitmap = NULL;
or_circuit_t *intro_circ = NULL;
trn_cell_establish_intro_t *establish_intro_cell = NULL;
ed25519_public_key_t auth_key;
crypto_pk_t *legacy_auth_key = NULL;
or_circuit_t *legacy_intro_circ = NULL;
or_circuit_t *returned_intro_circ = NULL;
(void) arg;
@@ -621,35 +581,11 @@ test_intro_point_registration(void *arg)
tt_ptr_op(intro_circ, OP_EQ, returned_intro_circ);
}
/* Create a v2 intro point */
{
char key_digest[DIGEST_LEN];
legacy_intro_circ = or_circuit_new(1, NULL);
tt_assert(legacy_intro_circ);
legacy_auth_key = helper_establish_intro_v2(legacy_intro_circ);
tt_assert(legacy_auth_key);
/* Check that the circuitmap now has two elements */
the_hs_circuitmap = get_hs_circuitmap();
tt_assert(the_hs_circuitmap);
tt_int_op(2, OP_EQ, HT_SIZE(the_hs_circuitmap));
/* Check that the new element is our legacy intro circuit. */
retval = crypto_pk_get_digest(legacy_auth_key, key_digest);
tt_int_op(retval, OP_EQ, 0);
returned_intro_circ =
hs_circuitmap_get_intro_circ_v2_relay_side((uint8_t*)key_digest);
tt_ptr_op(legacy_intro_circ, OP_EQ, returned_intro_circ);
}
/* XXX Continue test and try to register a second v3 intro point with the
* same auth key. Make sure that old intro circuit gets closed. */
done:
crypto_pk_free(legacy_auth_key);
circuit_free_(TO_CIRCUIT(intro_circ));
circuit_free_(TO_CIRCUIT(legacy_intro_circ));
trn_cell_establish_intro_free(establish_intro_cell);
test_circuitmap_free_all();
+1 -4
View File
@@ -403,10 +403,7 @@ test_load_keys(void *arg)
tor_asprintf(&conf, conf_fmt, hsdir_v2, HS_VERSION_TWO);
ret = helper_config_service(conf);
tor_free(conf);
tt_int_op(ret, OP_EQ, 0);
/* This one should now be registered into the v2 list. */
tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 0);
tt_int_op(rend_num_services(), OP_EQ, 1);
tt_int_op(ret, OP_EQ, -1);
/* v3 service. */
tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);