mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
test: Unit test for the SOCKS5 HS client auth errors
Part of #30382 Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
68a004d147
commit
c0dd5324b3
@ -25,6 +25,7 @@
|
||||
#include "app/config/config.h"
|
||||
#include "lib/crypt_ops/crypto_cipher.h"
|
||||
#include "lib/crypt_ops/crypto_dh.h"
|
||||
#include "lib/crypt_ops/crypto_rand.h"
|
||||
#include "core/or/channeltls.h"
|
||||
#include "feature/dircommon/directory.h"
|
||||
#include "core/mainloop/mainloop.h"
|
||||
@ -92,6 +93,24 @@ helper_config_client(const char *conf, int validate_only)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
helper_add_random_client_auth(const ed25519_public_key_t *service_pk)
|
||||
{
|
||||
char *conf = NULL;
|
||||
#define conf_fmt "ClientOnionAuthDir %s\n"
|
||||
tor_asprintf(&conf, conf_fmt, get_fname("auth_keys"));
|
||||
#undef conf_fmt
|
||||
helper_config_client(conf, 0);
|
||||
tor_free(conf);
|
||||
|
||||
digest256map_t *client_auths = get_hs_client_auths_map();
|
||||
hs_client_service_authorization_t *auth =
|
||||
tor_malloc_zero(sizeof(hs_client_service_authorization_t));
|
||||
curve25519_secret_key_generate(&auth->enc_seckey, 0);
|
||||
hs_build_address(service_pk, HS_VERSION_THREE, auth->onion_address);
|
||||
digest256map_set(client_auths, service_pk->pubkey, auth);
|
||||
}
|
||||
|
||||
/* 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
|
||||
@ -550,6 +569,17 @@ mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason,
|
||||
conn->edge_.base_.marked_for_close = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
mock_connection_mark_unattached_ap_no_close(entry_connection_t *conn,
|
||||
int endreason, int line,
|
||||
const char *file)
|
||||
{
|
||||
(void) conn;
|
||||
(void) endreason;
|
||||
(void) line;
|
||||
(void) file;
|
||||
}
|
||||
|
||||
static void
|
||||
test_descriptor_fetch(void *arg)
|
||||
{
|
||||
@ -1094,6 +1124,108 @@ test_close_intro_circuits_cache_clean(void *arg)
|
||||
UNMOCK(networkstatus_get_live_consensus);
|
||||
}
|
||||
|
||||
static void
|
||||
test_socks_hs_errors(void *arg)
|
||||
{
|
||||
int ret;
|
||||
char *desc_encoded = NULL;
|
||||
ed25519_keypair_t service_kp;
|
||||
ed25519_keypair_t signing_kp;
|
||||
entry_connection_t *socks_conn = NULL;
|
||||
dir_connection_t *dir_conn = NULL;
|
||||
hs_descriptor_t *desc = NULL;
|
||||
uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
|
||||
|
||||
(void) arg;
|
||||
|
||||
MOCK(networkstatus_get_live_consensus,
|
||||
mock_networkstatus_get_live_consensus);
|
||||
MOCK(connection_mark_unattached_ap_,
|
||||
mock_connection_mark_unattached_ap_no_close);
|
||||
MOCK(read_file_to_str, mock_read_file_to_str);
|
||||
MOCK(tor_listdir, mock_tor_listdir);
|
||||
MOCK(check_private_dir, mock_check_private_dir);
|
||||
|
||||
/* Set consensus time */
|
||||
parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
|
||||
&mock_ns.valid_after);
|
||||
parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
|
||||
&mock_ns.fresh_until);
|
||||
parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
|
||||
&mock_ns.valid_until);
|
||||
|
||||
hs_init();
|
||||
|
||||
ret = ed25519_keypair_generate(&service_kp, 0);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
ret = ed25519_keypair_generate(&signing_kp, 0);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
|
||||
socks_conn = helper_build_socks_connection(&service_kp.pubkey,
|
||||
AP_CONN_STATE_RENDDESC_WAIT);
|
||||
tt_assert(socks_conn);
|
||||
|
||||
/* Create directory connection. */
|
||||
dir_conn = dir_connection_new(AF_INET);
|
||||
dir_conn->hs_ident = tor_malloc_zero(sizeof(hs_ident_dir_conn_t));
|
||||
TO_CONN(dir_conn)->purpose = DIR_PURPOSE_FETCH_HSDESC;
|
||||
ed25519_pubkey_copy(&dir_conn->hs_ident->identity_pk, &service_kp.pubkey);
|
||||
|
||||
/* Encode descriptor so we can decode it. */
|
||||
desc = hs_helper_build_hs_desc_with_ip(&service_kp);
|
||||
tt_assert(desc);
|
||||
|
||||
crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
|
||||
ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
|
||||
&desc_encoded);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
tt_assert(desc_encoded);
|
||||
|
||||
/* Try decoding. Point this to an existing descriptor. The following should
|
||||
* fail thus the desc_out should be set to NULL. */
|
||||
hs_descriptor_t *desc_out = desc;
|
||||
ret = hs_client_decode_descriptor(desc_encoded, &service_kp.pubkey,
|
||||
&desc_out);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
|
||||
tt_assert(desc_out == NULL);
|
||||
|
||||
/* The caching will fail to decrypt because the descriptor_cookie used above
|
||||
* is not known to the HS subsystem. This will lead to a missing client
|
||||
* auth. */
|
||||
hs_client_dir_fetch_done(dir_conn, "Reason", desc_encoded, 200);
|
||||
|
||||
tt_int_op(socks_conn->socks_request->socks_extended_error_code, OP_EQ,
|
||||
SOCKS5_HS_MISSING_CLIENT_AUTH);
|
||||
|
||||
/* Add in the global client auth list bad creds for this service. */
|
||||
helper_add_random_client_auth(&service_kp.pubkey);
|
||||
|
||||
ret = hs_client_decode_descriptor(desc_encoded, &service_kp.pubkey,
|
||||
&desc_out);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_BAD_CLIENT_AUTH);
|
||||
tt_assert(desc_out == NULL);
|
||||
|
||||
/* Simmulate a fetch done again. This should replace the cached descriptor
|
||||
* and signal a bad client authorization. */
|
||||
hs_client_dir_fetch_done(dir_conn, "Reason", desc_encoded, 200);
|
||||
tt_int_op(socks_conn->socks_request->socks_extended_error_code, OP_EQ,
|
||||
SOCKS5_HS_BAD_CLIENT_AUTH);
|
||||
|
||||
done:
|
||||
connection_free_minimal(ENTRY_TO_CONN(socks_conn));
|
||||
connection_free_minimal(TO_CONN(dir_conn));
|
||||
hs_descriptor_free(desc);
|
||||
tor_free(desc_encoded);
|
||||
|
||||
hs_free_all();
|
||||
|
||||
UNMOCK(networkstatus_get_live_consensus);
|
||||
UNMOCK(connection_mark_unattached_ap_);
|
||||
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 },
|
||||
@ -1116,5 +1248,8 @@ struct testcase_t hs_client_tests[] = {
|
||||
{ "close_intro_circuits_cache_clean", test_close_intro_circuits_cache_clean,
|
||||
TT_FORK, NULL, NULL },
|
||||
|
||||
/* SOCKS5 Extended Error Code. */
|
||||
{ "socks_hs_errors", test_socks_hs_errors, TT_FORK, NULL, NULL },
|
||||
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user