|
@@ -75,6 +75,9 @@ static void connection_or_mark_bad_for_new_circs(or_connection_t *or_conn);
|
|
|
|
|
|
static void connection_or_change_state(or_connection_t *conn, uint8_t state);
|
|
|
|
|
|
+static void connection_or_check_canonicity(or_connection_t *conn,
|
|
|
+ int started_here);
|
|
|
+
|
|
|
/**************************************************************/
|
|
|
|
|
|
/** Global map between Extended ORPort identifiers and OR
|
|
@@ -869,13 +872,38 @@ connection_or_init_conn_from_address(or_connection_t *conn,
|
|
|
ed25519_fmt(ed_id),
|
|
|
started_here);
|
|
|
|
|
|
- const node_t *r = node_get_by_id(id_digest);
|
|
|
connection_or_set_identity_digest(conn, id_digest, ed_id);
|
|
|
connection_or_update_token_buckets_helper(conn, 1, get_options());
|
|
|
|
|
|
conn->base_.port = port;
|
|
|
tor_addr_copy(&conn->base_.addr, addr);
|
|
|
tor_addr_copy(&conn->real_addr, addr);
|
|
|
+
|
|
|
+ connection_or_check_canonicity(conn, started_here);
|
|
|
+}
|
|
|
+
|
|
|
+/** Check whether the identity of <b>conn</b> matches a known node. If it
|
|
|
+ * does, check whether the address of conn matches the expected address, and
|
|
|
+ * update the connection's is_canonical flag, nickname, and address fields as
|
|
|
+ * appropriate. */
|
|
|
+static void
|
|
|
+connection_or_check_canonicity(or_connection_t *conn, int started_here)
|
|
|
+{
|
|
|
+ const char *id_digest = conn->identity_digest;
|
|
|
+ const ed25519_public_key_t *ed_id = NULL;
|
|
|
+ const tor_addr_t *addr = &conn->real_addr;
|
|
|
+ if (conn->chan)
|
|
|
+ ed_id = & TLS_CHAN_TO_BASE(conn->chan)->ed25519_identity;
|
|
|
+
|
|
|
+ const node_t *r = node_get_by_id(id_digest);
|
|
|
+ if (r &&
|
|
|
+ node_supports_ed25519_link_authentication(r) &&
|
|
|
+ ! 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. */
|
|
|
+ r = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
if (r) {
|
|
|
tor_addr_port_t node_ap;
|
|
|
node_get_pref_orport(r, &node_ap);
|
|
@@ -897,10 +925,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
|
|
|
tor_addr_copy(&conn->base_.addr, &node_ap.addr);
|
|
|
conn->base_.port = node_ap.port;
|
|
|
}
|
|
|
+ tor_free(conn->nickname);
|
|
|
conn->nickname = tor_strdup(node_get_nickname(r));
|
|
|
tor_free(conn->base_.address);
|
|
|
conn->base_.address = tor_addr_to_str_dup(&node_ap.addr);
|
|
|
} else {
|
|
|
+ tor_free(conn->nickname);
|
|
|
conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
|
|
|
conn->nickname[0] = '$';
|
|
|
base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
|
|
@@ -1589,6 +1619,7 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
|
|
const or_options_t *options = get_options();
|
|
|
channel_tls_t *chan_tls = conn->chan;
|
|
|
channel_t *chan = channel_tls_to_base(chan_tls);
|
|
|
+ int changed_identity = 0;
|
|
|
tor_assert(chan);
|
|
|
|
|
|
const int expected_rsa_key =
|
|
@@ -1619,6 +1650,7 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
|
|
* we do -- remember it for future attempts. */
|
|
|
learned_router_identity(&conn->base_.addr, conn->base_.port,
|
|
|
(const char*)rsa_peer_id, ed_peer_id);
|
|
|
+ changed_identity = 1;
|
|
|
}
|
|
|
|
|
|
const int rsa_mismatch = expected_rsa_key &&
|
|
@@ -1706,6 +1738,13 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
|
|
"connection.");
|
|
|
connection_or_set_identity_digest(conn,
|
|
|
(const char*)rsa_peer_id, ed_peer_id);
|
|
|
+ changed_identity = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (changed_identity) {
|
|
|
+ /* If we learned an identity for this connection, then we might have
|
|
|
+ * just discovered it to be canonical. */
|
|
|
+ connection_or_check_canonicity(conn, conn->handshake_state->started_here);
|
|
|
}
|
|
|
|
|
|
if (authdir_mode_tests_reachability(options)) {
|