mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-14 07:03:44 +01:00
518 lines
15 KiB
C
518 lines
15 KiB
C
/* Copyright (c) 2016-2019, 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
|
|
|
|
#include "test/test.h"
|
|
#include "test/test_helpers.h"
|
|
#include "test/log_test_helpers.h"
|
|
|
|
#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();
|
|
}
|
|
|
|
/* 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;
|
|
|
|
/* 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:
|
|
;
|
|
}
|
|
|
|
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;
|
|
|
|
/* 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:
|
|
;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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 },
|
|
|
|
END_OF_TESTCASES
|
|
};
|
|
|