test: Add tests for fetching descs and handling SOCKS conns.

- Add tests that ensure that SOCKS requests for v2/v3 addresses get
  intercepted and handled.

- Add test that stores and lookups an HS descriptor in the client-side cache.

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
George Kadianakis 2017-06-01 14:35:39 +03:00 committed by David Goulet
parent 79ff2e014f
commit 6eb9de1b8c
4 changed files with 164 additions and 11 deletions

View File

@ -2203,16 +2203,6 @@ load_downloaded_routers(const char *body, smartlist_t *which,
return added;
}
/** A structure to hold arguments passed into each directory response
* handler */
typedef struct response_handler_args_t {
int status_code;
const char *reason;
const char *body;
size_t body_len;
const char *headers;
} response_handler_args_t;
static int handle_response_fetch_consensus(dir_connection_t *,
const response_handler_args_t *);
static int handle_response_fetch_certificate(dir_connection_t *,

View File

@ -168,6 +168,16 @@ int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
#ifdef DIRECTORY_PRIVATE
/** A structure to hold arguments passed into each directory response
* handler */
typedef struct response_handler_args_t {
int status_code;
const char *reason;
const char *body;
size_t body_len;
const char *headers;
} response_handler_args_t;
struct get_handler_args_t;
STATIC int handle_get_hs_descriptor_v3(dir_connection_t *conn,
const struct get_handler_args_t *args);
@ -183,7 +193,7 @@ STATIC int handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
#endif
#ifdef TOR_UNIT_TESTS
/* Used only by test_dir.c */
/* Used only by test_dir.c and test_hs_cache.c */
STATIC int parse_http_url(const char *headers, char **url);
STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose,

View File

@ -14,6 +14,10 @@
#include "confparse.h"
#include "connection.h"
#include "connection_edge.h"
#include "nodelist.h"
#include "hs_cache.h"
#include "rendcache.h"
static void *
entryconn_rewrite_setup(const struct testcase_t *tc)
@ -743,6 +747,87 @@ test_entryconn_rewrite_mapaddress_automap_onion4(void *arg)
test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 0, 1);
}
/** Test that rewrite functions can handle v2 addresses */
static void
test_entryconn_rewrite_onion_v2(void *arg)
{
int retval;
entry_connection_t *conn = arg;
(void) arg;
rend_cache_init();
/* Make a SOCKS request */
conn->socks_request->command = SOCKS_COMMAND_CONNECT;
strlcpy(conn->socks_request->address,
"pqeed46efnwmfuid.onion",
sizeof(conn->socks_request->address));
/* Make an onion connection using the SOCKS request */
conn->entry_cfg.onion_traffic = 1;
ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_SOCKS_WAIT;
tt_assert(!ENTRY_TO_EDGE_CONN(conn)->rend_data);
/* Handle SOCKS and rewrite! */
retval = connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL);
tt_int_op(retval, OP_EQ, 0);
/* Check connection state after rewrite */
tt_int_op(ENTRY_TO_CONN(conn)->state, OP_EQ, AP_CONN_STATE_RENDDESC_WAIT);
/* check that the address got rewritten */
tt_str_op(conn->socks_request->address, OP_EQ,
"pqeed46efnwmfuid");
/* check that HS information got attached to the connection */
tt_assert(ENTRY_TO_EDGE_CONN(conn)->rend_data);
tt_assert(!ENTRY_TO_EDGE_CONN(conn)->hs_ident);
done:
rend_cache_free_all();
/* 'conn' is cleaned by handler */
}
/** Test that rewrite functions can handle v3 onion addresses */
static void
test_entryconn_rewrite_onion_v3(void *arg)
{
int retval;
entry_connection_t *conn = arg;
(void) arg;
hs_cache_init();
/* Make a SOCKS request */
conn->socks_request->command = SOCKS_COMMAND_CONNECT;
strlcpy(conn->socks_request->address,
"git.p3xnclpu4mu22dwaurjtsybyqk4xfjmcfz6z62yl24uwmhjatiwnlnad.onion",
sizeof(conn->socks_request->address));
/* Make an onion connection using the SOCKS request */
conn->entry_cfg.onion_traffic = 1;
ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_SOCKS_WAIT;
tt_assert(!ENTRY_TO_EDGE_CONN(conn)->rend_data);
tt_assert(!ENTRY_TO_EDGE_CONN(conn)->hs_ident);
/* Handle SOCKS and rewrite! */
retval = connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL);
tt_int_op(retval, OP_EQ, 0);
/* Check connection state after rewrite */
tt_int_op(ENTRY_TO_CONN(conn)->state, OP_EQ, AP_CONN_STATE_RENDDESC_WAIT);
/* check that the address got rewritten */
tt_str_op(conn->socks_request->address, OP_EQ,
"p3xnclpu4mu22dwaurjtsybyqk4xfjmcfz6z62yl24uwmhjatiwnlnad");
/* check that HS information got attached to the connection */
tt_assert(ENTRY_TO_EDGE_CONN(conn)->hs_ident);
tt_assert(!ENTRY_TO_EDGE_CONN(conn)->rend_data);
done:
hs_free_all();
/* 'conn' is cleaned by handler */
}
#define REWRITE(name) \
{ #name, test_entryconn_##name, TT_FORK, &test_rewrite_setup, NULL }
@ -763,6 +848,8 @@ struct testcase_t entryconn_tests[] = {
REWRITE(rewrite_mapaddress_automap_onion2),
REWRITE(rewrite_mapaddress_automap_onion3),
REWRITE(rewrite_mapaddress_automap_onion4),
REWRITE(rewrite_onion_v2),
REWRITE(rewrite_onion_v3),
END_OF_TESTCASES
};

View File

@ -7,6 +7,7 @@
*/
#define CONNECTION_PRIVATE
#define DIRECTORY_PRIVATE
#define HS_CACHE_PRIVATE
#include "ed25519_cert.h"
@ -431,6 +432,69 @@ test_hsdir_revision_counter_check(void *arg)
tor_free(published_desc_str);
}
/** Test that we can store HS descriptors in the client HS cache. */
static void
test_client_cache(void *arg)
{
int retval;
ed25519_keypair_t signing_kp;
hs_descriptor_t *published_desc = NULL;
char *published_desc_str = NULL;
response_handler_args_t *args = NULL;
dir_connection_t *conn = NULL;
(void) arg;
/* Initialize HSDir cache subsystem */
init_test();
/* Generate a valid descriptor with normal values. */
{
retval = ed25519_keypair_generate(&signing_kp, 0);
tt_int_op(retval, ==, 0);
published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
tt_assert(published_desc);
retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
&published_desc_str);
tt_int_op(retval, OP_EQ, 0);
}
/* Test handle_response_fetch_hsdesc_v3() */
{
args = tor_malloc_zero(sizeof(response_handler_args_t));
args->status_code = 200;
args->reason = NULL;
args->body = published_desc_str;
args->body_len = strlen(published_desc_str);
conn = tor_malloc_zero(sizeof(dir_connection_t));
conn->hs_ident = tor_malloc_zero(sizeof(hs_ident_dir_conn_t));
ed25519_pubkey_copy(&conn->hs_ident->identity_pk, &signing_kp.pubkey);
}
/* store the descriptor! */
retval = handle_response_fetch_hsdesc_v3(conn, args);
tt_int_op(retval, == , 0);
/* fetch the descriptor and make sure it's there */
{
hs_cache_client_descriptor_t *cached_desc = NULL;
cached_desc = lookup_v3_desc_as_client(signing_kp.pubkey.pubkey);
tt_assert(cached_desc);
tt_str_op(cached_desc->encoded_desc, OP_EQ, published_desc_str);
}
done:
tor_free(args);
hs_descriptor_free(published_desc);
tor_free(published_desc_str);
if (conn) {
tor_free(conn->hs_ident);
tor_free(conn);
}
}
struct testcase_t hs_cache[] = {
/* Encoding tests. */
{ "directory", test_directory, TT_FORK,
@ -441,6 +505,8 @@ struct testcase_t hs_cache[] = {
NULL, NULL },
{ "upload_and_download_hs_desc", test_upload_and_download_hs_desc, TT_FORK,
NULL, NULL },
{ "client_cache", test_client_cache, TT_FORK,
NULL, NULL },
END_OF_TESTCASES
};