mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 07:07:52 +01:00
test: HS v3 loading client auth keys service side
Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
b894b40e64
commit
15af47ede0
3 changed files with 202 additions and 2 deletions
|
@ -1091,7 +1091,7 @@ load_service_keys(hs_service_t *service)
|
||||||
|
|
||||||
/* Check if the client file name is valid or not. Return 1 if valid,
|
/* Check if the client file name is valid or not. Return 1 if valid,
|
||||||
* otherwise return 0. */
|
* otherwise return 0. */
|
||||||
static int
|
STATIC int
|
||||||
client_filename_is_valid(const char *filename)
|
client_filename_is_valid(const char *filename)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
@ -1120,7 +1120,7 @@ client_filename_is_valid(const char *filename)
|
||||||
* The <key-type> can only be "x25519".
|
* The <key-type> can only be "x25519".
|
||||||
*
|
*
|
||||||
* Return the key on success, return NULL, otherwise. */
|
* Return the key on success, return NULL, otherwise. */
|
||||||
static hs_service_authorized_client_t *
|
STATIC hs_service_authorized_client_t *
|
||||||
parse_authorized_client(const char *client_key_str)
|
parse_authorized_client(const char *client_key_str)
|
||||||
{
|
{
|
||||||
char *auth_type = NULL;
|
char *auth_type = NULL;
|
||||||
|
|
|
@ -349,6 +349,9 @@ STATIC hs_service_descriptor_t *service_desc_find_by_intro(
|
||||||
const hs_service_t *service,
|
const hs_service_t *service,
|
||||||
const hs_service_intro_point_t *ip);
|
const hs_service_intro_point_t *ip);
|
||||||
/* Helper functions. */
|
/* Helper functions. */
|
||||||
|
STATIC int client_filename_is_valid(const char *filename);
|
||||||
|
STATIC hs_service_authorized_client_t *
|
||||||
|
parse_authorized_client(const char *client_key_str);
|
||||||
STATIC void get_objects_from_ident(const hs_ident_circuit_t *ident,
|
STATIC void get_objects_from_ident(const hs_ident_circuit_t *ident,
|
||||||
hs_service_t **service,
|
hs_service_t **service,
|
||||||
hs_service_intro_point_t **ip,
|
hs_service_intro_point_t **ip,
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "core/or/circuitlist.h"
|
#include "core/or/circuitlist.h"
|
||||||
#include "core/or/circuituse.h"
|
#include "core/or/circuituse.h"
|
||||||
#include "lib/crypt_ops/crypto_rand.h"
|
#include "lib/crypt_ops/crypto_rand.h"
|
||||||
|
#include "lib/fs/dir.h"
|
||||||
#include "feature/dirauth/dirvote.h"
|
#include "feature/dirauth/dirvote.h"
|
||||||
#include "feature/nodelist/networkstatus.h"
|
#include "feature/nodelist/networkstatus.h"
|
||||||
#include "feature/nodelist/nodelist.h"
|
#include "feature/nodelist/nodelist.h"
|
||||||
|
@ -65,6 +66,13 @@
|
||||||
/* Trunnel */
|
/* Trunnel */
|
||||||
#include "trunnel/hs/cell_establish_intro.h"
|
#include "trunnel/hs/cell_establish_intro.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static networkstatus_t mock_ns;
|
static networkstatus_t mock_ns;
|
||||||
|
|
||||||
static networkstatus_t *
|
static networkstatus_t *
|
||||||
|
@ -303,6 +311,8 @@ test_load_keys(void *arg)
|
||||||
/* It's in staging? */
|
/* It's in staging? */
|
||||||
tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
|
tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
|
||||||
|
|
||||||
|
#undef conf_fmt
|
||||||
|
|
||||||
/* Load the keys for these. After that, the v3 service should be registered
|
/* Load the keys for these. After that, the v3 service should be registered
|
||||||
* in the global map. */
|
* in the global map. */
|
||||||
hs_service_load_all_keys();
|
hs_service_load_all_keys();
|
||||||
|
@ -322,12 +332,193 @@ test_load_keys(void *arg)
|
||||||
tt_int_op(hs_address_is_valid(addr), OP_EQ, 1);
|
tt_int_op(hs_address_is_valid(addr), OP_EQ, 1);
|
||||||
tt_str_op(addr, OP_EQ, s->onion_address);
|
tt_str_op(addr, OP_EQ, s->onion_address);
|
||||||
|
|
||||||
|
/* Check that the is_client_auth_enabled is not set. */
|
||||||
|
tt_assert(!s->config.is_client_auth_enabled);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
tor_free(hsdir_v2);
|
tor_free(hsdir_v2);
|
||||||
tor_free(hsdir_v3);
|
tor_free(hsdir_v3);
|
||||||
hs_free_all();
|
hs_free_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_client_filename_is_valid(void *arg)
|
||||||
|
{
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
/* Valid file name. */
|
||||||
|
tt_assert(client_filename_is_valid("a.auth"));
|
||||||
|
/* Valid file name with special character. */
|
||||||
|
tt_assert(client_filename_is_valid("a-.auth"));
|
||||||
|
/* Invalid extension. */
|
||||||
|
tt_assert(!client_filename_is_valid("a.ath"));
|
||||||
|
/* Nothing before the extension. */
|
||||||
|
tt_assert(!client_filename_is_valid(".auth"));
|
||||||
|
|
||||||
|
done:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_parse_authorized_client(void *arg)
|
||||||
|
{
|
||||||
|
hs_service_authorized_client_t *client = NULL;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
/* Valid authorized client. */
|
||||||
|
client = parse_authorized_client(
|
||||||
|
"descriptor:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja");
|
||||||
|
tt_assert(client);
|
||||||
|
|
||||||
|
/* Wrong number of fields. */
|
||||||
|
tt_assert(!parse_authorized_client("a:b:c:d:e"));
|
||||||
|
/* Wrong auth type. */
|
||||||
|
tt_assert(!parse_authorized_client(
|
||||||
|
"x:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
|
||||||
|
/* Wrong key type. */
|
||||||
|
tt_assert(!parse_authorized_client(
|
||||||
|
"descriptor:x:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
|
||||||
|
/* Some malformed string. */
|
||||||
|
tt_assert(!parse_authorized_client("descriptor:x25519:aa=="));
|
||||||
|
tt_assert(!parse_authorized_client("descriptor:"));
|
||||||
|
tt_assert(!parse_authorized_client("descriptor:x25519"));
|
||||||
|
tt_assert(!parse_authorized_client("descriptor:x25519:"));
|
||||||
|
tt_assert(!parse_authorized_client(""));
|
||||||
|
|
||||||
|
done:
|
||||||
|
service_authorized_client_free(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out)
|
||||||
|
{
|
||||||
|
char *ret = NULL;
|
||||||
|
|
||||||
|
(void) flags;
|
||||||
|
(void) stat_out;
|
||||||
|
|
||||||
|
if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
|
||||||
|
"authorized_clients" PATH_SEPARATOR
|
||||||
|
"client1.auth"))) {
|
||||||
|
ret = tor_strdup("descriptor:x25519:"
|
||||||
|
"dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
|
||||||
|
"authorized_clients" PATH_SEPARATOR
|
||||||
|
"dummy.xxx"))) {
|
||||||
|
ret = tor_strdup("descriptor:x25519:"
|
||||||
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
|
||||||
|
"authorized_clients" PATH_SEPARATOR
|
||||||
|
"client2.auth"))) {
|
||||||
|
ret = tor_strdup("descriptor:x25519:"
|
||||||
|
"okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static smartlist_t *
|
||||||
|
mock_tor_listdir(const char *dirname)
|
||||||
|
{
|
||||||
|
smartlist_t *file_list = smartlist_new();
|
||||||
|
|
||||||
|
(void) dirname;
|
||||||
|
|
||||||
|
smartlist_add(file_list, tor_strdup("client1.auth"));
|
||||||
|
smartlist_add(file_list, tor_strdup("dummy.xxx"));
|
||||||
|
smartlist_add(file_list, tor_strdup("client2.auth"));
|
||||||
|
|
||||||
|
return file_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_load_keys_with_client_auth(void *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *conf = NULL;
|
||||||
|
smartlist_t *pubkey_b32_list = smartlist_new();
|
||||||
|
char *hsdir_v3 = tor_strdup(get_fname("hs3"));
|
||||||
|
hs_service_t *service;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
hs_init();
|
||||||
|
smartlist_add(pubkey_b32_list, tor_strdup(
|
||||||
|
"dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
|
||||||
|
smartlist_add(pubkey_b32_list, tor_strdup(
|
||||||
|
"okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta"));
|
||||||
|
|
||||||
|
#define conf_fmt \
|
||||||
|
"HiddenServiceDir %s\n" \
|
||||||
|
"HiddenServiceVersion %d\n" \
|
||||||
|
"HiddenServicePort 65534\n"
|
||||||
|
|
||||||
|
tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);
|
||||||
|
ret = helper_config_service(conf);
|
||||||
|
tor_free(conf);
|
||||||
|
tt_int_op(ret, OP_EQ, 0);
|
||||||
|
/* It's in staging? */
|
||||||
|
tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
|
||||||
|
|
||||||
|
#undef conf_fmt
|
||||||
|
|
||||||
|
MOCK(read_file_to_str, mock_read_file_to_str);
|
||||||
|
MOCK(tor_listdir, mock_tor_listdir);
|
||||||
|
|
||||||
|
/* Load the keys for these. After that, the v3 service should be registered
|
||||||
|
* in the global map. */
|
||||||
|
hs_service_load_all_keys();
|
||||||
|
tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
|
||||||
|
|
||||||
|
service = get_first_service();
|
||||||
|
tt_assert(service->config.clients);
|
||||||
|
tt_int_op(smartlist_len(service->config.clients), OP_EQ,
|
||||||
|
smartlist_len(pubkey_b32_list));
|
||||||
|
|
||||||
|
/* Test that the is_client_auth_enabled flag is set. */
|
||||||
|
tt_assert(service->config.is_client_auth_enabled);
|
||||||
|
|
||||||
|
/* Test that the keys in clients are correct. */
|
||||||
|
SMARTLIST_FOREACH_BEGIN(pubkey_b32_list, char *, pubkey_b32) {
|
||||||
|
|
||||||
|
curve25519_public_key_t pubkey;
|
||||||
|
/* This flag will be set if the key is found in clients. */
|
||||||
|
int is_found = 0;
|
||||||
|
base32_decode((char *) pubkey.public_key, sizeof(pubkey.public_key),
|
||||||
|
pubkey_b32, strlen(pubkey_b32));
|
||||||
|
|
||||||
|
SMARTLIST_FOREACH_BEGIN(service->config.clients,
|
||||||
|
hs_service_authorized_client_t *, client) {
|
||||||
|
if (tor_memeq(&pubkey, &client->client_pk, sizeof(pubkey))) {
|
||||||
|
is_found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} SMARTLIST_FOREACH_END(client);
|
||||||
|
|
||||||
|
tt_assert(is_found);
|
||||||
|
|
||||||
|
} SMARTLIST_FOREACH_END(pubkey_b32);
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (pubkey_b32_list) {
|
||||||
|
SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s));
|
||||||
|
}
|
||||||
|
smartlist_free(pubkey_b32_list);
|
||||||
|
tor_free(hsdir_v3);
|
||||||
|
hs_free_all();
|
||||||
|
UNMOCK(read_file_to_str);
|
||||||
|
UNMOCK(tor_listdir);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_access_service(void *arg)
|
test_access_service(void *arg)
|
||||||
{
|
{
|
||||||
|
@ -1561,6 +1752,12 @@ struct testcase_t hs_service_tests[] = {
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "load_keys", test_load_keys, TT_FORK,
|
{ "load_keys", test_load_keys, TT_FORK,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
|
{ "client_filename_is_valid", test_client_filename_is_valid, TT_FORK,
|
||||||
|
NULL, NULL },
|
||||||
|
{ "parse_authorized_client", test_parse_authorized_client, TT_FORK,
|
||||||
|
NULL, NULL },
|
||||||
|
{ "load_keys_with_client_auth", test_load_keys_with_client_auth, TT_FORK,
|
||||||
|
NULL, NULL },
|
||||||
{ "access_service", test_access_service, TT_FORK,
|
{ "access_service", test_access_service, TT_FORK,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "service_intro_point", test_service_intro_point, TT_FORK,
|
{ "service_intro_point", test_service_intro_point, TT_FORK,
|
||||||
|
|
Loading…
Add table
Reference in a new issue