mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
hs: Refactor rend_data_t for multi version support
In order to implement proposal 224, we need the data structure rend_data_t to be able to accomodate versionning that is the current version of hidden service (2) and the new version (3) and future version. For that, we implement a series of accessors and a downcast function to get the v2 data structure. rend_data_t becomes a top level generic place holder. The entire rend_data_t API has been moved to hs_common.{c|h} in order to seperate code that is shared from between HS versions and unshared code (in rendcommon.c). Closes #19024 Signed-off-by: David Goulet <dgoulet@torproject.org> Signed-off-by: George Kadianakis <desnacked@riseup.net>
This commit is contained in:
parent
8fe410e875
commit
8293356ad9
@ -23,6 +23,7 @@
|
||||
#include "connection_or.h"
|
||||
#include "control.h"
|
||||
#include "main.h"
|
||||
#include "hs_common.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "onion.h"
|
||||
@ -1311,9 +1312,11 @@ circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data)
|
||||
if (!circ->marked_for_close &&
|
||||
circ->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
|
||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||
if (ocirc->rend_data &&
|
||||
!rend_cmp_service_ids(rend_data->onion_address,
|
||||
ocirc->rend_data->onion_address) &&
|
||||
if (ocirc->rend_data == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (!rend_cmp_service_ids(rend_data_get_address(rend_data),
|
||||
rend_data_get_address(ocirc->rend_data)) &&
|
||||
tor_memeq(ocirc->rend_data->rend_cookie,
|
||||
rend_data->rend_cookie,
|
||||
REND_COOKIE_LEN))
|
||||
@ -1325,13 +1328,14 @@ circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data)
|
||||
}
|
||||
|
||||
/** Return the first circuit originating here in global_circuitlist after
|
||||
* <b>start</b> whose purpose is <b>purpose</b>, and where
|
||||
* <b>digest</b> (if set) matches the rend_pk_digest field. Return NULL if no
|
||||
* circuit is found. If <b>start</b> is NULL, begin at the start of the list.
|
||||
* <b>start</b> whose purpose is <b>purpose</b>, and where <b>digest</b> (if
|
||||
* set) matches the private key digest of the rend data associated with the
|
||||
* circuit. Return NULL if no circuit is found. If <b>start</b> is NULL,
|
||||
* begin at the start of the list.
|
||||
*/
|
||||
origin_circuit_t *
|
||||
circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
|
||||
const char *digest, uint8_t purpose)
|
||||
const uint8_t *digest, uint8_t purpose)
|
||||
{
|
||||
int idx;
|
||||
smartlist_t *lst = circuit_get_global_list();
|
||||
@ -1343,17 +1347,23 @@ circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
|
||||
|
||||
for ( ; idx < smartlist_len(lst); ++idx) {
|
||||
circuit_t *circ = smartlist_get(lst, idx);
|
||||
origin_circuit_t *ocirc;
|
||||
|
||||
if (circ->marked_for_close)
|
||||
continue;
|
||||
if (circ->purpose != purpose)
|
||||
continue;
|
||||
/* At this point we should be able to get a valid origin circuit because
|
||||
* the origin purpose we are looking for matches this circuit. */
|
||||
if (BUG(!CIRCUIT_PURPOSE_IS_ORIGIN(circ->purpose))) {
|
||||
break;
|
||||
}
|
||||
ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||
if (!digest)
|
||||
return TO_ORIGIN_CIRCUIT(circ);
|
||||
else if (TO_ORIGIN_CIRCUIT(circ)->rend_data &&
|
||||
tor_memeq(TO_ORIGIN_CIRCUIT(circ)->rend_data->rend_pk_digest,
|
||||
digest, DIGEST_LEN))
|
||||
return TO_ORIGIN_CIRCUIT(circ);
|
||||
return ocirc;
|
||||
if (rend_circuit_pk_digest_eq(ocirc, digest)) {
|
||||
return ocirc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -1831,7 +1841,7 @@ circuit_about_to_free(circuit_t *circ)
|
||||
if (orig_reason != END_CIRC_REASON_IP_NOW_REDUNDANT) {
|
||||
/* treat this like getting a nack from it */
|
||||
log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
|
||||
safe_str_client(ocirc->rend_data->onion_address),
|
||||
safe_str_client(rend_data_get_address(ocirc->rend_data)),
|
||||
safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
|
||||
timed_out ? "Recording timeout." : "Removing from descriptor.");
|
||||
rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
|
||||
@ -1848,7 +1858,7 @@ circuit_about_to_free(circuit_t *circ)
|
||||
log_info(LD_REND, "Failed intro circ %s to %s "
|
||||
"(building circuit to intro point). "
|
||||
"Marking intro point as possibly unreachable.",
|
||||
safe_str_client(ocirc->rend_data->onion_address),
|
||||
safe_str_client(rend_data_get_address(ocirc->rend_data)),
|
||||
safe_str_client(build_state_get_exit_nickname(
|
||||
ocirc->build_state)));
|
||||
rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
|
||||
|
@ -45,7 +45,7 @@ origin_circuit_t *circuit_get_by_global_id(uint32_t id);
|
||||
origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data(
|
||||
const rend_data_t *rend_data);
|
||||
origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
|
||||
const char *digest, uint8_t purpose);
|
||||
const uint8_t *digest, uint8_t purpose);
|
||||
or_circuit_t *circuit_get_rendezvous(const uint8_t *cookie);
|
||||
or_circuit_t *circuit_get_intro_point(const uint8_t *digest);
|
||||
void circuit_set_rendezvous_cookie(or_circuit_t *circ, const uint8_t *cookie);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "connection_edge.h"
|
||||
#include "control.h"
|
||||
#include "entrynodes.h"
|
||||
#include "hs_common.h"
|
||||
#include "nodelist.h"
|
||||
#include "networkstatus.h"
|
||||
#include "policies.h"
|
||||
@ -154,8 +155,8 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
|
||||
if ((edge_conn->rend_data && !origin_circ->rend_data) ||
|
||||
(!edge_conn->rend_data && origin_circ->rend_data) ||
|
||||
(edge_conn->rend_data && origin_circ->rend_data &&
|
||||
rend_cmp_service_ids(edge_conn->rend_data->onion_address,
|
||||
origin_circ->rend_data->onion_address))) {
|
||||
rend_cmp_service_ids(rend_data_get_address(edge_conn->rend_data),
|
||||
rend_data_get_address(origin_circ->rend_data)))) {
|
||||
/* this circ is not for this conn */
|
||||
return 0;
|
||||
}
|
||||
@ -1989,7 +1990,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
|
||||
if (!extend_info) {
|
||||
log_info(LD_REND,
|
||||
"No intro points for '%s': re-fetching service descriptor.",
|
||||
safe_str_client(rend_data->onion_address));
|
||||
safe_str_client(rend_data_get_address(rend_data)));
|
||||
rend_client_refetch_v2_renddesc(rend_data);
|
||||
connection_ap_mark_as_non_pending_circuit(conn);
|
||||
ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_RENDDESC_WAIT;
|
||||
@ -1997,7 +1998,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
|
||||
}
|
||||
log_info(LD_REND,"Chose %s as intro point for '%s'.",
|
||||
extend_info_describe(extend_info),
|
||||
safe_str_client(rend_data->onion_address));
|
||||
safe_str_client(rend_data_get_address(rend_data)));
|
||||
}
|
||||
|
||||
/* If we have specified a particular exit node for our
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "ext_orport.h"
|
||||
#include "geoip.h"
|
||||
#include "main.h"
|
||||
#include "hs_common.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "reasons.h"
|
||||
@ -4082,12 +4083,12 @@ connection_get_by_type_state_rendquery(int type, int state,
|
||||
(type == CONN_TYPE_DIR &&
|
||||
TO_DIR_CONN(conn)->rend_data &&
|
||||
!rend_cmp_service_ids(rendquery,
|
||||
TO_DIR_CONN(conn)->rend_data->onion_address))
|
||||
rend_data_get_address(TO_DIR_CONN(conn)->rend_data)))
|
||||
||
|
||||
(CONN_IS_EDGE(conn) &&
|
||||
TO_EDGE_CONN(conn)->rend_data &&
|
||||
!rend_cmp_service_ids(rendquery,
|
||||
TO_EDGE_CONN(conn)->rend_data->onion_address))
|
||||
rend_data_get_address(TO_EDGE_CONN(conn)->rend_data)))
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "dnsserv.h"
|
||||
#include "dirserv.h"
|
||||
#include "hibernate.h"
|
||||
#include "hs_common.h"
|
||||
#include "main.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
@ -1707,21 +1708,22 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
|
||||
if (rend_data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
const char *onion_address = rend_data_get_address(rend_data);
|
||||
log_info(LD_REND,"Got a hidden service request for ID '%s'",
|
||||
safe_str_client(rend_data->onion_address));
|
||||
safe_str_client(onion_address));
|
||||
|
||||
/* Lookup the given onion address. If invalid, stop right now else we
|
||||
* might have it in the cache or not, it will be tested later on. */
|
||||
unsigned int refetch_desc = 0;
|
||||
rend_cache_entry_t *entry = NULL;
|
||||
const int rend_cache_lookup_result =
|
||||
rend_cache_lookup_entry(rend_data->onion_address, -1, &entry);
|
||||
rend_cache_lookup_entry(onion_address, -1, &entry);
|
||||
if (rend_cache_lookup_result < 0) {
|
||||
switch (-rend_cache_lookup_result) {
|
||||
case EINVAL:
|
||||
/* We should already have rejected this address! */
|
||||
log_warn(LD_BUG,"Invalid service name '%s'",
|
||||
safe_str_client(rend_data->onion_address));
|
||||
safe_str_client(onion_address));
|
||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
||||
return -1;
|
||||
case ENOENT:
|
||||
@ -1745,7 +1747,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
|
||||
connection_ap_mark_as_non_pending_circuit(conn);
|
||||
base_conn->state = AP_CONN_STATE_RENDDESC_WAIT;
|
||||
log_info(LD_REND, "Unknown descriptor %s. Fetching.",
|
||||
safe_str_client(rend_data->onion_address));
|
||||
safe_str_client(onion_address));
|
||||
rend_client_refetch_v2_renddesc(rend_data);
|
||||
return 0;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "entrynodes.h"
|
||||
#include "geoip.h"
|
||||
#include "hibernate.h"
|
||||
#include "hs_common.h"
|
||||
#include "main.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
@ -2515,7 +2516,7 @@ circuit_describe_status_for_controller(origin_circuit_t *circ)
|
||||
|
||||
if (circ->rend_data != NULL) {
|
||||
smartlist_add_asprintf(descparts, "REND_QUERY=%s",
|
||||
circ->rend_data->onion_address);
|
||||
rend_data_get_address(circ->rend_data));
|
||||
}
|
||||
|
||||
{
|
||||
@ -6810,8 +6811,10 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query,
|
||||
|
||||
send_control_event(EVENT_HS_DESC,
|
||||
"650 HS_DESC REQUESTED %s %s %s %s\r\n",
|
||||
rend_hsaddress_str_or_unknown(rend_query->onion_address),
|
||||
rend_auth_type_to_string(rend_query->auth_type),
|
||||
rend_hsaddress_str_or_unknown(
|
||||
rend_data_get_address(rend_query)),
|
||||
rend_auth_type_to_string(
|
||||
TO_REND_DATA_V2(rend_query)->auth_type),
|
||||
node_describe_longname_by_id(id_digest),
|
||||
desc_id_base32);
|
||||
}
|
||||
@ -6827,11 +6830,12 @@ get_desc_id_from_query(const rend_data_t *rend_data, const char *hsdir_fp)
|
||||
{
|
||||
int replica;
|
||||
const char *desc_id = NULL;
|
||||
const rend_data_v2_t *rend_data_v2 = TO_REND_DATA_V2(rend_data);
|
||||
|
||||
/* Possible if the fetch was done using a descriptor ID. This means that
|
||||
* the HSFETCH command was used. */
|
||||
if (!tor_digest_is_zero(rend_data->desc_id_fetch)) {
|
||||
desc_id = rend_data->desc_id_fetch;
|
||||
if (!tor_digest_is_zero(rend_data_v2->desc_id_fetch)) {
|
||||
desc_id = rend_data_v2->desc_id_fetch;
|
||||
goto end;
|
||||
}
|
||||
|
||||
@ -6839,7 +6843,7 @@ get_desc_id_from_query(const rend_data_t *rend_data, const char *hsdir_fp)
|
||||
* is the one associated with the HSDir fingerprint. */
|
||||
for (replica = 0; replica < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS;
|
||||
replica++) {
|
||||
const char *digest = rend_data->descriptor_id[replica];
|
||||
const char *digest = rend_data_get_desc_id(rend_data, replica, NULL);
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(rend_data->hsdirs_fp, char *, fingerprint) {
|
||||
if (tor_memcmp(fingerprint, hsdir_fp, DIGEST_LEN) == 0) {
|
||||
@ -6948,7 +6952,8 @@ control_event_hs_descriptor_receive_end(const char *action,
|
||||
"650 HS_DESC %s %s %s %s%s%s\r\n",
|
||||
action,
|
||||
rend_hsaddress_str_or_unknown(onion_address),
|
||||
rend_auth_type_to_string(rend_data->auth_type),
|
||||
rend_auth_type_to_string(
|
||||
TO_REND_DATA_V2(rend_data)->auth_type),
|
||||
node_describe_longname_by_id(id_digest),
|
||||
desc_id_field ? desc_id_field : "",
|
||||
reason_field ? reason_field : "");
|
||||
@ -7045,7 +7050,7 @@ control_event_hs_descriptor_failed(const rend_data_t *rend_data,
|
||||
return;
|
||||
}
|
||||
control_event_hs_descriptor_receive_end("FAILED",
|
||||
rend_data->onion_address,
|
||||
rend_data_get_address(rend_data),
|
||||
rend_data, id_digest, reason);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "dirvote.h"
|
||||
#include "entrynodes.h"
|
||||
#include "geoip.h"
|
||||
#include "hs_common.h"
|
||||
#include "main.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
@ -2346,7 +2347,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
conn->identity_digest, \
|
||||
reason) )
|
||||
#define SEND_HS_DESC_FAILED_CONTENT() ( \
|
||||
control_event_hs_descriptor_content(conn->rend_data->onion_address, \
|
||||
control_event_hs_descriptor_content(rend_data_get_address(conn->rend_data), \
|
||||
conn->requested_resource, \
|
||||
conn->identity_digest, \
|
||||
NULL) )
|
||||
@ -2422,7 +2423,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
#define SEND_HS_DESC_UPLOAD_FAILED_EVENT(reason) ( \
|
||||
control_event_hs_descriptor_upload_failed( \
|
||||
conn->identity_digest, \
|
||||
conn->rend_data->onion_address, \
|
||||
rend_data_get_address(conn->rend_data), \
|
||||
reason) )
|
||||
log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
|
||||
"(%s))",
|
||||
@ -2436,7 +2437,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
"Uploading rendezvous descriptor: finished with status "
|
||||
"200 (%s)", escaped(reason));
|
||||
control_event_hs_descriptor_uploaded(conn->identity_digest,
|
||||
conn->rend_data->onion_address);
|
||||
rend_data_get_address(conn->rend_data));
|
||||
rend_service_desc_has_uploaded(conn->rend_data);
|
||||
break;
|
||||
case 400:
|
||||
@ -2547,7 +2548,8 @@ connection_dir_about_to_close(dir_connection_t *dir_conn)
|
||||
* refetching is unnecessary.) */
|
||||
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
|
||||
dir_conn->rend_data &&
|
||||
strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32)
|
||||
strlen(rend_data_get_address(dir_conn->rend_data)) ==
|
||||
REND_SERVICE_ID_LEN_BASE32)
|
||||
rend_client_refetch_v2_renddesc(dir_conn->rend_data);
|
||||
}
|
||||
|
||||
|
264
src/or/hs_common.c
Normal file
264
src/or/hs_common.c
Normal file
@ -0,0 +1,264 @@
|
||||
/* Copyright (c) 2016, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file hs_common.c
|
||||
* \brief Contains code shared between different HS protocol version as well
|
||||
* as useful data structures and accessors used by other subsystems.
|
||||
* The rendcommon.c should only contains code relating to the v2
|
||||
* protocol.
|
||||
**/
|
||||
|
||||
#include "or.h"
|
||||
|
||||
#include "hs_common.h"
|
||||
#include "rendcommon.h"
|
||||
|
||||
/* Create a new rend_data_t for a specific given <b>version</b>.
|
||||
* Return a pointer to the newly allocated data structure. */
|
||||
static rend_data_t *
|
||||
rend_data_alloc(uint32_t version)
|
||||
{
|
||||
rend_data_t *rend_data = NULL;
|
||||
|
||||
switch (version) {
|
||||
case HS_VERSION_TWO:
|
||||
{
|
||||
rend_data_v2_t *v2 = tor_malloc_zero(sizeof(*v2));
|
||||
v2->base_.version = HS_VERSION_TWO;
|
||||
v2->base_.hsdirs_fp = smartlist_new();
|
||||
rend_data = &v2->base_;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
tor_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return rend_data;
|
||||
}
|
||||
|
||||
/** Free all storage associated with <b>data</b> */
|
||||
void
|
||||
rend_data_free(rend_data_t *data)
|
||||
{
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
/* By using our allocation function, this should always be set. */
|
||||
tor_assert(data->hsdirs_fp);
|
||||
/* Cleanup the HSDir identity digest. */
|
||||
SMARTLIST_FOREACH(data->hsdirs_fp, char *, d, tor_free(d));
|
||||
smartlist_free(data->hsdirs_fp);
|
||||
/* Depending on the version, cleanup. */
|
||||
switch (data->version) {
|
||||
case HS_VERSION_TWO:
|
||||
{
|
||||
rend_data_v2_t *v2_data = TO_REND_DATA_V2(data);
|
||||
tor_free(v2_data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
tor_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate and return a deep copy of <b>data</b>. */
|
||||
rend_data_t *
|
||||
rend_data_dup(const rend_data_t *data)
|
||||
{
|
||||
rend_data_t *data_dup = NULL;
|
||||
smartlist_t *hsdirs_fp = smartlist_new();
|
||||
|
||||
tor_assert(data);
|
||||
tor_assert(data->hsdirs_fp);
|
||||
|
||||
SMARTLIST_FOREACH(data->hsdirs_fp, char *, fp,
|
||||
smartlist_add(hsdirs_fp, tor_memdup(fp, DIGEST_LEN)));
|
||||
|
||||
switch (data->version) {
|
||||
case HS_VERSION_TWO:
|
||||
{
|
||||
rend_data_v2_t *v2_data = tor_memdup(TO_REND_DATA_V2(data),
|
||||
sizeof(*v2_data));
|
||||
data_dup = &v2_data->base_;
|
||||
data_dup->hsdirs_fp = hsdirs_fp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
tor_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return data_dup;
|
||||
}
|
||||
|
||||
/* Compute the descriptor ID for each HS descriptor replica and save them. A
|
||||
* valid onion address must be present in the <b>rend_data</b>.
|
||||
*
|
||||
* Return 0 on success else -1. */
|
||||
static int
|
||||
compute_desc_id(rend_data_t *rend_data)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned replica;
|
||||
time_t now = time(NULL);
|
||||
|
||||
tor_assert(rend_data);
|
||||
|
||||
switch (rend_data->version) {
|
||||
case HS_VERSION_TWO:
|
||||
{
|
||||
rend_data_v2_t *v2_data = TO_REND_DATA_V2(rend_data);
|
||||
/* Compute descriptor ID for each replicas. */
|
||||
for (replica = 0; replica < ARRAY_LENGTH(v2_data->descriptor_id);
|
||||
replica++) {
|
||||
ret = rend_compute_v2_desc_id(v2_data->descriptor_id[replica],
|
||||
v2_data->onion_address,
|
||||
v2_data->descriptor_cookie,
|
||||
now, replica);
|
||||
if (ret < 0) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
tor_assert(0);
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate and initialize a rend_data_t object for a service using the
|
||||
* provided arguments. All arguments are optional (can be NULL), except from
|
||||
* <b>onion_address</b> which MUST be set.
|
||||
*
|
||||
* Return a valid rend_data_t pointer. This only returns a version 2 object of
|
||||
* rend_data_t. */
|
||||
rend_data_t *
|
||||
rend_data_service_create(const char *onion_address, const char *pk_digest,
|
||||
const uint8_t *cookie, rend_auth_type_t auth_type)
|
||||
{
|
||||
/* Create a rend_data_t object for version 2. */
|
||||
rend_data_t *rend_data = rend_data_alloc(HS_VERSION_TWO);
|
||||
rend_data_v2_t *v2= TO_REND_DATA_V2(rend_data);
|
||||
|
||||
/* We need at least one else the call is wrong. */
|
||||
tor_assert(onion_address != NULL);
|
||||
|
||||
if (pk_digest) {
|
||||
memcpy(v2->rend_pk_digest, pk_digest, sizeof(v2->rend_pk_digest));
|
||||
}
|
||||
if (cookie) {
|
||||
memcpy(rend_data->rend_cookie, cookie, sizeof(rend_data->rend_cookie));
|
||||
}
|
||||
|
||||
strlcpy(v2->onion_address, onion_address, sizeof(v2->onion_address));
|
||||
v2->auth_type = auth_type;
|
||||
|
||||
return rend_data;
|
||||
}
|
||||
|
||||
/* Allocate and initialize a rend_data_t object for a client request using
|
||||
* the given arguments. Either an onion address or a descriptor ID is
|
||||
* needed. Both can be given but only the onion address will be used to make
|
||||
* the descriptor fetch.
|
||||
*
|
||||
* Return a valid rend_data_t pointer or NULL on error meaning the
|
||||
* descriptor IDs couldn't be computed from the given data. */
|
||||
rend_data_t *
|
||||
rend_data_client_create(const char *onion_address, const char *desc_id,
|
||||
const char *cookie, rend_auth_type_t auth_type)
|
||||
{
|
||||
/* Create a rend_data_t object for version 2. */
|
||||
rend_data_t *rend_data = rend_data_alloc(HS_VERSION_TWO);
|
||||
rend_data_v2_t *v2= TO_REND_DATA_V2(rend_data);
|
||||
|
||||
/* We need at least one else the call is wrong. */
|
||||
tor_assert(onion_address != NULL || desc_id != NULL);
|
||||
|
||||
if (cookie) {
|
||||
memcpy(v2->descriptor_cookie, cookie, sizeof(v2->descriptor_cookie));
|
||||
}
|
||||
if (desc_id) {
|
||||
memcpy(v2->desc_id_fetch, desc_id, sizeof(v2->desc_id_fetch));
|
||||
}
|
||||
if (onion_address) {
|
||||
strlcpy(v2->onion_address, onion_address, sizeof(v2->onion_address));
|
||||
if (compute_desc_id(rend_data) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
v2->auth_type = auth_type;
|
||||
|
||||
return rend_data;
|
||||
|
||||
error:
|
||||
rend_data_free(rend_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the onion address from the rend data. Depending on the version,
|
||||
* the size of the address can vary but it's always NUL terminated. */
|
||||
const char *
|
||||
rend_data_get_address(const rend_data_t *rend_data)
|
||||
{
|
||||
tor_assert(rend_data);
|
||||
|
||||
switch (rend_data->version) {
|
||||
case HS_VERSION_TWO:
|
||||
return TO_REND_DATA_V2(rend_data)->onion_address;
|
||||
default:
|
||||
/* We should always have a supported version. */
|
||||
tor_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the descriptor ID for a specific replica number from the rend
|
||||
* data. The returned data is a binary digest and depending on the version its
|
||||
* size can vary. The size of the descriptor ID is put in <b>len_out</b> if
|
||||
* non NULL. */
|
||||
const char *
|
||||
rend_data_get_desc_id(const rend_data_t *rend_data, uint8_t replica,
|
||||
size_t *len_out)
|
||||
{
|
||||
tor_assert(rend_data);
|
||||
|
||||
switch (rend_data->version) {
|
||||
case HS_VERSION_TWO:
|
||||
tor_assert(replica < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS);
|
||||
if (len_out) {
|
||||
*len_out = DIGEST_LEN;
|
||||
}
|
||||
return TO_REND_DATA_V2(rend_data)->descriptor_id[replica];
|
||||
default:
|
||||
/* We should always have a supported version. */
|
||||
tor_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the public key digest using the given <b>rend_data</b>. The size of
|
||||
* the digest is put in <b>len_out</b> (if set) which can differ depending on
|
||||
* the version. */
|
||||
const uint8_t *
|
||||
rend_data_get_pk_digest(const rend_data_t *rend_data, size_t *len_out)
|
||||
{
|
||||
tor_assert(rend_data);
|
||||
|
||||
switch (rend_data->version) {
|
||||
case HS_VERSION_TWO:
|
||||
{
|
||||
const rend_data_v2_t *v2_data = TO_REND_DATA_V2(rend_data);
|
||||
if (len_out) {
|
||||
*len_out = sizeof(v2_data->rend_pk_digest);
|
||||
}
|
||||
return (const uint8_t *) v2_data->rend_pk_digest;
|
||||
}
|
||||
default:
|
||||
/* We should always have a supported version. */
|
||||
tor_assert(0);
|
||||
}
|
||||
}
|
34
src/or/hs_common.h
Normal file
34
src/or/hs_common.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* Copyright (c) 2016, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file hs_common.h
|
||||
* \brief Header file for hs_common.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_HS_COMMON_H
|
||||
#define TOR_HS_COMMON_H
|
||||
|
||||
#include "or.h"
|
||||
|
||||
/* Protocol version 2. Use this instead of hardcoding "2" in the code base,
|
||||
* this adds a clearer semantic to the value when used. */
|
||||
#define HS_VERSION_TWO 2
|
||||
|
||||
void rend_data_free(rend_data_t *data);
|
||||
rend_data_t *rend_data_dup(const rend_data_t *data);
|
||||
rend_data_t *rend_data_client_create(const char *onion_address,
|
||||
const char *desc_id,
|
||||
const char *cookie,
|
||||
rend_auth_type_t auth_type);
|
||||
rend_data_t *rend_data_service_create(const char *onion_address,
|
||||
const char *pk_digest,
|
||||
const uint8_t *cookie,
|
||||
rend_auth_type_t auth_type);
|
||||
const char *rend_data_get_address(const rend_data_t *rend_data);
|
||||
const char *rend_data_get_desc_id(const rend_data_t *rend_data,
|
||||
uint8_t replica, size_t *len_out);
|
||||
const uint8_t *rend_data_get_pk_digest(const rend_data_t *rend_data,
|
||||
size_t *len_out);
|
||||
|
||||
#endif /* TOR_HS_COMMON_H */
|
@ -48,6 +48,7 @@ LIBTOR_A_SOURCES = \
|
||||
src/or/entrynodes.c \
|
||||
src/or/ext_orport.c \
|
||||
src/or/hibernate.c \
|
||||
src/or/hs_common.c \
|
||||
src/or/keypin.c \
|
||||
src/or/main.c \
|
||||
src/or/microdesc.c \
|
||||
@ -156,6 +157,7 @@ ORHEADERS = \
|
||||
src/or/geoip.h \
|
||||
src/or/entrynodes.h \
|
||||
src/or/hibernate.h \
|
||||
src/or/hs_common.h \
|
||||
src/or/keypin.h \
|
||||
src/or/main.h \
|
||||
src/or/microdesc.h \
|
||||
|
42
src/or/or.h
42
src/or/or.h
@ -114,6 +114,9 @@
|
||||
#define NON_ANONYMOUS_MODE_ENABLED 1
|
||||
#endif
|
||||
|
||||
/** Helper macro: Given a pointer to to.base_, of type from*, return &to. */
|
||||
#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, base_))
|
||||
|
||||
/** Length of longest allowable configured nickname. */
|
||||
#define MAX_NICKNAME_LEN 19
|
||||
/** Length of a router identity encoded as a hexadecimal digest, plus
|
||||
@ -779,6 +782,24 @@ typedef struct rend_service_authorization_t {
|
||||
* establishment. Not all fields contain data depending on where this struct
|
||||
* is used. */
|
||||
typedef struct rend_data_t {
|
||||
/* Hidden service protocol version of this base object. */
|
||||
uint32_t version;
|
||||
|
||||
/** List of HSDir fingerprints on which this request has been sent to. This
|
||||
* contains binary identity digest of the directory of size DIGEST_LEN. */
|
||||
smartlist_t *hsdirs_fp;
|
||||
|
||||
/** Rendezvous cookie used by both, client and service. */
|
||||
char rend_cookie[REND_COOKIE_LEN];
|
||||
|
||||
/** Number of streams associated with this rendezvous circuit. */
|
||||
int nr_streams;
|
||||
} rend_data_t;
|
||||
|
||||
typedef struct rend_data_v2_t {
|
||||
/* Rendezvous base data. */
|
||||
rend_data_t base_;
|
||||
|
||||
/** Onion address (without the .onion part) that a client requests. */
|
||||
char onion_address[REND_SERVICE_ID_LEN_BASE32+1];
|
||||
|
||||
@ -800,17 +821,16 @@ typedef struct rend_data_t {
|
||||
|
||||
/** Hash of the hidden service's PK used by a service. */
|
||||
char rend_pk_digest[DIGEST_LEN];
|
||||
} rend_data_v2_t;
|
||||
|
||||
/** Rendezvous cookie used by both, client and service. */
|
||||
char rend_cookie[REND_COOKIE_LEN];
|
||||
|
||||
/** List of HSDir fingerprints on which this request has been sent to.
|
||||
* This contains binary identity digest of the directory. */
|
||||
smartlist_t *hsdirs_fp;
|
||||
|
||||
/** Number of streams associated with this rendezvous circuit. */
|
||||
int nr_streams;
|
||||
} rend_data_t;
|
||||
/* From a base rend_data_t object <b>d</d>, return the v2 object. */
|
||||
static inline
|
||||
rend_data_v2_t *TO_REND_DATA_V2(const rend_data_t *d)
|
||||
{
|
||||
tor_assert(d);
|
||||
tor_assert(d->version == 2);
|
||||
return DOWNCAST(rend_data_v2_t, d);
|
||||
}
|
||||
|
||||
/** Time interval for tracking replays of DH public keys received in
|
||||
* INTRODUCE2 cells. Used only to avoid launching multiple
|
||||
@ -1759,8 +1779,6 @@ typedef struct control_connection_t {
|
||||
|
||||
/** Cast a connection_t subtype pointer to a connection_t **/
|
||||
#define TO_CONN(c) (&(((c)->base_)))
|
||||
/** Helper macro: Given a pointer to to.base_, of type from*, return &to. */
|
||||
#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, base_))
|
||||
|
||||
/** Cast a entry_connection_t subtype pointer to a edge_connection_t **/
|
||||
#define ENTRY_TO_EDGE_CONN(c) (&(((c))->edge_))
|
||||
|
@ -849,6 +849,8 @@ rend_cache_store_v2_desc_as_client(const char *desc,
|
||||
char want_desc_id[DIGEST_LEN];
|
||||
rend_cache_entry_t *e;
|
||||
int retval = -1;
|
||||
rend_data_v2_t *rend_data = TO_REND_DATA_V2(rend_query);
|
||||
|
||||
tor_assert(rend_cache);
|
||||
tor_assert(desc);
|
||||
tor_assert(desc_id_base32);
|
||||
@ -874,11 +876,11 @@ rend_cache_store_v2_desc_as_client(const char *desc,
|
||||
log_warn(LD_REND, "Couldn't compute service ID.");
|
||||
goto err;
|
||||
}
|
||||
if (rend_query->onion_address[0] != '\0' &&
|
||||
strcmp(rend_query->onion_address, service_id)) {
|
||||
if (rend_data->onion_address[0] != '\0' &&
|
||||
strcmp(rend_data->onion_address, service_id)) {
|
||||
log_warn(LD_REND, "Received service descriptor for service ID %s; "
|
||||
"expected descriptor for service ID %s.",
|
||||
service_id, safe_str(rend_query->onion_address));
|
||||
service_id, safe_str(rend_data->onion_address));
|
||||
goto err;
|
||||
}
|
||||
if (tor_memneq(desc_id, want_desc_id, DIGEST_LEN)) {
|
||||
@ -890,14 +892,14 @@ rend_cache_store_v2_desc_as_client(const char *desc,
|
||||
/* Decode/decrypt introduction points. */
|
||||
if (intro_content && intro_size > 0) {
|
||||
int n_intro_points;
|
||||
if (rend_query->auth_type != REND_NO_AUTH &&
|
||||
!tor_mem_is_zero(rend_query->descriptor_cookie,
|
||||
sizeof(rend_query->descriptor_cookie))) {
|
||||
if (rend_data->auth_type != REND_NO_AUTH &&
|
||||
!tor_mem_is_zero(rend_data->descriptor_cookie,
|
||||
sizeof(rend_data->descriptor_cookie))) {
|
||||
char *ipos_decrypted = NULL;
|
||||
size_t ipos_decrypted_size;
|
||||
if (rend_decrypt_introduction_points(&ipos_decrypted,
|
||||
&ipos_decrypted_size,
|
||||
rend_query->descriptor_cookie,
|
||||
rend_data->descriptor_cookie,
|
||||
intro_content,
|
||||
intro_size) < 0) {
|
||||
log_warn(LD_REND, "Failed to decrypt introduction points. We are "
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "connection.h"
|
||||
#include "connection_edge.h"
|
||||
#include "directory.h"
|
||||
#include "hs_common.h"
|
||||
#include "main.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
@ -104,7 +105,7 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ)
|
||||
if (!extend_info) {
|
||||
log_warn(LD_REND,
|
||||
"No usable introduction points left for %s. Closing.",
|
||||
safe_str_client(circ->rend_data->onion_address));
|
||||
safe_str_client(rend_data_get_address(circ->rend_data)));
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
|
||||
return -1;
|
||||
}
|
||||
@ -143,20 +144,21 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
||||
off_t dh_offset;
|
||||
crypto_pk_t *intro_key = NULL;
|
||||
int status = 0;
|
||||
const char *onion_address;
|
||||
|
||||
tor_assert(introcirc->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
tor_assert(rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY);
|
||||
tor_assert(introcirc->rend_data);
|
||||
tor_assert(rendcirc->rend_data);
|
||||
tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address,
|
||||
rendcirc->rend_data->onion_address));
|
||||
tor_assert(!rend_cmp_service_ids(rend_data_get_address(introcirc->rend_data),
|
||||
rend_data_get_address(rendcirc->rend_data)));
|
||||
#ifndef NON_ANONYMOUS_MODE_ENABLED
|
||||
tor_assert(!(introcirc->build_state->onehop_tunnel));
|
||||
tor_assert(!(rendcirc->build_state->onehop_tunnel));
|
||||
#endif
|
||||
onion_address = rend_data_get_address(introcirc->rend_data);
|
||||
|
||||
r = rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
|
||||
&entry);
|
||||
r = rend_cache_lookup_entry(onion_address, -1, &entry);
|
||||
/* An invalid onion address is not possible else we have a big issue. */
|
||||
tor_assert(r != -EINVAL);
|
||||
if (r < 0 || !rend_client_any_intro_points_usable(entry)) {
|
||||
@ -165,14 +167,13 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
||||
log_info(LD_REND,
|
||||
"query %s didn't have valid rend desc in cache. "
|
||||
"Refetching descriptor.",
|
||||
safe_str_client(introcirc->rend_data->onion_address));
|
||||
safe_str_client(onion_address));
|
||||
rend_client_refetch_v2_renddesc(introcirc->rend_data);
|
||||
{
|
||||
connection_t *conn;
|
||||
|
||||
while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
|
||||
AP_CONN_STATE_CIRCUIT_WAIT,
|
||||
introcirc->rend_data->onion_address))) {
|
||||
AP_CONN_STATE_CIRCUIT_WAIT, onion_address))) {
|
||||
connection_ap_mark_as_non_pending_circuit(TO_ENTRY_CONN(conn));
|
||||
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
|
||||
}
|
||||
@ -196,7 +197,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
||||
log_info(LD_REND, "Could not find intro key for %s at %s; we "
|
||||
"have a v2 rend desc with %d intro points. "
|
||||
"Trying a different intro point...",
|
||||
safe_str_client(introcirc->rend_data->onion_address),
|
||||
safe_str_client(onion_address),
|
||||
safe_str_client(extend_info_describe(
|
||||
introcirc->build_state->chosen_exit)),
|
||||
smartlist_len(entry->parsed->intro_nodes));
|
||||
@ -236,11 +237,12 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
||||
/* If version is 3, write (optional) auth data and timestamp. */
|
||||
if (entry->parsed->protocols & (1<<3)) {
|
||||
tmp[0] = 3; /* version 3 of the cell format */
|
||||
tmp[1] = (uint8_t)introcirc->rend_data->auth_type; /* auth type, if any */
|
||||
/* auth type, if any */
|
||||
tmp[1] = (uint8_t) TO_REND_DATA_V2(introcirc->rend_data)->auth_type;
|
||||
v3_shift = 1;
|
||||
if (introcirc->rend_data->auth_type != REND_NO_AUTH) {
|
||||
if (tmp[1] != REND_NO_AUTH) {
|
||||
set_uint16(tmp+2, htons(REND_DESC_COOKIE_LEN));
|
||||
memcpy(tmp+4, introcirc->rend_data->descriptor_cookie,
|
||||
memcpy(tmp+4, TO_REND_DATA_V2(introcirc->rend_data)->descriptor_cookie,
|
||||
REND_DESC_COOKIE_LEN);
|
||||
v3_shift += 2+REND_DESC_COOKIE_LEN;
|
||||
}
|
||||
@ -360,7 +362,7 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ)
|
||||
* Called to close other intro circuits we launched in parallel.
|
||||
*/
|
||||
static void
|
||||
rend_client_close_other_intros(const char *onion_address)
|
||||
rend_client_close_other_intros(const uint8_t *rend_pk_digest)
|
||||
{
|
||||
/* abort parallel intro circs, if any */
|
||||
SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) {
|
||||
@ -369,8 +371,7 @@ rend_client_close_other_intros(const char *onion_address)
|
||||
!c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) {
|
||||
origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c);
|
||||
if (oc->rend_data &&
|
||||
!rend_cmp_service_ids(onion_address,
|
||||
oc->rend_data->onion_address)) {
|
||||
rend_circuit_pk_digest_eq(oc, rend_pk_digest)) {
|
||||
log_info(LD_REND|LD_CIRC, "Closing introduction circuit %d that we "
|
||||
"built in parallel (Purpose %d).", oc->global_identifier,
|
||||
c->purpose);
|
||||
@ -434,7 +435,8 @@ rend_client_introduction_acked(origin_circuit_t *circ,
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
|
||||
|
||||
/* close any other intros launched in parallel */
|
||||
rend_client_close_other_intros(circ->rend_data->onion_address);
|
||||
rend_client_close_other_intros(rend_data_get_pk_digest(circ->rend_data,
|
||||
NULL));
|
||||
} else {
|
||||
/* It's a NAK; the introduction point didn't relay our request. */
|
||||
circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
@ -443,7 +445,7 @@ rend_client_introduction_acked(origin_circuit_t *circ,
|
||||
* If none remain, refetch the service descriptor.
|
||||
*/
|
||||
log_info(LD_REND, "Got nack for %s from %s...",
|
||||
safe_str_client(circ->rend_data->onion_address),
|
||||
safe_str_client(rend_data_get_address(circ->rend_data)),
|
||||
safe_str_client(extend_info_describe(circ->build_state->chosen_exit)));
|
||||
if (rend_client_report_intro_point_failure(circ->build_state->chosen_exit,
|
||||
circ->rend_data,
|
||||
@ -697,13 +699,15 @@ pick_hsdir(const char *desc_id, const char *desc_id_base32)
|
||||
* in the case that no hidden service directory is left to ask for the
|
||||
* descriptor, return 0, and in case of a failure -1. */
|
||||
static int
|
||||
directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query,
|
||||
directory_get_from_hs_dir(const char *desc_id,
|
||||
const rend_data_t *rend_query,
|
||||
routerstatus_t *rs_hsdir)
|
||||
{
|
||||
routerstatus_t *hs_dir = rs_hsdir;
|
||||
char *hsdir_fp;
|
||||
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
|
||||
char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64];
|
||||
const rend_data_v2_t *rend_data;
|
||||
#ifdef ENABLE_TOR2WEB_MODE
|
||||
const int tor2web_mode = get_options()->Tor2webMode;
|
||||
const int how_to_fetch = tor2web_mode ? DIRIND_ONEHOP : DIRIND_ANONYMOUS;
|
||||
@ -712,6 +716,8 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query,
|
||||
#endif
|
||||
|
||||
tor_assert(desc_id);
|
||||
tor_assert(rend_query);
|
||||
rend_data = TO_REND_DATA_V2(rend_query);
|
||||
|
||||
base32_encode(desc_id_base32, sizeof(desc_id_base32),
|
||||
desc_id, DIGEST_LEN);
|
||||
@ -734,10 +740,11 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query,
|
||||
/* Encode descriptor cookie for logging purposes. Also, if the cookie is
|
||||
* malformed, no fetch is triggered thus this needs to be done before the
|
||||
* fetch request. */
|
||||
if (rend_query->auth_type != REND_NO_AUTH) {
|
||||
if (rend_data->auth_type != REND_NO_AUTH) {
|
||||
if (base64_encode(descriptor_cookie_base64,
|
||||
sizeof(descriptor_cookie_base64),
|
||||
rend_query->descriptor_cookie, REND_DESC_COOKIE_LEN,
|
||||
rend_data->descriptor_cookie,
|
||||
REND_DESC_COOKIE_LEN,
|
||||
0)<0) {
|
||||
log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
|
||||
return 0;
|
||||
@ -763,9 +770,9 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query,
|
||||
"service '%s' with descriptor ID '%s', auth type %d, "
|
||||
"and descriptor cookie '%s' to hidden service "
|
||||
"directory %s",
|
||||
rend_query->onion_address, desc_id_base32,
|
||||
rend_query->auth_type,
|
||||
(rend_query->auth_type == REND_NO_AUTH ? "[none]" :
|
||||
rend_data->onion_address, desc_id_base32,
|
||||
rend_data->auth_type,
|
||||
(rend_data->auth_type == REND_NO_AUTH ? "[none]" :
|
||||
escaped_safe_str_client(descriptor_cookie_base64)),
|
||||
routerstatus_describe(hs_dir));
|
||||
control_event_hs_descriptor_requested(rend_query,
|
||||
@ -780,8 +787,8 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query,
|
||||
* On success, 1 is returned. If no hidden service is left to ask, return 0.
|
||||
* On error, -1 is returned. */
|
||||
static int
|
||||
fetch_v2_desc_by_descid(const char *desc_id, const rend_data_t *rend_query,
|
||||
smartlist_t *hsdirs)
|
||||
fetch_v2_desc_by_descid(const char *desc_id,
|
||||
const rend_data_t *rend_query, smartlist_t *hsdirs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -814,13 +821,12 @@ fetch_v2_desc_by_descid(const char *desc_id, const rend_data_t *rend_query,
|
||||
* On success, 1 is returned. If no hidden service is left to ask, return 0.
|
||||
* On error, -1 is returned. */
|
||||
static int
|
||||
fetch_v2_desc_by_addr(rend_data_t *query, smartlist_t *hsdirs)
|
||||
fetch_v2_desc_by_addr(rend_data_t *rend_query, smartlist_t *hsdirs)
|
||||
{
|
||||
char descriptor_id[DIGEST_LEN];
|
||||
int replicas_left_to_try[REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS];
|
||||
int i, tries_left, ret;
|
||||
|
||||
tor_assert(query);
|
||||
rend_data_v2_t *rend_data = TO_REND_DATA_V2(rend_query);
|
||||
|
||||
/* Randomly iterate over the replicas until a descriptor can be fetched
|
||||
* from one of the consecutive nodes, or no options are left. */
|
||||
@ -834,9 +840,10 @@ fetch_v2_desc_by_addr(rend_data_t *query, smartlist_t *hsdirs)
|
||||
int chosen_replica = replicas_left_to_try[rand_val];
|
||||
replicas_left_to_try[rand_val] = replicas_left_to_try[--tries_left];
|
||||
|
||||
ret = rend_compute_v2_desc_id(descriptor_id, query->onion_address,
|
||||
query->auth_type == REND_STEALTH_AUTH ?
|
||||
query->descriptor_cookie : NULL,
|
||||
ret = rend_compute_v2_desc_id(descriptor_id,
|
||||
rend_data->onion_address,
|
||||
rend_data->auth_type == REND_STEALTH_AUTH ?
|
||||
rend_data->descriptor_cookie : NULL,
|
||||
time(NULL), chosen_replica);
|
||||
if (ret < 0) {
|
||||
/* Normally, on failure the descriptor_id is untouched but let's be
|
||||
@ -844,18 +851,18 @@ fetch_v2_desc_by_addr(rend_data_t *query, smartlist_t *hsdirs)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (tor_memcmp(descriptor_id, query->descriptor_id[chosen_replica],
|
||||
if (tor_memcmp(descriptor_id, rend_data->descriptor_id[chosen_replica],
|
||||
sizeof(descriptor_id)) != 0) {
|
||||
/* Not equal from what we currently have so purge the last hid serv
|
||||
* request cache and update the descriptor ID with the new value. */
|
||||
purge_hid_serv_from_last_hid_serv_requests(
|
||||
query->descriptor_id[chosen_replica]);
|
||||
memcpy(query->descriptor_id[chosen_replica], descriptor_id,
|
||||
sizeof(query->descriptor_id[chosen_replica]));
|
||||
rend_data->descriptor_id[chosen_replica]);
|
||||
memcpy(rend_data->descriptor_id[chosen_replica], descriptor_id,
|
||||
sizeof(rend_data->descriptor_id[chosen_replica]));
|
||||
}
|
||||
|
||||
/* Trigger the fetch with the computed descriptor ID. */
|
||||
ret = fetch_v2_desc_by_descid(descriptor_id, query, hsdirs);
|
||||
ret = fetch_v2_desc_by_descid(descriptor_id, rend_query, hsdirs);
|
||||
if (ret != 0) {
|
||||
/* Either on success or failure, as long as we tried a fetch we are
|
||||
* done here. */
|
||||
@ -883,16 +890,23 @@ int
|
||||
rend_client_fetch_v2_desc(rend_data_t *query, smartlist_t *hsdirs)
|
||||
{
|
||||
int ret;
|
||||
rend_data_v2_t *rend_data;
|
||||
const char *onion_address;
|
||||
|
||||
tor_assert(query);
|
||||
|
||||
/* Get the version 2 data structure of the query. */
|
||||
rend_data = TO_REND_DATA_V2(query);
|
||||
onion_address = rend_data_get_address(query);
|
||||
|
||||
/* Depending on what's available in the rend data query object, we will
|
||||
* trigger a fetch by HS address or using a descriptor ID. */
|
||||
|
||||
if (query->onion_address[0] != '\0') {
|
||||
if (onion_address[0] != '\0') {
|
||||
ret = fetch_v2_desc_by_addr(query, hsdirs);
|
||||
} else if (!tor_digest_is_zero(query->desc_id_fetch)) {
|
||||
ret = fetch_v2_desc_by_descid(query->desc_id_fetch, query, hsdirs);
|
||||
} else if (!tor_digest_is_zero(rend_data->desc_id_fetch)) {
|
||||
ret = fetch_v2_desc_by_descid(rend_data->desc_id_fetch, query,
|
||||
hsdirs);
|
||||
} else {
|
||||
/* Query data is invalid. */
|
||||
ret = -1;
|
||||
@ -910,10 +924,11 @@ void
|
||||
rend_client_refetch_v2_renddesc(rend_data_t *rend_query)
|
||||
{
|
||||
rend_cache_entry_t *e = NULL;
|
||||
const char *onion_address = rend_data_get_address(rend_query);
|
||||
|
||||
tor_assert(rend_query);
|
||||
/* Before fetching, check if we already have a usable descriptor here. */
|
||||
if (rend_cache_lookup_entry(rend_query->onion_address, -1, &e) == 0 &&
|
||||
if (rend_cache_lookup_entry(onion_address, -1, &e) == 0 &&
|
||||
rend_client_any_intro_points_usable(e)) {
|
||||
log_info(LD_REND, "We would fetch a v2 rendezvous descriptor, but we "
|
||||
"already have a usable descriptor here. Not fetching.");
|
||||
@ -926,7 +941,7 @@ rend_client_refetch_v2_renddesc(rend_data_t *rend_query)
|
||||
return;
|
||||
}
|
||||
log_debug(LD_REND, "Fetching v2 rendezvous descriptor for service %s",
|
||||
safe_str_client(rend_query->onion_address));
|
||||
safe_str_client(onion_address));
|
||||
|
||||
rend_client_fetch_v2_desc(rend_query, NULL);
|
||||
/* We don't need to look the error code because either on failure or
|
||||
@ -962,7 +977,7 @@ rend_client_cancel_descriptor_fetches(void)
|
||||
} else {
|
||||
log_debug(LD_REND, "Marking for close dir conn fetching "
|
||||
"rendezvous descriptor for service %s",
|
||||
safe_str(rd->onion_address));
|
||||
safe_str(rend_data_get_address(rd)));
|
||||
}
|
||||
connection_mark_for_close(conn);
|
||||
}
|
||||
@ -992,25 +1007,26 @@ rend_client_cancel_descriptor_fetches(void)
|
||||
*/
|
||||
int
|
||||
rend_client_report_intro_point_failure(extend_info_t *failed_intro,
|
||||
rend_data_t *rend_query,
|
||||
rend_data_t *rend_data,
|
||||
unsigned int failure_type)
|
||||
{
|
||||
int i, r;
|
||||
rend_cache_entry_t *ent;
|
||||
connection_t *conn;
|
||||
const char *onion_address = rend_data_get_address(rend_data);
|
||||
|
||||
r = rend_cache_lookup_entry(rend_query->onion_address, -1, &ent);
|
||||
r = rend_cache_lookup_entry(onion_address, -1, &ent);
|
||||
if (r < 0) {
|
||||
/* Either invalid onion address or cache entry not found. */
|
||||
switch (-r) {
|
||||
case EINVAL:
|
||||
log_warn(LD_BUG, "Malformed service ID %s.",
|
||||
escaped_safe_str_client(rend_query->onion_address));
|
||||
escaped_safe_str_client(onion_address));
|
||||
return -1;
|
||||
case ENOENT:
|
||||
log_info(LD_REND, "Unknown service %s. Re-fetching descriptor.",
|
||||
escaped_safe_str_client(rend_query->onion_address));
|
||||
rend_client_refetch_v2_renddesc(rend_query);
|
||||
escaped_safe_str_client(onion_address));
|
||||
rend_client_refetch_v2_renddesc(rend_data);
|
||||
return 0;
|
||||
default:
|
||||
log_warn(LD_BUG, "Unknown cache lookup returned code: %d", r);
|
||||
@ -1034,7 +1050,7 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
|
||||
case INTRO_POINT_FAILURE_GENERIC:
|
||||
rend_cache_intro_failure_note(failure_type,
|
||||
(uint8_t *)failed_intro->identity_digest,
|
||||
rend_query->onion_address);
|
||||
onion_address);
|
||||
rend_intro_point_free(intro);
|
||||
smartlist_del(ent->parsed->intro_nodes, i);
|
||||
break;
|
||||
@ -1052,8 +1068,7 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
|
||||
if (zap_intro_point) {
|
||||
rend_cache_intro_failure_note(
|
||||
failure_type,
|
||||
(uint8_t *) failed_intro->identity_digest,
|
||||
rend_query->onion_address);
|
||||
(uint8_t *) failed_intro->identity_digest, onion_address);
|
||||
rend_intro_point_free(intro);
|
||||
smartlist_del(ent->parsed->intro_nodes, i);
|
||||
}
|
||||
@ -1067,14 +1082,14 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
|
||||
if (! rend_client_any_intro_points_usable(ent)) {
|
||||
log_info(LD_REND,
|
||||
"No more intro points remain for %s. Re-fetching descriptor.",
|
||||
escaped_safe_str_client(rend_query->onion_address));
|
||||
rend_client_refetch_v2_renddesc(rend_query);
|
||||
escaped_safe_str_client(onion_address));
|
||||
rend_client_refetch_v2_renddesc(rend_data);
|
||||
|
||||
/* move all pending streams back to renddesc_wait */
|
||||
/* NOTE: We can now do this faster, if we use pending_entry_connections */
|
||||
while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
|
||||
AP_CONN_STATE_CIRCUIT_WAIT,
|
||||
rend_query->onion_address))) {
|
||||
onion_address))) {
|
||||
connection_ap_mark_as_non_pending_circuit(TO_ENTRY_CONN(conn));
|
||||
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
|
||||
}
|
||||
@ -1083,7 +1098,7 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
|
||||
}
|
||||
log_info(LD_REND,"%d options left for %s.",
|
||||
smartlist_len(ent->parsed->intro_nodes),
|
||||
escaped_safe_str_client(rend_query->onion_address));
|
||||
escaped_safe_str_client(onion_address));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1224,10 +1239,11 @@ rend_client_desc_trynow(const char *query)
|
||||
rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data;
|
||||
if (!rend_data)
|
||||
continue;
|
||||
if (rend_cmp_service_ids(query, rend_data->onion_address))
|
||||
const char *onion_address = rend_data_get_address(rend_data);
|
||||
if (rend_cmp_service_ids(query, onion_address))
|
||||
continue;
|
||||
assert_connection_ok(base_conn, now);
|
||||
if (rend_cache_lookup_entry(rend_data->onion_address, -1,
|
||||
if (rend_cache_lookup_entry(onion_address, -1,
|
||||
&entry) == 0 &&
|
||||
rend_client_any_intro_points_usable(entry)) {
|
||||
/* either this fetch worked, or it failed but there was a
|
||||
@ -1262,11 +1278,12 @@ rend_client_note_connection_attempt_ended(const rend_data_t *rend_data)
|
||||
{
|
||||
unsigned int have_onion = 0;
|
||||
rend_cache_entry_t *cache_entry = NULL;
|
||||
const char *onion_address = rend_data_get_address(rend_data);
|
||||
rend_data_v2_t *rend_data_v2 = TO_REND_DATA_V2(rend_data);
|
||||
|
||||
if (*rend_data->onion_address != '\0') {
|
||||
if (onion_address[0] != '\0') {
|
||||
/* Ignore return value; we find an entry, or we don't. */
|
||||
(void) rend_cache_lookup_entry(rend_data->onion_address, -1,
|
||||
&cache_entry);
|
||||
(void) rend_cache_lookup_entry(onion_address, -1, &cache_entry);
|
||||
have_onion = 1;
|
||||
}
|
||||
|
||||
@ -1280,17 +1297,17 @@ rend_client_note_connection_attempt_ended(const rend_data_t *rend_data)
|
||||
/* Remove the HS's entries in last_hid_serv_requests. */
|
||||
if (have_onion) {
|
||||
unsigned int replica;
|
||||
for (replica = 0; replica < ARRAY_LENGTH(rend_data->descriptor_id);
|
||||
for (replica = 0; replica < ARRAY_LENGTH(rend_data_v2->descriptor_id);
|
||||
replica++) {
|
||||
const char *desc_id = rend_data->descriptor_id[replica];
|
||||
const char *desc_id = rend_data_v2->descriptor_id[replica];
|
||||
purge_hid_serv_from_last_hid_serv_requests(desc_id);
|
||||
}
|
||||
log_info(LD_REND, "Connection attempt for %s has ended; "
|
||||
"cleaning up temporary state.",
|
||||
safe_str_client(rend_data->onion_address));
|
||||
safe_str_client(onion_address));
|
||||
} else {
|
||||
/* We only have an ID for a fetch. Probably used by HSFETCH. */
|
||||
purge_hid_serv_from_last_hid_serv_requests(rend_data->desc_id_fetch);
|
||||
purge_hid_serv_from_last_hid_serv_requests(rend_data_v2->desc_id_fetch);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1304,12 +1321,13 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
|
||||
int ret;
|
||||
extend_info_t *result;
|
||||
rend_cache_entry_t *entry;
|
||||
const char *onion_address = rend_data_get_address(rend_query);
|
||||
|
||||
ret = rend_cache_lookup_entry(rend_query->onion_address, -1, &entry);
|
||||
ret = rend_cache_lookup_entry(onion_address, -1, &entry);
|
||||
if (ret < 0 || !rend_client_any_intro_points_usable(entry)) {
|
||||
log_warn(LD_REND,
|
||||
"Query '%s' didn't have valid rend desc in cache. Failing.",
|
||||
safe_str_client(rend_query->onion_address));
|
||||
safe_str_client(onion_address));
|
||||
/* XXX: Should we refetch the descriptor here if the IPs are not usable
|
||||
* anymore ?. */
|
||||
return NULL;
|
||||
|
@ -27,7 +27,7 @@ void rend_client_cancel_descriptor_fetches(void);
|
||||
void rend_client_purge_last_hid_serv_requests(void);
|
||||
|
||||
int rend_client_report_intro_point_failure(extend_info_t *failed_intro,
|
||||
rend_data_t *rend_query,
|
||||
rend_data_t *rend_data,
|
||||
unsigned int failure_type);
|
||||
|
||||
int rend_client_rendezvous_acked(origin_circuit_t *circ,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "circuitbuild.h"
|
||||
#include "config.h"
|
||||
#include "control.h"
|
||||
#include "hs_common.h"
|
||||
#include "rendclient.h"
|
||||
#include "rendcommon.h"
|
||||
#include "rendmid.h"
|
||||
@ -804,124 +805,6 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
|
||||
command);
|
||||
}
|
||||
|
||||
/** Allocate and return a new rend_data_t with the same
|
||||
* contents as <b>query</b>. */
|
||||
rend_data_t *
|
||||
rend_data_dup(const rend_data_t *data)
|
||||
{
|
||||
rend_data_t *data_dup;
|
||||
tor_assert(data);
|
||||
data_dup = tor_memdup(data, sizeof(rend_data_t));
|
||||
data_dup->hsdirs_fp = smartlist_new();
|
||||
SMARTLIST_FOREACH(data->hsdirs_fp, char *, fp,
|
||||
smartlist_add(data_dup->hsdirs_fp,
|
||||
tor_memdup(fp, DIGEST_LEN)));
|
||||
return data_dup;
|
||||
}
|
||||
|
||||
/** Compute descriptor ID for each replicas and save them. A valid onion
|
||||
* address must be present in the <b>rend_data</b>.
|
||||
*
|
||||
* Return 0 on success else -1. */
|
||||
static int
|
||||
compute_desc_id(rend_data_t *rend_data)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned replica;
|
||||
time_t now = time(NULL);
|
||||
|
||||
tor_assert(rend_data);
|
||||
|
||||
/* Compute descriptor ID for each replicas. */
|
||||
for (replica = 0; replica < ARRAY_LENGTH(rend_data->descriptor_id);
|
||||
replica++) {
|
||||
ret = rend_compute_v2_desc_id(rend_data->descriptor_id[replica],
|
||||
rend_data->onion_address,
|
||||
rend_data->descriptor_cookie,
|
||||
now, replica);
|
||||
if (ret < 0) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Allocate and initialize a rend_data_t object for a service using the
|
||||
* given arguments. Only the <b>onion_address</b> is not optional.
|
||||
*
|
||||
* Return a valid rend_data_t pointer. */
|
||||
rend_data_t *
|
||||
rend_data_service_create(const char *onion_address, const char *pk_digest,
|
||||
const uint8_t *cookie, rend_auth_type_t auth_type)
|
||||
{
|
||||
rend_data_t *rend_data = tor_malloc_zero(sizeof(*rend_data));
|
||||
|
||||
/* We need at least one else the call is wrong. */
|
||||
tor_assert(onion_address != NULL);
|
||||
|
||||
if (pk_digest) {
|
||||
memcpy(rend_data->rend_pk_digest, pk_digest,
|
||||
sizeof(rend_data->rend_pk_digest));
|
||||
}
|
||||
if (cookie) {
|
||||
memcpy(rend_data->rend_cookie, cookie,
|
||||
sizeof(rend_data->rend_cookie));
|
||||
}
|
||||
|
||||
strlcpy(rend_data->onion_address, onion_address,
|
||||
sizeof(rend_data->onion_address));
|
||||
rend_data->auth_type = auth_type;
|
||||
/* Won't be used but still need to initialize it for rend_data dup and
|
||||
* free. */
|
||||
rend_data->hsdirs_fp = smartlist_new();
|
||||
|
||||
return rend_data;
|
||||
}
|
||||
|
||||
/** Allocate and initialize a rend_data_t object for a client request using
|
||||
* the given arguments. Either an onion address or a descriptor ID is
|
||||
* needed. Both can be given but only the onion address will be used to make
|
||||
* the descriptor fetch.
|
||||
*
|
||||
* Return a valid rend_data_t pointer or NULL on error meaning the
|
||||
* descriptor IDs couldn't be computed from the given data. */
|
||||
rend_data_t *
|
||||
rend_data_client_create(const char *onion_address, const char *desc_id,
|
||||
const char *cookie, rend_auth_type_t auth_type)
|
||||
{
|
||||
rend_data_t *rend_data = tor_malloc_zero(sizeof(*rend_data));
|
||||
|
||||
/* We need at least one else the call is wrong. */
|
||||
tor_assert(onion_address != NULL || desc_id != NULL);
|
||||
|
||||
if (cookie) {
|
||||
memcpy(rend_data->descriptor_cookie, cookie,
|
||||
sizeof(rend_data->descriptor_cookie));
|
||||
}
|
||||
if (desc_id) {
|
||||
memcpy(rend_data->desc_id_fetch, desc_id,
|
||||
sizeof(rend_data->desc_id_fetch));
|
||||
}
|
||||
if (onion_address) {
|
||||
strlcpy(rend_data->onion_address, onion_address,
|
||||
sizeof(rend_data->onion_address));
|
||||
if (compute_desc_id(rend_data) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
rend_data->auth_type = auth_type;
|
||||
rend_data->hsdirs_fp = smartlist_new();
|
||||
|
||||
return rend_data;
|
||||
|
||||
error:
|
||||
rend_data_free(rend_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Determine the routers that are responsible for <b>id</b> (binary) and
|
||||
* add pointers to those routers' routerstatus_t to <b>responsible_dirs</b>.
|
||||
* Return -1 if we're returning an empty smartlist, else return 0.
|
||||
@ -1067,3 +950,31 @@ rend_auth_decode_cookie(const char *cookie_in, uint8_t *cookie_out,
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Return 1 iff the given <b>digest</b> of a permenanent hidden service key is
|
||||
* equal to the digest in the origin circuit <b>ocirc</b> of its rend data .
|
||||
* If the rend data doesn't exist, 0 is returned. This function is agnostic to
|
||||
* the rend data version. */
|
||||
int
|
||||
rend_circuit_pk_digest_eq(const origin_circuit_t *ocirc,
|
||||
const uint8_t *digest)
|
||||
{
|
||||
size_t rend_pk_digest_len;
|
||||
const uint8_t *rend_pk_digest;
|
||||
|
||||
tor_assert(ocirc);
|
||||
tor_assert(digest);
|
||||
|
||||
if (ocirc->rend_data == NULL) {
|
||||
goto no_match;
|
||||
}
|
||||
|
||||
rend_pk_digest = rend_data_get_pk_digest(ocirc->rend_data,
|
||||
&rend_pk_digest_len);
|
||||
if (tor_memeq(rend_pk_digest, digest, rend_pk_digest_len)) {
|
||||
goto match;
|
||||
}
|
||||
no_match:
|
||||
return 0;
|
||||
match:
|
||||
return 1;
|
||||
}
|
||||
|
@ -18,19 +18,6 @@ typedef enum rend_intro_point_failure_t {
|
||||
INTRO_POINT_FAILURE_UNREACHABLE = 2,
|
||||
} rend_intro_point_failure_t;
|
||||
|
||||
/** Free all storage associated with <b>data</b> */
|
||||
static inline void
|
||||
rend_data_free(rend_data_t *data)
|
||||
{
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
/* Cleanup the HSDir identity digest. */
|
||||
SMARTLIST_FOREACH(data->hsdirs_fp, char *, d, tor_free(d));
|
||||
smartlist_free(data->hsdirs_fp);
|
||||
tor_free(data);
|
||||
}
|
||||
|
||||
int rend_cmp_service_ids(const char *one, const char *two);
|
||||
|
||||
void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
|
||||
@ -60,15 +47,8 @@ void rend_get_descriptor_id_bytes(char *descriptor_id_out,
|
||||
int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
|
||||
const char *id);
|
||||
|
||||
rend_data_t *rend_data_dup(const rend_data_t *data);
|
||||
rend_data_t *rend_data_client_create(const char *onion_address,
|
||||
const char *desc_id,
|
||||
const char *cookie,
|
||||
rend_auth_type_t auth_type);
|
||||
rend_data_t *rend_data_service_create(const char *onion_address,
|
||||
const char *pk_digest,
|
||||
const uint8_t *cookie,
|
||||
rend_auth_type_t auth_type);
|
||||
int rend_circuit_pk_digest_eq(const origin_circuit_t *ocirc,
|
||||
const uint8_t *digest);
|
||||
|
||||
char *rend_auth_encode_cookie(const uint8_t *cookie_in,
|
||||
rend_auth_type_t auth_type);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "config.h"
|
||||
#include "control.h"
|
||||
#include "directory.h"
|
||||
#include "hs_common.h"
|
||||
#include "main.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
@ -792,8 +793,7 @@ rend_config_services(const or_options_t *options, int validate_only)
|
||||
int keep_it = 0;
|
||||
tor_assert(oc->rend_data);
|
||||
SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
|
||||
if (tor_memeq(ptr->pk_digest, oc->rend_data->rend_pk_digest,
|
||||
DIGEST_LEN)) {
|
||||
if (rend_circuit_pk_digest_eq(oc, (uint8_t *) ptr->pk_digest)) {
|
||||
keep_it = 1;
|
||||
break;
|
||||
}
|
||||
@ -803,7 +803,7 @@ rend_config_services(const or_options_t *options, int validate_only)
|
||||
log_info(LD_REND, "Closing intro point %s for service %s.",
|
||||
safe_str_client(extend_info_describe(
|
||||
oc->build_state->chosen_exit)),
|
||||
oc->rend_data->onion_address);
|
||||
rend_data_get_address(oc->rend_data));
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
|
||||
/* XXXX Is there another reason we should use here? */
|
||||
}
|
||||
@ -930,12 +930,13 @@ rend_service_del_ephemeral(const char *service_id)
|
||||
circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
|
||||
origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
|
||||
tor_assert(oc->rend_data);
|
||||
if (!tor_memeq(s->pk_digest, oc->rend_data->rend_pk_digest, DIGEST_LEN))
|
||||
if (!rend_circuit_pk_digest_eq(oc, (uint8_t *) s->pk_digest)) {
|
||||
continue;
|
||||
}
|
||||
log_debug(LD_REND, "Closing intro point %s for service %s.",
|
||||
safe_str_client(extend_info_describe(
|
||||
oc->build_state->chosen_exit)),
|
||||
oc->rend_data->onion_address);
|
||||
rend_data_get_address(oc->rend_data));
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(circ);
|
||||
@ -1441,7 +1442,7 @@ rend_service_receive_introduction(origin_circuit_t *circuit,
|
||||
const or_options_t *options = get_options();
|
||||
char *err_msg = NULL;
|
||||
int err_msg_severity = LOG_WARN;
|
||||
const char *stage_descr = NULL;
|
||||
const char *stage_descr = NULL, *rend_pk_digest;
|
||||
int reason = END_CIRC_REASON_TORPROTOCOL;
|
||||
/* Service/circuit/key stuff we can learn before parsing */
|
||||
char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
|
||||
@ -1477,14 +1478,15 @@ rend_service_receive_introduction(origin_circuit_t *circuit,
|
||||
tor_assert(!(circuit->build_state->onehop_tunnel));
|
||||
#endif
|
||||
tor_assert(circuit->rend_data);
|
||||
/* XXX: This is version 2 specific (only one supported). */
|
||||
rend_pk_digest = (char *) rend_data_get_pk_digest(circuit->rend_data, NULL);
|
||||
|
||||
/* We'll use this in a bazillion log messages */
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
|
||||
circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
|
||||
/* look up service depending on circuit. */
|
||||
service =
|
||||
rend_service_get_by_pk_digest(circuit->rend_data->rend_pk_digest);
|
||||
service = rend_service_get_by_pk_digest(rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_BUG,
|
||||
"Internal error: Got an INTRODUCE2 cell on an intro "
|
||||
@ -1702,8 +1704,7 @@ rend_service_receive_introduction(origin_circuit_t *circuit,
|
||||
/* Fill in the circuit's state. */
|
||||
|
||||
launched->rend_data =
|
||||
rend_data_service_create(service->service_id,
|
||||
circuit->rend_data->rend_pk_digest,
|
||||
rend_data_service_create(service->service_id, rend_pk_digest,
|
||||
parsed_req->rc, service->auth_type);
|
||||
|
||||
launched->build_state->service_pending_final_cpath_ref =
|
||||
@ -2679,9 +2680,9 @@ count_intro_point_circuits(const rend_service_t *service)
|
||||
circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
|
||||
origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
|
||||
if (oc->rend_data &&
|
||||
!rend_cmp_service_ids(service->service_id,
|
||||
oc->rend_data->onion_address))
|
||||
rend_circuit_pk_digest_eq(oc, (uint8_t *) service->pk_digest)) {
|
||||
num_ipos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
SMARTLIST_FOREACH_END(circ);
|
||||
@ -2701,6 +2702,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
|
||||
char auth[DIGEST_LEN + 9];
|
||||
char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
|
||||
int reason = END_CIRC_REASON_TORPROTOCOL;
|
||||
const char *rend_pk_digest;
|
||||
|
||||
tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
|
||||
#ifndef NON_ANONYMOUS_MODE_ENABLED
|
||||
@ -2708,12 +2710,13 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
|
||||
#endif
|
||||
tor_assert(circuit->cpath);
|
||||
tor_assert(circuit->rend_data);
|
||||
/* XXX: This is version 2 specific (only on supported). */
|
||||
rend_pk_digest = (char *) rend_data_get_pk_digest(circuit->rend_data, NULL);
|
||||
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
|
||||
circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
|
||||
service = rend_service_get_by_pk_digest(
|
||||
circuit->rend_data->rend_pk_digest);
|
||||
service = rend_service_get_by_pk_digest(rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %u.",
|
||||
safe_str_client(serviceid), (unsigned)circuit->base_.n_circ_id);
|
||||
@ -2754,9 +2757,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
|
||||
circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_C_GENERAL);
|
||||
|
||||
{
|
||||
rend_data_t *rend_data = circuit->rend_data;
|
||||
rend_data_free(circuit->rend_data);
|
||||
circuit->rend_data = NULL;
|
||||
rend_data_free(rend_data);
|
||||
}
|
||||
{
|
||||
crypto_pk_t *intro_key = circuit->intro_key;
|
||||
@ -2839,15 +2841,17 @@ rend_service_intro_established(origin_circuit_t *circuit,
|
||||
char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
|
||||
(void) request;
|
||||
(void) request_len;
|
||||
tor_assert(circuit->rend_data);
|
||||
/* XXX: This is version 2 specific (only supported one for now). */
|
||||
const char *rend_pk_digest =
|
||||
(char *) rend_data_get_pk_digest(circuit->rend_data, NULL);
|
||||
|
||||
if (circuit->base_.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
|
||||
log_warn(LD_PROTOCOL,
|
||||
"received INTRO_ESTABLISHED cell on non-intro circuit.");
|
||||
goto err;
|
||||
}
|
||||
tor_assert(circuit->rend_data);
|
||||
service = rend_service_get_by_pk_digest(
|
||||
circuit->rend_data->rend_pk_digest);
|
||||
service = rend_service_get_by_pk_digest(rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_REND, "Unknown service on introduction circuit %u.",
|
||||
(unsigned)circuit->base_.n_circ_id);
|
||||
@ -2870,7 +2874,7 @@ rend_service_intro_established(origin_circuit_t *circuit,
|
||||
circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_INTRO);
|
||||
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32 + 1,
|
||||
circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
log_info(LD_REND,
|
||||
"Received INTRO_ESTABLISHED cell on circuit %u for service %s",
|
||||
(unsigned)circuit->base_.n_circ_id, serviceid);
|
||||
@ -2897,6 +2901,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
|
||||
char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
|
||||
char hexcookie[9];
|
||||
int reason;
|
||||
const char *rend_cookie, *rend_pk_digest;
|
||||
|
||||
tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
|
||||
tor_assert(circuit->cpath);
|
||||
@ -2906,6 +2911,11 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
|
||||
#endif
|
||||
tor_assert(circuit->rend_data);
|
||||
|
||||
/* XXX: This is version 2 specific (only one supported). */
|
||||
rend_pk_digest = (char *) rend_data_get_pk_digest(circuit->rend_data,
|
||||
NULL);
|
||||
rend_cookie = circuit->rend_data->rend_cookie;
|
||||
|
||||
/* Declare the circuit dirty to avoid reuse, and for path-bias */
|
||||
if (!circuit->base_.timestamp_dirty)
|
||||
circuit->base_.timestamp_dirty = time(NULL);
|
||||
@ -2915,9 +2925,9 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
|
||||
|
||||
hop = circuit->build_state->service_pending_final_cpath_ref->cpath;
|
||||
|
||||
base16_encode(hexcookie,9,circuit->rend_data->rend_cookie,4);
|
||||
base16_encode(hexcookie,9, rend_cookie,4);
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
|
||||
circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
|
||||
log_info(LD_REND,
|
||||
"Done building circuit %u to rendezvous with "
|
||||
@ -2945,8 +2955,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
|
||||
circuit->build_state->pending_final_cpath = hop;
|
||||
circuit->build_state->service_pending_final_cpath_ref->cpath = NULL;
|
||||
|
||||
service = rend_service_get_by_pk_digest(
|
||||
circuit->rend_data->rend_pk_digest);
|
||||
service = rend_service_get_by_pk_digest(rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_GENERAL, "Internal error: unrecognized service ID on "
|
||||
"rendezvous circuit.");
|
||||
@ -2955,7 +2964,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
|
||||
}
|
||||
|
||||
/* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
|
||||
memcpy(buf, circuit->rend_data->rend_cookie, REND_COOKIE_LEN);
|
||||
memcpy(buf, rend_cookie, REND_COOKIE_LEN);
|
||||
if (crypto_dh_get_public(hop->rend_dh_handshake_state,
|
||||
buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
|
||||
log_warn(LD_GENERAL,"Couldn't get DH public key.");
|
||||
@ -3019,8 +3028,8 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
|
||||
origin_circuit_t *circ = NULL;
|
||||
|
||||
tor_assert(intro);
|
||||
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
|
||||
CIRCUIT_PURPOSE_S_INTRO))) {
|
||||
while ((circ = circuit_get_next_by_pk_and_purpose(circ,
|
||||
(uint8_t *) pk_digest, CIRCUIT_PURPOSE_S_INTRO))) {
|
||||
if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
|
||||
intro->extend_info->identity_digest, DIGEST_LEN) &&
|
||||
circ->rend_data) {
|
||||
@ -3029,8 +3038,9 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
|
||||
}
|
||||
|
||||
circ = NULL;
|
||||
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
|
||||
CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
|
||||
while ((circ = circuit_get_next_by_pk_and_purpose(circ,
|
||||
(uint8_t *) pk_digest,
|
||||
CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
|
||||
if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
|
||||
intro->extend_info->identity_digest, DIGEST_LEN) &&
|
||||
circ->rend_data) {
|
||||
@ -3069,7 +3079,7 @@ find_intro_point(origin_circuit_t *circ)
|
||||
tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
|
||||
TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO);
|
||||
tor_assert(circ->rend_data);
|
||||
serviceid = circ->rend_data->onion_address;
|
||||
serviceid = rend_data_get_address(circ->rend_data);
|
||||
|
||||
SMARTLIST_FOREACH(rend_service_list, rend_service_t *, s,
|
||||
if (tor_memeq(s->service_id, serviceid, REND_SERVICE_ID_LEN_BASE32)) {
|
||||
@ -3454,10 +3464,13 @@ void
|
||||
rend_service_desc_has_uploaded(const rend_data_t *rend_data)
|
||||
{
|
||||
rend_service_t *service;
|
||||
const char *onion_address;
|
||||
|
||||
tor_assert(rend_data);
|
||||
|
||||
service = rend_service_get_by_service_id(rend_data->onion_address);
|
||||
onion_address = rend_data_get_address(rend_data);
|
||||
|
||||
service = rend_service_get_by_service_id(onion_address);
|
||||
if (service == NULL) {
|
||||
return;
|
||||
}
|
||||
@ -3815,14 +3828,16 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
|
||||
smartlist_t *matching_ports;
|
||||
rend_service_port_config_t *chosen_port;
|
||||
unsigned int warn_once = 0;
|
||||
const char *rend_pk_digest;
|
||||
|
||||
tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
|
||||
tor_assert(circ->rend_data);
|
||||
log_debug(LD_REND,"beginning to hunt for addr/port");
|
||||
/* XXX: This is version 2 specific (only one supported). */
|
||||
rend_pk_digest = (char *) rend_data_get_pk_digest(circ->rend_data, NULL);
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
|
||||
circ->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
service = rend_service_get_by_pk_digest(
|
||||
circ->rend_data->rend_pk_digest);
|
||||
rend_pk_digest, REND_SERVICE_ID_LEN);
|
||||
service = rend_service_get_by_pk_digest(rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
|
||||
"rendezvous circuit %u; closing.",
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "test.h"
|
||||
|
||||
#include "connection.h"
|
||||
#include "hs_common.h"
|
||||
#include "main.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
@ -239,13 +240,9 @@ test_conn_get_rend_setup(const struct testcase_t *tc)
|
||||
rend_cache_init();
|
||||
|
||||
/* TODO: use directory_initiate_command_rend() to do this - maybe? */
|
||||
conn->rend_data = tor_malloc_zero(sizeof(rend_data_t));
|
||||
tor_assert(strlen(TEST_CONN_REND_ADDR) == REND_SERVICE_ID_LEN_BASE32);
|
||||
memcpy(conn->rend_data->onion_address,
|
||||
TEST_CONN_REND_ADDR,
|
||||
REND_SERVICE_ID_LEN_BASE32+1);
|
||||
conn->rend_data->hsdirs_fp = smartlist_new();
|
||||
|
||||
conn->rend_data = rend_data_client_create(TEST_CONN_REND_ADDR, NULL, NULL,
|
||||
REND_NO_AUTH);
|
||||
assert_connection_ok(&conn->base_, time(NULL));
|
||||
return conn;
|
||||
|
||||
@ -528,7 +525,8 @@ test_conn_get_rend(void *arg)
|
||||
tt_assert(connection_get_by_type_state_rendquery(
|
||||
conn->base_.type,
|
||||
conn->base_.state,
|
||||
conn->rend_data->onion_address)
|
||||
rend_data_get_address(
|
||||
conn->rend_data))
|
||||
== TO_CONN(conn));
|
||||
tt_assert(connection_get_by_type_state_rendquery(
|
||||
TEST_CONN_TYPE,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "test.h"
|
||||
#include "control.h"
|
||||
#include "config.h"
|
||||
#include "hs_common.h"
|
||||
#include "rendcommon.h"
|
||||
#include "routerset.h"
|
||||
#include "circuitbuild.h"
|
||||
@ -134,7 +135,7 @@ test_hs_desc_event(void *arg)
|
||||
#define STR_DESC_ID_BASE32 "hba3gmcgpfivzfhx5rtfqkfdhv65yrj3"
|
||||
|
||||
int ret;
|
||||
rend_data_t rend_query;
|
||||
rend_data_v2_t rend_query;
|
||||
const char *expected_msg;
|
||||
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
|
||||
|
||||
@ -146,12 +147,13 @@ test_hs_desc_event(void *arg)
|
||||
|
||||
/* setup rend_query struct */
|
||||
memset(&rend_query, 0, sizeof(rend_query));
|
||||
rend_query.base_.version = 2;
|
||||
strncpy(rend_query.onion_address, STR_HS_ADDR,
|
||||
REND_SERVICE_ID_LEN_BASE32+1);
|
||||
rend_query.auth_type = REND_NO_AUTH;
|
||||
rend_query.hsdirs_fp = smartlist_new();
|
||||
smartlist_add(rend_query.hsdirs_fp, tor_memdup(HSDIR_EXIST_ID,
|
||||
DIGEST_LEN));
|
||||
rend_query.base_.hsdirs_fp = smartlist_new();
|
||||
smartlist_add(rend_query.base_.hsdirs_fp, tor_memdup(HSDIR_EXIST_ID,
|
||||
DIGEST_LEN));
|
||||
|
||||
/* Compute descriptor ID for replica 0, should be STR_DESC_ID_BASE32. */
|
||||
ret = rend_compute_v2_desc_id(rend_query.descriptor_id[0],
|
||||
@ -165,7 +167,7 @@ test_hs_desc_event(void *arg)
|
||||
sizeof(desc_id_base32));
|
||||
|
||||
/* test request event */
|
||||
control_event_hs_descriptor_requested(&rend_query, HSDIR_EXIST_ID,
|
||||
control_event_hs_descriptor_requested(&rend_query.base_, HSDIR_EXIST_ID,
|
||||
STR_DESC_ID_BASE32);
|
||||
expected_msg = "650 HS_DESC REQUESTED "STR_HS_ADDR" NO_AUTH "\
|
||||
STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32 "\r\n";
|
||||
@ -176,7 +178,7 @@ test_hs_desc_event(void *arg)
|
||||
/* test received event */
|
||||
rend_query.auth_type = REND_BASIC_AUTH;
|
||||
control_event_hs_descriptor_received(rend_query.onion_address,
|
||||
&rend_query, HSDIR_EXIST_ID);
|
||||
&rend_query.base_, HSDIR_EXIST_ID);
|
||||
expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\
|
||||
STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32"\r\n";
|
||||
tt_assert(received_msg);
|
||||
@ -185,7 +187,7 @@ test_hs_desc_event(void *arg)
|
||||
|
||||
/* test failed event */
|
||||
rend_query.auth_type = REND_STEALTH_AUTH;
|
||||
control_event_hs_descriptor_failed(&rend_query,
|
||||
control_event_hs_descriptor_failed(&rend_query.base_,
|
||||
HSDIR_NONE_EXIST_ID,
|
||||
"QUERY_REJECTED");
|
||||
expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "\
|
||||
@ -196,7 +198,7 @@ test_hs_desc_event(void *arg)
|
||||
|
||||
/* test invalid auth type */
|
||||
rend_query.auth_type = 999;
|
||||
control_event_hs_descriptor_failed(&rend_query,
|
||||
control_event_hs_descriptor_failed(&rend_query.base_,
|
||||
HSDIR_EXIST_ID,
|
||||
"QUERY_REJECTED");
|
||||
expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\
|
||||
@ -219,8 +221,8 @@ test_hs_desc_event(void *arg)
|
||||
tt_str_op(received_msg, OP_EQ, exp_msg);
|
||||
tor_free(received_msg);
|
||||
tor_free(exp_msg);
|
||||
SMARTLIST_FOREACH(rend_query.hsdirs_fp, char *, d, tor_free(d));
|
||||
smartlist_free(rend_query.hsdirs_fp);
|
||||
SMARTLIST_FOREACH(rend_query.base_.hsdirs_fp, char *, d, tor_free(d));
|
||||
smartlist_free(rend_query.base_.hsdirs_fp);
|
||||
|
||||
done:
|
||||
UNMOCK(queue_control_event_string);
|
||||
@ -320,42 +322,45 @@ test_hs_rend_data(void *arg)
|
||||
client = rend_data_client_create(STR_HS_ADDR, desc_id, client_cookie,
|
||||
REND_NO_AUTH);
|
||||
tt_assert(client);
|
||||
tt_int_op(client->auth_type, ==, REND_NO_AUTH);
|
||||
tt_str_op(client->onion_address, OP_EQ, STR_HS_ADDR);
|
||||
tt_mem_op(client->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id));
|
||||
tt_mem_op(client->descriptor_cookie, OP_EQ, client_cookie,
|
||||
rend_data_v2_t *client_v2 = TO_REND_DATA_V2(client);
|
||||
tt_int_op(client_v2->auth_type, ==, REND_NO_AUTH);
|
||||
tt_str_op(client_v2->onion_address, OP_EQ, STR_HS_ADDR);
|
||||
tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id));
|
||||
tt_mem_op(client_v2->descriptor_cookie, OP_EQ, client_cookie,
|
||||
sizeof(client_cookie));
|
||||
tt_assert(client->hsdirs_fp);
|
||||
tt_int_op(smartlist_len(client->hsdirs_fp), ==, 0);
|
||||
for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
|
||||
int ret = rend_compute_v2_desc_id(desc_id, client->onion_address,
|
||||
client->descriptor_cookie, now, rep);
|
||||
int ret = rend_compute_v2_desc_id(desc_id, client_v2->onion_address,
|
||||
client_v2->descriptor_cookie, now, rep);
|
||||
/* That shouldn't never fail. */
|
||||
tt_int_op(ret, ==, 0);
|
||||
tt_mem_op(client->descriptor_id[rep], OP_EQ, desc_id, sizeof(desc_id));
|
||||
tt_mem_op(client_v2->descriptor_id[rep], OP_EQ, desc_id,
|
||||
sizeof(desc_id));
|
||||
}
|
||||
/* The rest should be zeroed because this is a client request. */
|
||||
tt_int_op(tor_digest_is_zero(client->rend_pk_digest), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(client->rend_cookie), ==, 1);
|
||||
|
||||
/* Test dup(). */
|
||||
client_dup = rend_data_dup(client);
|
||||
tt_assert(client_dup);
|
||||
tt_int_op(client_dup->auth_type, ==, client->auth_type);
|
||||
tt_str_op(client_dup->onion_address, OP_EQ, client->onion_address);
|
||||
tt_mem_op(client_dup->desc_id_fetch, OP_EQ, client->desc_id_fetch,
|
||||
sizeof(client_dup->desc_id_fetch));
|
||||
tt_mem_op(client_dup->descriptor_cookie, OP_EQ, client->descriptor_cookie,
|
||||
sizeof(client_dup->descriptor_cookie));
|
||||
rend_data_v2_t *client_dup_v2 = TO_REND_DATA_V2(client_dup);
|
||||
tt_int_op(client_dup_v2->auth_type, ==, client_v2->auth_type);
|
||||
tt_str_op(client_dup_v2->onion_address, OP_EQ, client_v2->onion_address);
|
||||
tt_mem_op(client_dup_v2->desc_id_fetch, OP_EQ, client_v2->desc_id_fetch,
|
||||
sizeof(client_dup_v2->desc_id_fetch));
|
||||
tt_mem_op(client_dup_v2->descriptor_cookie, OP_EQ, client_v2->descriptor_cookie,
|
||||
sizeof(client_dup_v2->descriptor_cookie));
|
||||
|
||||
tt_assert(client_dup->hsdirs_fp);
|
||||
tt_int_op(smartlist_len(client_dup->hsdirs_fp), ==, 0);
|
||||
for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
|
||||
tt_mem_op(client_dup->descriptor_id[rep], OP_EQ,
|
||||
client->descriptor_id[rep], DIGEST_LEN);
|
||||
tt_mem_op(client_dup_v2->descriptor_id[rep], OP_EQ,
|
||||
client_v2->descriptor_id[rep], DIGEST_LEN);
|
||||
}
|
||||
/* The rest should be zeroed because this is a client request. */
|
||||
tt_int_op(tor_digest_is_zero(client_dup->rend_pk_digest), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(client_dup_v2->rend_pk_digest), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(client_dup->rend_cookie), ==, 1);
|
||||
rend_data_free(client);
|
||||
client = NULL;
|
||||
@ -371,18 +376,19 @@ test_hs_rend_data(void *arg)
|
||||
* zeroed out. */
|
||||
client = rend_data_client_create(NULL, desc_id, NULL, REND_BASIC_AUTH);
|
||||
tt_assert(client);
|
||||
tt_int_op(client->auth_type, ==, REND_BASIC_AUTH);
|
||||
tt_int_op(strlen(client->onion_address), ==, 0);
|
||||
tt_mem_op(client->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id));
|
||||
tt_int_op(tor_mem_is_zero(client->descriptor_cookie,
|
||||
sizeof(client->descriptor_cookie)), ==, 1);
|
||||
client_v2 = TO_REND_DATA_V2(client);
|
||||
tt_int_op(client_v2->auth_type, ==, REND_BASIC_AUTH);
|
||||
tt_int_op(strlen(client_v2->onion_address), ==, 0);
|
||||
tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id));
|
||||
tt_int_op(tor_mem_is_zero(client_v2->descriptor_cookie,
|
||||
sizeof(client_v2->descriptor_cookie)), ==, 1);
|
||||
tt_assert(client->hsdirs_fp);
|
||||
tt_int_op(smartlist_len(client->hsdirs_fp), ==, 0);
|
||||
for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
|
||||
tt_int_op(tor_digest_is_zero(client->descriptor_id[rep]), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(client_v2->descriptor_id[rep]), ==, 1);
|
||||
}
|
||||
/* The rest should be zeroed because this is a client request. */
|
||||
tt_int_op(tor_digest_is_zero(client->rend_pk_digest), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(client->rend_cookie), ==, 1);
|
||||
rend_data_free(client);
|
||||
client = NULL;
|
||||
@ -396,37 +402,39 @@ test_hs_rend_data(void *arg)
|
||||
service = rend_data_service_create(STR_HS_ADDR, rend_pk_digest,
|
||||
rend_cookie, REND_NO_AUTH);
|
||||
tt_assert(service);
|
||||
tt_int_op(service->auth_type, ==, REND_NO_AUTH);
|
||||
tt_str_op(service->onion_address, OP_EQ, STR_HS_ADDR);
|
||||
tt_mem_op(service->rend_pk_digest, OP_EQ, rend_pk_digest,
|
||||
rend_data_v2_t *service_v2 = TO_REND_DATA_V2(service);
|
||||
tt_int_op(service_v2->auth_type, ==, REND_NO_AUTH);
|
||||
tt_str_op(service_v2->onion_address, OP_EQ, STR_HS_ADDR);
|
||||
tt_mem_op(service_v2->rend_pk_digest, OP_EQ, rend_pk_digest,
|
||||
sizeof(rend_pk_digest));
|
||||
tt_mem_op(service->rend_cookie, OP_EQ, rend_cookie, sizeof(rend_cookie));
|
||||
tt_assert(service->hsdirs_fp);
|
||||
tt_int_op(smartlist_len(service->hsdirs_fp), ==, 0);
|
||||
for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
|
||||
tt_int_op(tor_digest_is_zero(service->descriptor_id[rep]), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(service_v2->descriptor_id[rep]), ==, 1);
|
||||
}
|
||||
/* The rest should be zeroed because this is a service request. */
|
||||
tt_int_op(tor_digest_is_zero(service->descriptor_cookie), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(service->desc_id_fetch), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(service_v2->descriptor_cookie), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(service_v2->desc_id_fetch), ==, 1);
|
||||
|
||||
/* Test dup(). */
|
||||
service_dup = rend_data_dup(service);
|
||||
rend_data_v2_t *service_dup_v2 = TO_REND_DATA_V2(service_dup);
|
||||
tt_assert(service_dup);
|
||||
tt_int_op(service_dup->auth_type, ==, service->auth_type);
|
||||
tt_str_op(service_dup->onion_address, OP_EQ, service->onion_address);
|
||||
tt_mem_op(service_dup->rend_pk_digest, OP_EQ, service->rend_pk_digest,
|
||||
sizeof(service_dup->rend_pk_digest));
|
||||
tt_int_op(service_dup_v2->auth_type, ==, service_v2->auth_type);
|
||||
tt_str_op(service_dup_v2->onion_address, OP_EQ, service_v2->onion_address);
|
||||
tt_mem_op(service_dup_v2->rend_pk_digest, OP_EQ, service_v2->rend_pk_digest,
|
||||
sizeof(service_dup_v2->rend_pk_digest));
|
||||
tt_mem_op(service_dup->rend_cookie, OP_EQ, service->rend_cookie,
|
||||
sizeof(service_dup->rend_cookie));
|
||||
tt_assert(service_dup->hsdirs_fp);
|
||||
tt_int_op(smartlist_len(service_dup->hsdirs_fp), ==, 0);
|
||||
for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
|
||||
tt_int_op(tor_digest_is_zero(service_dup->descriptor_id[rep]), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(service_dup_v2->descriptor_id[rep]), ==, 1);
|
||||
}
|
||||
/* The rest should be zeroed because this is a service request. */
|
||||
tt_int_op(tor_digest_is_zero(service_dup->descriptor_cookie), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(service_dup->desc_id_fetch), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(service_dup_v2->descriptor_cookie), ==, 1);
|
||||
tt_int_op(tor_digest_is_zero(service_dup_v2->desc_id_fetch), ==, 1);
|
||||
|
||||
done:
|
||||
rend_data_free(service);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "router.h"
|
||||
#include "routerlist.h"
|
||||
#include "config.h"
|
||||
#include "hs_common.h"
|
||||
#include <openssl/rsa.h>
|
||||
#include "rend_test_helpers.h"
|
||||
|
||||
@ -23,15 +24,16 @@ static const int TIME_IN_THE_FUTURE = REND_CACHE_MAX_SKEW + 60;
|
||||
static rend_data_t *
|
||||
mock_rend_data(const char *onion_address)
|
||||
{
|
||||
rend_data_t *rend_query = tor_malloc_zero(sizeof(rend_data_t));
|
||||
rend_data_v2_t *v2_data = tor_malloc_zero(sizeof(*v2_data));
|
||||
rend_data_t *rend_query = &v2_data->base_;
|
||||
rend_query->version = 2;
|
||||
|
||||
strlcpy(rend_query->onion_address, onion_address,
|
||||
sizeof(rend_query->onion_address));
|
||||
rend_query->auth_type = REND_NO_AUTH;
|
||||
strlcpy(v2_data->onion_address, onion_address,
|
||||
sizeof(v2_data->onion_address));
|
||||
v2_data->auth_type = REND_NO_AUTH;
|
||||
rend_query->hsdirs_fp = smartlist_new();
|
||||
smartlist_add(rend_query->hsdirs_fp, tor_memdup("aaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
DIGEST_LEN));
|
||||
|
||||
return rend_query;
|
||||
}
|
||||
|
||||
@ -143,7 +145,8 @@ test_rend_cache_store_v2_desc_as_client(void *data)
|
||||
|
||||
// Test mismatch between service ID and onion address
|
||||
rend_cache_init();
|
||||
strncpy(mock_rend_query->onion_address, "abc", REND_SERVICE_ID_LEN_BASE32+1);
|
||||
strncpy(TO_REND_DATA_V2(mock_rend_query)->onion_address, "abc",
|
||||
REND_SERVICE_ID_LEN_BASE32+1);
|
||||
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
||||
desc_id_base32,
|
||||
mock_rend_query, NULL);
|
||||
@ -229,9 +232,9 @@ test_rend_cache_store_v2_desc_as_client(void *data)
|
||||
|
||||
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
||||
mock_rend_query = mock_rend_data(service_id);
|
||||
mock_rend_query->auth_type = REND_BASIC_AUTH;
|
||||
TO_REND_DATA_V2(mock_rend_query)->auth_type = REND_BASIC_AUTH;
|
||||
client_cookie[0] = 'A';
|
||||
memcpy(mock_rend_query->descriptor_cookie, client_cookie,
|
||||
memcpy(TO_REND_DATA_V2(mock_rend_query)->descriptor_cookie, client_cookie,
|
||||
REND_DESC_COOKIE_LEN);
|
||||
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
||||
DIGEST_LEN);
|
||||
@ -249,7 +252,7 @@ test_rend_cache_store_v2_desc_as_client(void *data)
|
||||
|
||||
generate_desc(RECENT_TIME, &desc_holder, &service_id, 3);
|
||||
mock_rend_query = mock_rend_data(service_id);
|
||||
mock_rend_query->auth_type = REND_BASIC_AUTH;
|
||||
TO_REND_DATA_V2(mock_rend_query)->auth_type = REND_BASIC_AUTH;
|
||||
base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id,
|
||||
DIGEST_LEN);
|
||||
ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str,
|
||||
|
Loading…
Reference in New Issue
Block a user