[tor-commits] [tor/master] Clients avoid choosing nodes that can't do ntor

nickm at torproject.org nickm at torproject.org
Mon Aug 29 19:11:31 UTC 2016


commit 579a80d4ae54ec03fd9b02c4a125b2943770c85d
Author: teor (Tim Wilson-Brown) <teor2345 at gmail.com>
Date:   Thu Jul 7 12:58:47 2016 +1000

    Clients avoid choosing nodes that can't do ntor
    
    If we know a node's version, and it can't do ntor, consider it not running.
    If we have a node's descriptor, and it doesn't have a valid ntor key,
    consider it not running.
    
    Refactor these checks so they're consistent between authorities and clients.
---
 changes/reject-tap     |  3 +++
 src/or/circuitbuild.c  |  7 ++++---
 src/or/dirserv.c       |  4 +---
 src/or/networkstatus.c |  6 ++++--
 src/or/nodelist.c      | 25 +++++++++++++++++++++++--
 src/or/routerlist.c    | 44 ++++++++++++++++++++++++++++++++++++++++++++
 src/or/routerlist.h    |  3 +++
 7 files changed, 82 insertions(+), 10 deletions(-)

diff --git a/changes/reject-tap b/changes/reject-tap
index 77ca63b..7580018 100644
--- a/changes/reject-tap
+++ b/changes/reject-tap
@@ -7,4 +7,7 @@
       instead, they check specifically for an ntor key.
     - Clients avoid downloading a descriptor if the relay version is
       too old to support ntor.
+    - Client code ignores nodes without ntor keys: they will not be
+      selected during circuit-building, or as guards, or as directory
+      mirrors, or as introduction or rendezvous points.
       Fixes bug 19163; bugfix on 0.2.4.18-rc.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 13cc166..d6c5c85 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -820,8 +820,8 @@ circuit_pick_create_handshake(uint8_t *cell_type_out,
 
 /** Decide whether to use a TAP or ntor handshake for connecting to <b>ei</b>
  * directly, and set *<b>handshake_type_out</b> accordingly. Decide whether,
- * in extending through <b>node</b> to do so, we should use an EXTEND2 or an
- * EXTEND cell to do so, and set *<b>cell_type_out</b> and
+ * in extending through <b>node_prev</b> to do so, we should use an EXTEND2 or
+ * an EXTEND cell to do so, and set *<b>cell_type_out</b> and
  * *<b>create_cell_type_out</b> accordingly. */
 static void
 circuit_pick_extend_handshake(uint8_t *cell_type_out,
@@ -837,7 +837,8 @@ circuit_pick_extend_handshake(uint8_t *cell_type_out,
   if (node_prev &&
       *handshake_type_out != ONION_HANDSHAKE_TYPE_TAP &&
       (node_has_curve25519_onion_key(node_prev) ||
-       (node_prev->rs && node_prev->rs->version_supports_extend2_cells))) {
+       (node_prev->rs &&
+        routerstatus_version_supports_ntor(node_prev->rs, 0)))) {
     *cell_type_out = RELAY_COMMAND_EXTEND2;
     *create_cell_type_out = CELL_CREATE2;
   } else {
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index ef3a305..ff50ca4 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -260,9 +260,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
    * But just in case a relay doesn't provide or lies about its version, or
    * doesn't include an ntor key in its descriptor, check that it exists,
    * and is non-zero (clients check that it's non-zero before using it). */
-  if (router->onion_curve25519_pkey == NULL ||
-      tor_mem_is_zero((const char*)router->onion_curve25519_pkey->public_key,
-                      CURVE25519_PUBKEY_LEN)) {
+  if (!routerinfo_has_curve25519_onion_key(router)) {
     log_fn(severity, LD_DIR,
            "Descriptor from router %s is missing an ntor curve25519 onion "
            "key.", router_describe(router));
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 61753e5..1223788 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -2272,8 +2272,10 @@ client_would_use_router(const routerstatus_t *rs, time_t now,
     /* We'd drop it immediately for being too old. */
     return 0;
   }
-  if (rs->version_known && !rs->version_supports_extend2_cells) {
-    /* We'd ignore it because it doesn't support ntor. */
+  if (!routerstatus_version_supports_ntor(rs, 1)) {
+    /* We'd ignore it because it doesn't support ntor.
+     * If we don't know the version, download the descriptor so we can
+     * check if it supports ntor. */
     return 0;
   }
   return 1;
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index a49bf03..a888ebe 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -1171,14 +1171,35 @@ node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out)
   }
 }
 
+/** Return true iff <b>md</b> has a curve25519 onion key.
+ * Use node_has_curve25519_onion_key() instead of calling this directly. */
+static int
+microdesc_has_curve25519_onion_key(const microdesc_t *md)
+{
+  if (!md) {
+    return 0;
+  }
+
+  if (!md->onion_curve25519_pkey) {
+    return 0;
+  }
+
+  if (tor_mem_is_zero((const char*)md->onion_curve25519_pkey->public_key,
+                      CURVE25519_PUBKEY_LEN)) {
+    return 0;
+  }
+
+  return 1;
+}
+
 /** Return true iff <b>node</b> has a curve25519 onion key. */
 int
 node_has_curve25519_onion_key(const node_t *node)
 {
   if (node->ri)
-    return node->ri->onion_curve25519_pkey != NULL;
+    return routerinfo_has_curve25519_onion_key(node->ri);
   else if (node->md)
-    return node->md->onion_curve25519_pkey != NULL;
+    return microdesc_has_curve25519_onion_key(node->md);
   else
     return 0;
 }
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 6ea9d8b..0801503 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -2260,6 +2260,11 @@ router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
       continue;
     if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
       continue;
+    /* Don't choose nodes if we are certain they can't do ntor */
+    if (node->rs && !routerstatus_version_supports_ntor(node->rs, 1))
+      continue;
+    if ((node->ri || node->md) && !node_has_curve25519_onion_key(node))
+      continue;
     /* Choose a node with an OR address that matches the firewall rules */
     if (check_reach && !fascist_firewall_allows_node(node,
                                                      FIREWALL_OR_CONNECTION,
@@ -5488,6 +5493,45 @@ routerinfo_incompatible_with_extrainfo(const crypto_pk_t *identity_pkey,
   return r;
 }
 
+/* Does ri have a valid ntor onion key?
+ * Valid ntor onion keys exist and have at least one non-zero byte. */
+int
+routerinfo_has_curve25519_onion_key(const routerinfo_t *ri)
+{
+  if (!ri) {
+    return 0;
+  }
+
+  if (!ri->onion_curve25519_pkey) {
+    return 0;
+  }
+
+  if (tor_mem_is_zero((const char*)ri->onion_curve25519_pkey->public_key,
+                      CURVE25519_PUBKEY_LEN)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+/* Is rs running a tor version known to support ntor?
+ * If allow_unknown_versions is true, return true if the version is unknown.
+ * Otherwise, return false if the version is unknown. */
+int
+routerstatus_version_supports_ntor(const routerstatus_t *rs,
+                                   int allow_unknown_versions)
+{
+  if (!rs) {
+    return allow_unknown_versions;
+  }
+
+  if (!rs->version_known) {
+    return allow_unknown_versions;
+  }
+
+  return rs->version_supports_extend2_cells;
+}
+
 /** Assert that the internal representation of <b>rl</b> is
  * self-consistent. */
 void
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index 01f7644..4041a38 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -205,6 +205,9 @@ int routerinfo_incompatible_with_extrainfo(const crypto_pk_t *ri,
                                            extrainfo_t *ei,
                                            signed_descriptor_t *sd,
                                            const char **msg);
+int routerinfo_has_curve25519_onion_key(const routerinfo_t *ri);
+int routerstatus_version_supports_ntor(const routerstatus_t *rs,
+                                       int allow_unknown_versions);
 
 void routerlist_assert_ok(const routerlist_t *rl);
 const char *esc_router_info(const routerinfo_t *router);





More information about the tor-commits mailing list