test: HS v3 client authorization loading secret key

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
Suphanat Chunhapanya 2018-08-19 08:26:43 +07:00 committed by David Goulet
parent 8e81fcd51a
commit 9c36219236
3 changed files with 197 additions and 2 deletions

View File

@ -1428,7 +1428,7 @@ client_service_authorization_free_all(void)
/* Check if the auth key file name is valid or not. Return 1 if valid,
* otherwise return 0. */
static int
STATIC int
auth_key_filename_is_valid(const char *filename)
{
int ret = 1;
@ -1448,7 +1448,7 @@ auth_key_filename_is_valid(const char *filename)
return ret;
}
static hs_client_service_authorization_t *
STATIC hs_client_service_authorization_t *
parse_auth_file_content(const char *client_key_str)
{
char *onion_address = NULL;
@ -1836,3 +1836,13 @@ hs_client_dir_info_changed(void)
* AP_CONN_STATE_RENDDESC_WAIT state in order to fetch the descriptor. */
retry_all_socks_conn_waiting_for_desc();
}
#ifdef TOR_UNIT_TESTS
STATIC digest256map_t *
get_hs_client_auths_map(void)
{
return client_auths;
}
#endif /* defined(TOR_UNIT_TESTS) */

View File

@ -84,6 +84,11 @@ void hs_client_free_all(void);
#ifdef HS_CLIENT_PRIVATE
STATIC int auth_key_filename_is_valid(const char *filename);
STATIC hs_client_service_authorization_t *
parse_auth_file_content(const char *client_key_str);
STATIC routerstatus_t *
pick_hsdir_v3(const ed25519_public_key_t *onion_identity_pk);
@ -99,6 +104,12 @@ STATIC int handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
MOCK_DECL(STATIC hs_client_fetch_status_t,
fetch_v3_desc, (const ed25519_public_key_t *onion_identity_pk));
#ifdef TOR_UNIT_TESTS
STATIC digest256map_t *get_hs_client_auths_map(void);
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* defined(HS_CLIENT_PRIVATE) */
#endif /* !defined(TOR_HS_CLIENT_H) */

View File

@ -6,6 +6,7 @@
* \brief Test prop224 HS client functionality.
*/
#define CONFIG_PRIVATE
#define CRYPTO_PRIVATE
#define MAIN_PRIVATE
#define HS_CLIENT_PRIVATE
@ -32,6 +33,7 @@
#include "feature/hs/hs_circuit.h"
#include "feature/hs/hs_circuitmap.h"
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_config.h"
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_cache.h"
#include "core/or/circuitlist.h"
@ -73,6 +75,20 @@ mock_networkstatus_get_live_consensus(time_t now)
return &mock_ns;
}
static int
helper_config_client(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_client_auth_all(options, validate_only);
done:
or_options_free(options);
return ret;
}
/* Test helper function: Setup a circuit and a stream with the same hidden
* service destination, and put them in <b>circ_out</b> and
* <b>conn_out</b>. Make the stream wait for circuits to be established to the
@ -601,6 +617,158 @@ test_descriptor_fetch(void *arg)
hs_free_all();
}
static void
test_auth_key_filename_is_valid(void *arg)
{
(void) arg;
/* Valid file name. */
tt_assert(auth_key_filename_is_valid("a.auth_private"));
/* Valid file name with special character. */
tt_assert(auth_key_filename_is_valid("a-.auth_private"));
/* Invalid extension. */
tt_assert(!auth_key_filename_is_valid("a.ath_private"));
/* Nothing before the extension. */
tt_assert(!auth_key_filename_is_valid(".auth_private"));
done:
;
}
static void
test_parse_auth_file_content(void *arg)
{
hs_client_service_authorization_t *auth = NULL;
(void) arg;
/* Valid authorized client. */
auth = parse_auth_file_content(
"4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:"
"x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq");
tt_assert(auth);
/* Wrong number of fields. */
tt_assert(!parse_auth_file_content("a:b"));
/* Wrong auth type. */
tt_assert(!parse_auth_file_content(
"4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:x:"
"x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq"));
/* Wrong key type. */
tt_assert(!parse_auth_file_content(
"4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:"
"x:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq"));
/* Some malformed string. */
tt_assert(!parse_auth_file_content("xx:descriptor:x25519:aa=="));
done:
tor_free(auth);
}
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("auth_keys" PATH_SEPARATOR
"client1.auth_private"))) {
ret = tor_strdup(
"4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:"
"x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq");
goto done;
}
if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR "dummy.xxx"))) {
ret = tor_strdup(
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:descriptor:"
"x25519:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
goto done;
}
if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR
"client2.auth_private"))) {
ret = tor_strdup(
"25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid:descriptor:"
"x25519:fdreqzjqso7d2ac7qscrxfl5qfpamdvgy5d6cxejcgzc3hvhurmq");
goto done;
}
done:
return ret;
}
static int
mock_check_private_dir(const char *dirname, cpd_check_t check,
const char *effective_user)
{
(void) dirname;
(void) check;
(void) effective_user;
return 0;
}
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_private"));
smartlist_add(file_list, tor_strdup("dummy.xxx"));
smartlist_add(file_list, tor_strdup("client2.auth_private"));
return file_list;
}
static void
test_config_client_authorization(void *arg)
{
int ret;
char *conf = NULL;
ed25519_public_key_t pk1, pk2;
digest256map_t *global_map = NULL;
char *key_dir = tor_strdup(get_fname("auth_keys"));
(void) arg;
MOCK(read_file_to_str, mock_read_file_to_str);
MOCK(tor_listdir, mock_tor_listdir);
MOCK(check_private_dir, mock_check_private_dir);
#define conf_fmt \
"ClientOnionAuthDir %s\n"
tor_asprintf(&conf, conf_fmt, key_dir);
ret = helper_config_client(conf, 0);
tor_free(conf);
tt_int_op(ret, OP_EQ, 0);
#undef conf_fmt
global_map = get_hs_client_auths_map();
tt_int_op(digest256map_size(global_map), OP_EQ, 2);
hs_parse_address("4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad",
&pk1, NULL, NULL);
hs_parse_address("25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid",
&pk2, NULL, NULL);
tt_assert(digest256map_get(global_map, pk1.pubkey));
tt_assert(digest256map_get(global_map, pk2.pubkey));
done:
tor_free(key_dir);
hs_free_all();
UNMOCK(read_file_to_str);
UNMOCK(tor_listdir);
UNMOCK(check_private_dir);
}
struct testcase_t hs_client_tests[] = {
{ "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy,
TT_FORK, NULL, NULL },
@ -610,5 +778,11 @@ struct testcase_t hs_client_tests[] = {
TT_FORK, NULL, NULL },
{ "descriptor_fetch", test_descriptor_fetch,
TT_FORK, NULL, NULL },
{ "auth_key_filename_is_valid", test_auth_key_filename_is_valid, TT_FORK,
NULL, NULL },
{ "parse_auth_file_content", test_parse_auth_file_content, TT_FORK,
NULL, NULL },
{ "config_client_authorization", test_config_client_authorization,
TT_FORK, NULL, NULL },
END_OF_TESTCASES
};