|
@@ -1547,8 +1547,24 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
|
|
const ed25519_public_key_t *ed_peer_id)
|
|
|
{
|
|
|
const or_options_t *options = get_options();
|
|
|
-
|
|
|
- if (tor_digest_is_zero(conn->identity_digest)) {
|
|
|
+ channel_tls_t *chan_tls = conn->chan;
|
|
|
+ channel_t *chan = channel_tls_to_base(chan_tls);
|
|
|
+ tor_assert(chan);
|
|
|
+
|
|
|
+ const int expected_rsa_key =
|
|
|
+ ! tor_digest_is_zero(conn->identity_digest);
|
|
|
+ const int expected_ed_key =
|
|
|
+ ! ed25519_public_key_is_zero(&chan->ed25519_identity);
|
|
|
+
|
|
|
+ log_info(LD_HANDSHAKE, "learned peer id for %p (%s): %s, %s",
|
|
|
+ conn,
|
|
|
+ safe_str_client(conn->base_.address),
|
|
|
+ hex_str((const char*)rsa_peer_id, DIGEST_LEN),
|
|
|
+ ed25519_fmt(ed_peer_id));
|
|
|
+
|
|
|
+ if (! expected_rsa_key && ! expected_ed_key) {
|
|
|
+ log_info(LD_HANDSHAKE, "(we had no ID in mind when we made this "
|
|
|
+ "connection.");
|
|
|
connection_or_set_identity_digest(conn,
|
|
|
(const char*)rsa_peer_id, ed_peer_id);
|
|
|
tor_free(conn->nickname);
|
|
@@ -1565,13 +1581,35 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
|
|
(const char*)rsa_peer_id, ed_peer_id);
|
|
|
}
|
|
|
|
|
|
- if (tor_memneq(rsa_peer_id, conn->identity_digest, DIGEST_LEN)) {
|
|
|
+ const int rsa_mismatch = expected_rsa_key &&
|
|
|
+ tor_memneq(rsa_peer_id, conn->identity_digest, DIGEST_LEN);
|
|
|
+ /* It only counts as an ed25519 mismatch if we wanted an ed25519 identity
|
|
|
+ * and didn't get it. It's okay if we get one that we didn't ask for. */
|
|
|
+ const int ed25519_mismatch =
|
|
|
+ expected_ed_key &&
|
|
|
+ (ed_peer_id == NULL ||
|
|
|
+ ! ed25519_pubkey_eq(&chan->ed25519_identity, ed_peer_id));
|
|
|
+
|
|
|
+ if (rsa_mismatch || ed25519_mismatch) {
|
|
|
/* I was aiming for a particular digest. I didn't get it! */
|
|
|
- char seen[HEX_DIGEST_LEN+1];
|
|
|
- char expected[HEX_DIGEST_LEN+1];
|
|
|
- base16_encode(seen, sizeof(seen), (const char*)rsa_peer_id, DIGEST_LEN);
|
|
|
- base16_encode(expected, sizeof(expected), conn->identity_digest,
|
|
|
+ char seen_rsa[HEX_DIGEST_LEN+1];
|
|
|
+ char expected_rsa[HEX_DIGEST_LEN+1];
|
|
|
+ char seen_ed[ED25519_BASE64_LEN+1];
|
|
|
+ char expected_ed[ED25519_BASE64_LEN+1];
|
|
|
+ base16_encode(seen_rsa, sizeof(seen_rsa),
|
|
|
+ (const char*)rsa_peer_id, DIGEST_LEN);
|
|
|
+ base16_encode(expected_rsa, sizeof(expected_rsa), conn->identity_digest,
|
|
|
DIGEST_LEN);
|
|
|
+ if (ed_peer_id) {
|
|
|
+ ed25519_public_to_base64(seen_ed, ed_peer_id);
|
|
|
+ } else {
|
|
|
+ strlcpy(seen_ed, "no ed25519 key", sizeof(seen_ed));
|
|
|
+ }
|
|
|
+ if (! ed25519_public_key_is_zero(&chan->ed25519_identity)) {
|
|
|
+ ed25519_public_to_base64(expected_ed, &chan->ed25519_identity);
|
|
|
+ } else {
|
|
|
+ strlcpy(expected_ed, "no ed25519 key", sizeof(expected_ed));
|
|
|
+ }
|
|
|
const int using_hardcoded_fingerprints =
|
|
|
!networkstatus_get_reasonably_live_consensus(time(NULL),
|
|
|
usable_consensus_flavor());
|
|
@@ -1606,9 +1644,11 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
|
|
}
|
|
|
|
|
|
log_fn(severity, LD_HANDSHAKE,
|
|
|
- "Tried connecting to router at %s:%d, but identity key was not "
|
|
|
- "as expected: wanted %s but got %s.%s",
|
|
|
- conn->base_.address, conn->base_.port, expected, seen, extra_log);
|
|
|
+ "Tried connecting to router at %s:%d, but RSA identity key was not "
|
|
|
+ "as expected: wanted %s + %s but got %s + %s.%s",
|
|
|
+ conn->base_.address, conn->base_.port,
|
|
|
+ expected_rsa, expected_ed, seen_rsa, seen_ed, extra_log);
|
|
|
+
|
|
|
entry_guard_register_connect_status(conn->identity_digest, 0, 1,
|
|
|
time(NULL));
|
|
|
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
|
|
@@ -1621,7 +1661,12 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- /* XXXX 15056 -- use the Ed25519 key */
|
|
|
+ if (!expected_ed_key && ed_peer_id) {
|
|
|
+ log_info(LD_HANDSHAKE, "(we had no Ed25519 ID in mind when we made this "
|
|
|
+ "connection.");
|
|
|
+ connection_or_set_identity_digest(conn,
|
|
|
+ (const char*)rsa_peer_id, ed_peer_id);
|
|
|
+ }
|
|
|
|
|
|
if (authdir_mode_tests_reachability(options)) {
|
|
|
dirserv_orconn_tls_done(&conn->base_.addr, conn->base_.port,
|