mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Canonicity update for ed25519.
If a node can prove its Ed25519 identity, don't consider connections to it canonical unless they match both identities. Includes link handshake changes needed to avoid crashing with bug warnings, since the tests now reach more parts of the code. Closes ticket 20355
This commit is contained in:
parent
424ae9e18b
commit
cd741cc595
@ -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_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
|
/** 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),
|
ed25519_fmt(ed_id),
|
||||||
started_here);
|
started_here);
|
||||||
|
|
||||||
const node_t *r = node_get_by_id(id_digest);
|
|
||||||
connection_or_set_identity_digest(conn, id_digest, ed_id);
|
connection_or_set_identity_digest(conn, id_digest, ed_id);
|
||||||
connection_or_update_token_buckets_helper(conn, 1, get_options());
|
connection_or_update_token_buckets_helper(conn, 1, get_options());
|
||||||
|
|
||||||
conn->base_.port = port;
|
conn->base_.port = port;
|
||||||
tor_addr_copy(&conn->base_.addr, addr);
|
tor_addr_copy(&conn->base_.addr, addr);
|
||||||
tor_addr_copy(&conn->real_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) {
|
if (r) {
|
||||||
tor_addr_port_t node_ap;
|
tor_addr_port_t node_ap;
|
||||||
node_get_pref_orport(r, &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);
|
tor_addr_copy(&conn->base_.addr, &node_ap.addr);
|
||||||
conn->base_.port = node_ap.port;
|
conn->base_.port = node_ap.port;
|
||||||
}
|
}
|
||||||
|
tor_free(conn->nickname);
|
||||||
conn->nickname = tor_strdup(node_get_nickname(r));
|
conn->nickname = tor_strdup(node_get_nickname(r));
|
||||||
tor_free(conn->base_.address);
|
tor_free(conn->base_.address);
|
||||||
conn->base_.address = tor_addr_to_str_dup(&node_ap.addr);
|
conn->base_.address = tor_addr_to_str_dup(&node_ap.addr);
|
||||||
} else {
|
} else {
|
||||||
|
tor_free(conn->nickname);
|
||||||
conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
|
conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
|
||||||
conn->nickname[0] = '$';
|
conn->nickname[0] = '$';
|
||||||
base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
|
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();
|
const or_options_t *options = get_options();
|
||||||
channel_tls_t *chan_tls = conn->chan;
|
channel_tls_t *chan_tls = conn->chan;
|
||||||
channel_t *chan = channel_tls_to_base(chan_tls);
|
channel_t *chan = channel_tls_to_base(chan_tls);
|
||||||
|
int changed_identity = 0;
|
||||||
tor_assert(chan);
|
tor_assert(chan);
|
||||||
|
|
||||||
const int expected_rsa_key =
|
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. */
|
* we do -- remember it for future attempts. */
|
||||||
learned_router_identity(&conn->base_.addr, conn->base_.port,
|
learned_router_identity(&conn->base_.addr, conn->base_.port,
|
||||||
(const char*)rsa_peer_id, ed_peer_id);
|
(const char*)rsa_peer_id, ed_peer_id);
|
||||||
|
changed_identity = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int rsa_mismatch = expected_rsa_key &&
|
const int rsa_mismatch = expected_rsa_key &&
|
||||||
@ -1706,6 +1738,13 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
|||||||
"connection.");
|
"connection.");
|
||||||
connection_or_set_identity_digest(conn,
|
connection_or_set_identity_digest(conn,
|
||||||
(const char*)rsa_peer_id, ed_peer_id);
|
(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)) {
|
if (authdir_mode_tests_reachability(options)) {
|
||||||
|
@ -117,6 +117,9 @@ test_link_handshake_certs_ok(void *arg)
|
|||||||
crypto_pk_t *key1 = NULL, *key2 = NULL;
|
crypto_pk_t *key1 = NULL, *key2 = NULL;
|
||||||
const int with_ed = !strcmp((const char *)arg, "Ed25519");
|
const int with_ed = !strcmp((const char *)arg, "Ed25519");
|
||||||
|
|
||||||
|
tor_addr_from_ipv4h(&c1->base_.addr, 0x7f000001);
|
||||||
|
tor_addr_from_ipv4h(&c2->base_.addr, 0x7f000001);
|
||||||
|
|
||||||
scheduler_init();
|
scheduler_init();
|
||||||
|
|
||||||
MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key);
|
MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key);
|
||||||
@ -354,6 +357,7 @@ recv_certs_setup(const struct testcase_t *test)
|
|||||||
d->chan = tor_malloc_zero(sizeof(*d->chan));
|
d->chan = tor_malloc_zero(sizeof(*d->chan));
|
||||||
d->c->chan = d->chan;
|
d->c->chan = d->chan;
|
||||||
d->c->base_.address = tor_strdup("HaveAnAddress");
|
d->c->base_.address = tor_strdup("HaveAnAddress");
|
||||||
|
tor_addr_from_ipv4h(&d->c->base_.addr, 0x801f0127);
|
||||||
d->c->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
|
d->c->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3;
|
||||||
d->chan->conn = d->c;
|
d->chan->conn = d->c;
|
||||||
tt_int_op(connection_init_or_handshake_state(d->c, 1), ==, 0);
|
tt_int_op(connection_init_or_handshake_state(d->c, 1), ==, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user