tor/src/test/test_hs_config.c

629 lines
19 KiB
C
Raw Normal View History

/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file test_hs_config.c
* \brief Test hidden service configuration functionality.
*/
#define CONFIG_PRIVATE
#define HS_SERVICE_PRIVATE
2018-06-20 15:35:05 +02:00
#include "test/test.h"
#include "test/test_helpers.h"
#include "test/log_test_helpers.h"
#include "test/resolve_test_helpers.h"
2018-06-20 15:35:05 +02:00
#include "app/config/config.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_config.h"
#include "feature/hs/hs_service.h"
#include "feature/rend/rendservice.h"
static int
helper_config_service(const char *conf, int validate_only)
{
int ret = 0;
or_options_t *options = NULL;
tt_assert(conf);
options = helper_parse_options(conf);
tt_assert(options);
ret = hs_config_service_all(options, validate_only);
done:
or_options_free(options);
return ret;
}
static void
test_invalid_service(void *arg)
{
int ret;
(void) arg;
/* Try with a missing port configuration. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 1\n"; /* Wrong not supported version. */
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");
teardown_capture_of_logs();
}
/* Bad value of HiddenServiceAllowUnknownPorts. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceAllowUnknownPorts 2\n"; /* Should be 0 or 1. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceAllowUnknownPorts must be "
"between 0 and 1, not 2");
teardown_capture_of_logs();
}
/* Bad value of HiddenServiceDirGroupReadable */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceDirGroupReadable 2\n"; /* Should be 0 or 1. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceDirGroupReadable must be "
"between 0 and 1, not 2");
teardown_capture_of_logs();
}
/* Bad value of HiddenServiceMaxStreamsCloseCircuit */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServiceMaxStreamsCloseCircuit 2\n"; /* Should be 0 or 1. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceMaxStreamsCloseCircuit must "
"be between 0 and 1, not 2");
teardown_capture_of_logs();
}
/* Too much max streams. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80\n"
"HiddenServiceMaxStreams 65536\n"; /* One too many. */
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 1);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceMaxStreams must be between "
"0 and 65535, not 65536");
teardown_capture_of_logs();
}
/* Duplicate directory directive. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80\n"
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 81\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("Another hidden service is already "
"configured for directory");
teardown_capture_of_logs();
}
/* Bad port. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 65536\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("Missing or invalid port");
teardown_capture_of_logs();
}
2018-08-28 17:32:31 +02:00
/* Bad target addr:port separation. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 2\n"
"HiddenServicePort 80 127.0.0.1 8000\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("HiddenServicePort parse error: "
"invalid port mapping");
teardown_capture_of_logs();
}
/* Out of order directives. */
{
const char *conf =
"HiddenServiceVersion 2\n"
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServicePort 80\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 with no preceding "
"HiddenServiceDir directive");
teardown_capture_of_logs();
}
done:
;
}
static void
test_valid_service(void *arg)
{
int ret;
(void) arg;
/* 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:
;
}
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 should "
"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("HiddenServiceNumIntroductionPoints should "
"be between 0 and 10, not -1");
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)
{
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 3\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 3\n"
"HiddenServicePort 80\n"
"HiddenServiceNumIntroductionPoints 21\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 3 and 20, not 21.");
teardown_capture_of_logs();
}
/* Too little introduction points. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 3\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("HiddenServiceNumIntroductionPoints must "
"be between 3 and 20, not 1.");
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:
;
}
static void
test_valid_service_v3(void *arg)
{
int ret;
(void) arg;
mock_hostname_resolver();
/* Valid complex configuration. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 80\n"
"HiddenServicePort 22 localhost:22\n"
#ifdef HAVE_SYS_UN_H
"HiddenServicePort 42 unix:/path/to/socket\n"
#endif
"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. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n"
"HiddenServiceVersion 3\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
"HiddenServiceAllowUnknownPorts 0\n"
"HiddenServiceMaxStreams 42\n"
"HiddenServiceMaxStreamsCloseCircuit 0\n"
"HiddenServiceDirGroupReadable 1\n"
"HiddenServiceNumIntroductionPoints 20\n";
ret = helper_config_service(conf, 1);
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();
}
static void
test_staging_service_v3(void *arg)
{
int ret;
(void) arg;
/* We don't validate a service object, this is the service test that are in
* charge of doing so. We just check for the stable state after
* registration. */
hs_init();
/* Time for a valid v3 service that should get staged. */
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n"
"HiddenServiceVersion 3\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
"HiddenServiceAllowUnknownPorts 0\n"
"HiddenServiceMaxStreams 42\n"
"HiddenServiceMaxStreamsCloseCircuit 0\n"
"HiddenServiceDirGroupReadable 1\n"
"HiddenServiceNumIntroductionPoints 20\n";
ret = helper_config_service(conf, 0);
tt_int_op(ret, OP_EQ, 0);
/* Ok, we have a service in our map! Registration went well. */
tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
/* Make sure we don't have a magic v2 service out of this. */
tt_int_op(rend_num_services(), OP_EQ, 0);
done:
hs_free_all();
}
static void
test_dos_parameters(void *arg)
{
int ret;
(void) arg;
hs_init();
/* Valid configuration. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 22 1.1.1.1:22\n"
"HiddenServiceEnableIntroDoSDefense 1\n"
"HiddenServiceEnableIntroDoSRatePerSec 42\n"
"HiddenServiceEnableIntroDoSBurstPerSec 87\n";
setup_full_capture_of_logs(LOG_INFO);
ret = helper_config_service(conf, 0);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg_containing("Service INTRO2 DoS defenses rate set to: 42");
expect_log_msg_containing("Service INTRO2 DoS defenses burst set to: 87");
teardown_capture_of_logs();
}
/* Invalid rate. Value of 2^37. Max allowed is 2^31. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 22 1.1.1.1:22\n"
"HiddenServiceEnableIntroDoSDefense 1\n"
"HiddenServiceEnableIntroDoSRatePerSec 137438953472\n"
"HiddenServiceEnableIntroDoSBurstPerSec 87\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 0);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceEnableIntroDoSRatePerSec must "
"be between 0 and 2147483647, "
"not 137438953472");
teardown_capture_of_logs();
}
/* Invalid burst. Value of 2^38. Max allowed is 2^31. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 22 1.1.1.1:22\n"
"HiddenServiceEnableIntroDoSDefense 1\n"
"HiddenServiceEnableIntroDoSRatePerSec 42\n"
"HiddenServiceEnableIntroDoSBurstPerSec 274877906944\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 0);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceEnableIntroDoSBurstPerSec must "
"be between 0 and 2147483647, "
"not 274877906944");
teardown_capture_of_logs();
}
/* Burst is smaller than rate. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 22 1.1.1.1:22\n"
"HiddenServiceEnableIntroDoSDefense 1\n"
"HiddenServiceEnableIntroDoSRatePerSec 42\n"
"HiddenServiceEnableIntroDoSBurstPerSec 27\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 0);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("Hidden service DoS defenses burst (27) can "
"not be smaller than the rate value (42).");
teardown_capture_of_logs();
}
/* Negative value. */
{
const char *conf =
"HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
"HiddenServiceVersion 3\n"
"HiddenServicePort 22 1.1.1.1:22\n"
"HiddenServiceEnableIntroDoSDefense 1\n"
"HiddenServiceEnableIntroDoSRatePerSec -1\n"
"HiddenServiceEnableIntroDoSBurstPerSec 42\n";
setup_full_capture_of_logs(LOG_WARN);
ret = helper_config_service(conf, 0);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg_containing("HiddenServiceEnableIntroDoSRatePerSec must be "
"between 0 and 2147483647, not -1");
teardown_capture_of_logs();
}
done:
hs_free_all();
}
struct testcase_t hs_config_tests[] = {
/* Invalid service not specific to any version. */
{ "invalid_service", test_invalid_service, TT_FORK,
NULL, NULL },
{ "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 },
{ "valid_service_v3", test_valid_service_v3, TT_FORK,
NULL, NULL },
/* Test service staging. */
{ "staging_service_v3", test_staging_service_v3, TT_FORK,
NULL, NULL },
/* Test HS DoS parameters. */
{ "dos_parameters", test_dos_parameters, TT_FORK,
NULL, NULL },
END_OF_TESTCASES
};