[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] prop224: Pick rendezvous point of protover HSRend=2
commit c527cde82f74849ec3b183159d20441019b77e2e
Author: David Goulet <dgoulet@xxxxxxxxxxxxxx>
Date: Wed Aug 30 10:13:22 2017 -0400
prop224: Pick rendezvous point of protover HSRend=2
Version 3 hidden service needs rendezvous point that have the protocol version
HSRend >= 2 else the rendezvous cells are rejected.
Fixes #23361
Signed-off-by: David Goulet <dgoulet@xxxxxxxxxxxxxx>
---
src/or/circuitbuild.c | 28 ++++++++++++++++++++++------
src/or/circuitlist.c | 32 ++++++++++++++++++++++++++++++++
src/or/circuituse.c | 10 ++++++++++
src/or/circuituse.h | 3 +++
src/or/hs_client.c | 17 +++++++++++++++--
src/or/nodelist.c | 22 ++++++++++++++++++++++
src/or/nodelist.h | 1 +
src/or/or.h | 10 +++++++++-
src/or/protover.h | 2 ++
src/or/routerlist.c | 16 ++++++++++++----
src/or/routerparse.c | 3 +++
11 files changed, 131 insertions(+), 13 deletions(-)
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 65cd7bd5d..e5c6767d4 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -71,7 +71,8 @@ static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
static int circuit_deliver_create_cell(circuit_t *circ,
const create_cell_t *create_cell,
int relayed);
-static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
+static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit,
+ int is_hs_v3_rp_circuit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
@@ -505,10 +506,15 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *exit_ei, int flags)
{
origin_circuit_t *circ;
int err_reason = 0;
+ int is_hs_v3_rp_circuit = 0;
+
+ if (flags & CIRCLAUNCH_IS_V3_RP) {
+ is_hs_v3_rp_circuit = 1;
+ }
circ = origin_circuit_init(purpose, flags);
- if (onion_pick_cpath_exit(circ, exit_ei) < 0 ||
+ if (onion_pick_cpath_exit(circ, exit_ei, is_hs_v3_rp_circuit) < 0 ||
onion_populate_cpath(circ) < 0) {
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_NOPATH);
return NULL;
@@ -2156,7 +2162,8 @@ pick_rendezvous_node(router_crn_flags_t flags)
*/
static const node_t *
choose_good_exit_server(uint8_t purpose,
- int need_uptime, int need_capacity, int is_internal)
+ int need_uptime, int need_capacity, int is_internal,
+ int need_hs_v3)
{
const or_options_t *options = get_options();
router_crn_flags_t flags = CRN_NEED_DESC;
@@ -2164,6 +2171,8 @@ choose_good_exit_server(uint8_t purpose,
flags |= CRN_NEED_UPTIME;
if (need_capacity)
flags |= CRN_NEED_CAPACITY;
+ if (need_hs_v3)
+ flags |= CRN_RENDEZVOUS_V3;
switch (purpose) {
case CIRCUIT_PURPOSE_C_GENERAL:
@@ -2263,9 +2272,15 @@ warn_if_last_router_excluded(origin_circuit_t *circ,
/** Decide a suitable length for circ's cpath, and pick an exit
* router (or use <b>exit</b> if provided). Store these in the
- * cpath. Return 0 if ok, -1 if circuit should be closed. */
+ * cpath.
+ *
+ * If <b>is_hs_v3_rp_circuit</b> is set, then this exit should be suitable to
+ * be used as an HS v3 rendezvous point.
+ *
+ * Return 0 if ok, -1 if circuit should be closed. */
static int
-onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei)
+onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei,
+ int is_hs_v3_rp_circuit)
{
cpath_build_state_t *state = circ->build_state;
@@ -2289,7 +2304,8 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei)
} else { /* we have to decide one */
const node_t *node =
choose_good_exit_server(circ->base_.purpose, state->need_uptime,
- state->need_capacity, state->is_internal);
+ state->need_capacity, state->is_internal,
+ is_hs_v3_rp_circuit);
if (!node) {
log_warn(LD_CIRC,"Failed to choose an exit server");
return -1;
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 2f3fe327e..774edc90b 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -1609,6 +1609,30 @@ circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
return NULL;
}
+/** We might cannibalize this circuit: Return true if its last hop can be used
+ * as a v3 rendezvous point. */
+static int
+circuit_can_be_cannibalized_for_v3_rp(const origin_circuit_t *circ)
+{
+ if (!circ->build_state) {
+ return 0;
+ }
+
+ extend_info_t *chosen_exit = circ->build_state->chosen_exit;
+ if (BUG(!chosen_exit)) {
+ return 0;
+ }
+
+ const node_t *rp_node = node_get_by_id(chosen_exit->identity_digest);
+ if (rp_node) {
+ if (node_supports_v3_rendezvous_point(rp_node)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/** Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL,
* has a timestamp_dirty value of 0, has flags matching the CIRCLAUNCH_*
* flags in <b>flags</b>, and if info is defined, does not already use info
@@ -1691,6 +1715,14 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
hop = hop->next;
} while (hop != circ->cpath);
}
+
+ if ((flags & CIRCLAUNCH_IS_V3_RP) &&
+ !circuit_can_be_cannibalized_for_v3_rp(circ)) {
+ log_debug(LD_GENERAL, "Skipping uncannibalizable circuit for v3 "
+ "rendezvous point.");
+ goto next;
+ }
+
if (!best || (best->build_state->need_uptime && !need_uptime))
best = circ;
next: ;
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 570b05e57..c229c84d9 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -2290,6 +2290,16 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
if (want_onehop) flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
if (need_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
if (need_internal) flags |= CIRCLAUNCH_IS_INTERNAL;
+
+ /* If we are about to pick a v3 RP right now, make sure we pick a
+ * rendezvous point that supports the v3 protocol! */
+ if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_REND_JOINED &&
+ new_circ_purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
+ ENTRY_TO_EDGE_CONN(conn)->hs_ident) {
+ flags |= CIRCLAUNCH_IS_V3_RP;
+ log_info(LD_GENERAL, "Getting rendezvous circuit to v3 service!");
+ }
+
circ = circuit_launch_by_extend_info(new_circ_purpose, extend_info,
flags);
}
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index e66679586..6c0bcbb35 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -44,6 +44,9 @@ void circuit_build_failed(origin_circuit_t *circ);
/** Flag to set when the last hop of a circuit doesn't need to be an
* exit node. */
#define CIRCLAUNCH_IS_INTERNAL (1<<3)
+/** Flag to set when we are trying to launch a v3 rendezvous circuit. We need
+ * to apply some additional filters on the node picked. */
+#define CIRCLAUNCH_IS_V3_RP (1<<4)
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int flags);
diff --git a/src/or/hs_client.c b/src/or/hs_client.c
index 99be058eb..2acc639e4 100644
--- a/src/or/hs_client.c
+++ b/src/or/hs_client.c
@@ -24,6 +24,7 @@
#include "circuitlist.h"
#include "circuituse.h"
#include "connection.h"
+#include "nodelist.h"
#include "circpathbias.h"
#include "connection.h"
#include "hs_ntor.h"
@@ -461,9 +462,21 @@ client_rendezvous_circ_has_opened(origin_circuit_t *circ)
tor_assert(circ);
tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
+ const extend_info_t *rp_ei = circ->build_state->chosen_exit;
+
+ /* Check that we didn't accidentally choose a node that does not understand
+ * the v3 rendezvous protocol */
+ if (rp_ei) {
+ const node_t *rp_node = node_get_by_id(rp_ei->identity_digest);
+ if (rp_node) {
+ if (BUG(!node_supports_v3_rendezvous_point(rp_node))) {
+ return;
+ }
+ }
+ }
+
log_info(LD_REND, "Rendezvous circuit has opened to %s.",
- safe_str_client(
- extend_info_describe(circ->build_state->chosen_exit)));
+ safe_str_client(extend_info_describe(rp_ei)));
/* Ignore returned value, nothing we can really do. On failure, the circuit
* will be marked for close. */
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 6acc87f96..f670870f6 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -863,6 +863,28 @@ node_supports_ed25519_hs_intro(const node_t *node)
return 0;
}
+/** Return true iff <b>node</b> supports to be a rendezvous point for hidden
+ * service version 3 (HSRend=2). */
+int
+node_supports_v3_rendezvous_point(const node_t *node)
+{
+ tor_assert(node);
+
+ if (node->rs) {
+ return node->rs->supports_v3_rendezvous_point;
+ }
+ if (node->ri) {
+ if (node->ri->protocol_list == NULL) {
+ return 0;
+ }
+ return protocol_list_supports_protocol(node->ri->protocol_list,
+ PRT_HSREND,
+ PROTOVER_HS_RENDEZVOUS_POINT_V3);
+ }
+ tor_assert_nonfatal_unreached_once();
+ return 0;
+}
+
/** Return the RSA ID key's SHA1 digest for the provided node. */
const uint8_t *
node_get_rsa_id_digest(const node_t *node)
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index d16cf0ecf..9676263f7 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -62,6 +62,7 @@ int node_ed25519_id_matches(const node_t *node,
int node_supports_ed25519_link_authentication(const node_t *node);
int node_supports_v3_hsdir(const node_t *node);
int node_supports_ed25519_hs_intro(const node_t *node);
+int node_supports_v3_rendezvous_point(const node_t *node);
const uint8_t *node_get_rsa_id_digest(const node_t *node);
int node_has_ipv6_addr(const node_t *node);
diff --git a/src/or/or.h b/src/or/or.h
index 5d55094a0..a2707b4d4 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2321,6 +2321,11 @@ typedef struct routerstatus_t {
* requires HSDir=2. */
unsigned int supports_v3_hsdir : 1;
+ /** True iff this router has a protocol list that allows it to be an hidden
+ * service rendezvous point supporting version 3 as seen in proposal 224.
+ * This requires HSRend=2. */
+ unsigned int supports_v3_rendezvous_point: 1;
+
unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
unsigned int bw_is_unmeasured:1; /**< This is a consensus entry, with
@@ -5381,7 +5386,10 @@ typedef enum {
CRN_PREF_ADDR = 1<<7,
/* On clients, only provide nodes that we can connect to directly, based on
* our firewall rules */
- CRN_DIRECT_CONN = 1<<8
+ CRN_DIRECT_CONN = 1<<8,
+ /* On clients, only provide nodes with HSRend >= 2 protocol version which
+ * is required for hidden service version >= 3. */
+ CRN_RENDEZVOUS_V3 = 1<<9,
} router_crn_flags_t;
/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
diff --git a/src/or/protover.h b/src/or/protover.h
index 2066aeec7..ec8da1a0d 100644
--- a/src/or/protover.h
+++ b/src/or/protover.h
@@ -21,6 +21,8 @@
#define PROTOVER_HSDIR_V3 2
/** The protover version number that signifies HSv3 intro point support */
#define PROTOVER_HS_INTRO_V3 4
+/** The protover version number that signifies HSv3 rendezvous point support */
+#define PROTOVER_HS_RENDEZVOUS_POINT_V3 2
/** List of recognized subprotocols. */
typedef enum protocol_type_t {
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 989401947..da2dff600 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -2799,6 +2799,7 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
const int need_desc = (flags & CRN_NEED_DESC) != 0;
const int pref_addr = (flags & CRN_PREF_ADDR) != 0;
const int direct_conn = (flags & CRN_DIRECT_CONN) != 0;
+ const int rendezvous_v3 = (flags & CRN_RENDEZVOUS_V3) != 0;
smartlist_t *sl=smartlist_new(),
*excludednodes=smartlist_new();
@@ -2810,12 +2811,19 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
rule = weight_for_exit ? WEIGHT_FOR_EXIT :
(need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID);
- /* Exclude relays that allow single hop exit circuits. This is an obsolete
- * option since 0.2.9.2-alpha and done by default in 0.3.1.0-alpha. */
- SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
if (node_allows_single_hop_exits(node)) {
+ /* Exclude relays that allow single hop exit circuits. This is an
+ * obsolete option since 0.2.9.2-alpha and done by default in
+ * 0.3.1.0-alpha. */
smartlist_add(excludednodes, node);
- });
+ } else if (rendezvous_v3 &&
+ !node_supports_v3_rendezvous_point(node)) {
+ /* Exclude relays that do not support to rendezvous for a hidden service
+ * version 3. */
+ smartlist_add(excludednodes, node);
+ }
+ } SMARTLIST_FOREACH_END(node);
if ((r = routerlist_find_my_routerinfo()))
routerlist_add_node_and_family(excludednodes, r);
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 9c11f4d07..08c3fc0a0 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -2708,6 +2708,9 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->supports_v3_hsdir =
protocol_list_supports_protocol(tok->args[0], PRT_HSDIR,
PROTOVER_HSDIR_V3);
+ rs->supports_v3_rendezvous_point =
+ protocol_list_supports_protocol(tok->args[0], PRT_HSDIR,
+ PROTOVER_HS_RENDEZVOUS_POINT_V3);
}
if ((tok = find_opt_by_keyword(tokens, K_V))) {
tor_assert(tok->n_args == 1);
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits