diff --git a/changes/ticket20895 b/changes/ticket20895 new file mode 100644 index 0000000000000000000000000000000000000000..a1d82049978e8fa685e2d2bc76b834a311368a77 --- /dev/null +++ b/changes/ticket20895 @@ -0,0 +1,6 @@ + o Minor features (forward-compatibility): + - If a relay supports some link authentication protocol that we do not + recognize, then include that relay's ed25519 key when telling other + relays to extend to it. Previously, we treated future versions as if + they were too old to support ed25519 link authentication. + Closes ticket 20895. diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 279308afcbf9db1e26978bba73981e20a6b1b2a4..45bf0195450074009c50aa0cd71edd9126988d90 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1290,7 +1290,7 @@ circuit_extend(cell_t *cell, circuit_t *circ) const node_t *node = node_get_by_id((const char*)ec.node_id); const ed25519_public_key_t *node_ed_id = NULL; if (node && - node_supports_ed25519_link_authentication(node) && + node_supports_ed25519_link_authentication(node, 1) && (node_ed_id = node_get_ed25519_id(node))) { ed25519_pubkey_copy(&ec.ed_pubkey, node_ed_id); } @@ -2698,7 +2698,7 @@ extend_info_from_node(const node_t *node, int for_direct_connect) /* Don't send the ed25519 pubkey unless the target node actually supports * authenticating with it. */ - if (node_supports_ed25519_link_authentication(node)) { + if (node_supports_ed25519_link_authentication(node, 0)) { log_info(LD_CIRC, "Including Ed25519 ID for %s", node_describe(node)); ed_pubkey = node_get_ed25519_id(node); } else if (node_get_ed25519_id(node)) { diff --git a/src/or/connection_or.c b/src/or/connection_or.c index d890b58da6fe04867f27ce43e3b8ba22ed2a5964..29c1166b3c58c66bd5021de3597997cb8f55835b 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -886,7 +886,7 @@ connection_or_check_canonicity(or_connection_t *conn, int started_here) const node_t *r = node_get_by_id(id_digest); if (r && - node_supports_ed25519_link_authentication(r) && + node_supports_ed25519_link_authentication(r, 1) && ! node_ed25519_id_matches(r, ed_id)) { /* If this node is capable of proving an ed25519 ID, * we can't call this a canonical connection unless both IDs match. */ diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 06ac15d587c5392efbd439cf84fe8488b65ac862..75cd0879aa2104677c74309e9f5f0f3defda8966 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -3284,7 +3284,7 @@ dirserv_orconn_tls_done(const tor_addr_t *addr, ri = node->ri; if (get_options()->AuthDirTestEd25519LinkKeys && - node_supports_ed25519_link_authentication(node) && + node_supports_ed25519_link_authentication(node, 1) && ri->cache_info.signing_key_cert) { /* We allow the node to have an ed25519 key if we haven't been told one in * the routerinfo, but if we *HAVE* been told one in the routerinfo, it @@ -3367,7 +3367,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router) tor_assert(node); if (options->AuthDirTestEd25519LinkKeys && - node_supports_ed25519_link_authentication(node)) { + node_supports_ed25519_link_authentication(node, 1)) { ed_id_key = &router->cache_info.signing_key_cert->signing_key; } else { ed_id_key = NULL; diff --git a/src/or/hs_service.c b/src/or/hs_service.c index 5759aa81273157bd97cc33d434bd5fd4eacc1c54..5ae7614e2963ac24e0d3400bbb9cf86fdff1dfc4 100644 --- a/src/or/hs_service.c +++ b/src/or/hs_service.c @@ -1494,7 +1494,7 @@ pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes) /* Let's do a basic sanity check here so that we don't end up advertising the * ed25519 identity key of relays that don't actually support the link * protocol */ - if (!node_supports_ed25519_link_authentication(node)) { + if (!node_supports_ed25519_link_authentication(node, 0)) { tor_assert_nonfatal(ed25519_public_key_is_zero(&info->ed_identity)); } diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 00b8fb144fadbf68b3a20c41a3fff0620229364c..1f2d37f285f4773edf493e96c5566f8259350bd4 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -962,23 +962,29 @@ node_ed25519_id_matches(const node_t *node, const ed25519_public_key_t *id) } /** Return true iff <b>node</b> supports authenticating itself - * by ed25519 ID during the link handshake in a way that we can understand - * when we probe it. */ + * by ed25519 ID during the link handshake. If <b>compatible_with_us</b>, + * it needs to be using a link authentication method that we understand. + * If not, any plausible link authentication method will do. */ int -node_supports_ed25519_link_authentication(const node_t *node) +node_supports_ed25519_link_authentication(const node_t *node, + int compatible_with_us) { - /* XXXX Oh hm. What if some day in the future there are link handshake - * versions that aren't 3 but which are ed25519 */ if (! node_get_ed25519_id(node)) return 0; if (node->ri) { const char *protos = node->ri->protocol_list; if (protos == NULL) return 0; - return protocol_list_supports_protocol(protos, PRT_LINKAUTH, 3); + if (compatible_with_us) + return protocol_list_supports_protocol(protos, PRT_LINKAUTH, 3); + else + return protocol_list_supports_protocol_or_later(protos, PRT_LINKAUTH, 3); } if (node->rs) { - return node->rs->supports_ed25519_link_handshake; + if (compatible_with_us) + return node->rs->supports_ed25519_link_handshake_compat; + else + return node->rs->supports_ed25519_link_handshake_any; } tor_assert_nonfatal_unreached_once(); return 0; diff --git a/src/or/nodelist.h b/src/or/nodelist.h index 427e449ad92a1ce81925e916c41da5fa3430d7d3..58743c5e78d7d4911d8a7bc93fe5b0afd30aaf80 100644 --- a/src/or/nodelist.h +++ b/src/or/nodelist.h @@ -65,7 +65,8 @@ const smartlist_t *node_get_declared_family(const node_t *node); const ed25519_public_key_t *node_get_ed25519_id(const node_t *node); int node_ed25519_id_matches(const node_t *node, const ed25519_public_key_t *id); -int node_supports_ed25519_link_authentication(const node_t *node); +int node_supports_ed25519_link_authentication(const node_t *node, + int compatible_with_us); 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); diff --git a/src/or/or.h b/src/or/or.h index 161d80ed96ca5d099fe030db6e1d940e6be1ff99..8e1d15b8cbab711ca1d042731dc6414983a7b317 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2316,8 +2316,12 @@ typedef struct routerstatus_t { unsigned int supports_extend2_cells:1; /** True iff this router has a protocol list that allows it to negotiate - * ed25519 identity keys on a link handshake. */ - unsigned int supports_ed25519_link_handshake:1; + * ed25519 identity keys on a link handshake with us. */ + unsigned int supports_ed25519_link_handshake_compat:1; + + /** True iff this router has a protocol list that allows it to negotiate + * ed25519 identity keys on a link handshake, at all. */ + unsigned int supports_ed25519_link_handshake_any:1; /** True iff this router has a protocol list that allows it to be an * introduction point supporting ed25519 authentication key which is part of diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 08c3fc0a026b263bca69cc16f4c3d2d384c51389..b26231db01a401fd170307325029d40cb39efd74 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -2701,8 +2701,10 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->protocols_known = 1; rs->supports_extend2_cells = protocol_list_supports_protocol(tok->args[0], PRT_RELAY, 2); - rs->supports_ed25519_link_handshake = + rs->supports_ed25519_link_handshake_compat = protocol_list_supports_protocol(tok->args[0], PRT_LINKAUTH, 3); + rs->supports_ed25519_link_handshake_any = + protocol_list_supports_protocol_or_later(tok->args[0], PRT_LINKAUTH, 3); rs->supports_ed25519_hs_intro = protocol_list_supports_protocol(tok->args[0], PRT_HSINTRO, 4); rs->supports_v3_hsdir =