diff options
-rw-r--r-- | src/or/connection_or.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/src/or/connection_or.c b/src/or/connection_or.c index e10eaaf35c..2889bb7a4d 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -105,20 +105,51 @@ connection_or_clear_identity_map(void) } /** Change conn->identity_digest to digest, and add conn into - * orconn_digest_map. */ + * the appropriate digest maps. + * + * NOTE that this function only allows two kinds of transitions: from + * unset identity to set identity, and from idempotent re-settings + * of the same identity. It's not allowed to clear an identity or to + * change an identity. Return 0 on success, and -1 if the transition + * is not allowed. + **/ static void connection_or_set_identity_digest(or_connection_t *conn, const char *rsa_digest, const ed25519_public_key_t *ed_id) { + channel_t *chan = NULL; tor_assert(conn); tor_assert(rsa_digest); - if (tor_memeq(conn->identity_digest, rsa_digest, DIGEST_LEN)) + if (conn->chan) + chan = TLS_CHAN_TO_BASE(conn->chan); + + log_info(LD_HANDSHAKE, "Set identity digest for %p (%s): %s %s.", + conn, + escaped_safe_str(conn->base_.address), + hex_str(rsa_digest, DIGEST_LEN), + ed25519_fmt(ed_id)); + log_info(LD_HANDSHAKE, " (Previously: %s %s)", + hex_str(conn->identity_digest, DIGEST_LEN), + chan ? ed25519_fmt(&chan->ed25519_identity) : "<null>"); + + const int rsa_id_was_set = ! tor_digest_is_zero(conn->identity_digest); + const int ed_id_was_set = + chan && !ed25519_public_key_is_zero(&chan->ed25519_identity); + const int rsa_changed = + tor_memneq(conn->identity_digest, rsa_digest, DIGEST_LEN); + const int ed_changed = ed_id_was_set && + (!ed_id || !ed25519_pubkey_eq(ed_id, &chan->ed25519_identity)); + + tor_assert(!rsa_changed || !rsa_id_was_set); + tor_assert(!ed_changed || !ed_id_was_set); + + if (!rsa_changed && !ed_changed) return; /* If the identity was set previously, remove the old mapping. */ - if (! tor_digest_is_zero(conn->identity_digest)) { + if (rsa_id_was_set) { connection_or_clear_identity(conn); if (conn->chan) channel_clear_identity_digest(TLS_CHAN_TO_BASE(conn->chan)); @@ -126,8 +157,9 @@ connection_or_set_identity_digest(or_connection_t *conn, memcpy(conn->identity_digest, rsa_digest, DIGEST_LEN); - /* If we're setting the ID to zero, don't add a mapping. */ - if (tor_digest_is_zero(rsa_digest)) + /* If we're initializing the IDs to zero, don't add a mapping yet. */ + if (tor_digest_is_zero(rsa_digest) && + (!ed_id || ed25519_public_key_is_zero(ed_id))) return; /* Deal with channels */ |