Fix gossip announce address binding

This commit is contained in:
2026-06-17 16:17:03 -04:00
parent 22f0eed94d
commit 8982df364e
+23 -6
View File
@@ -79,6 +79,8 @@ enum GossipReject {
BadSignature,
/// Timestamp outside the freshness window — stale (replay) or implausibly future.
OutOfWindow,
/// A signed Announce advertised an address for a different node id.
AnnounceAddressMismatch,
}
/// Authenticate a received payload against the room topic and local clock. The
@@ -99,6 +101,10 @@ fn verify_gossip(
if now_ms.abs_diff(payload.ts) > window_ms {
return Err(GossipReject::OutOfWindow);
}
if let GossipMessage::Announce(state) = &payload.msg
&& state.addr.id != payload.author {
return Err(GossipReject::AnnounceAddressMismatch);
}
Ok(())
}
@@ -490,10 +496,8 @@ mod tests {
use crate::network::PeerState;
use iroh::SecretKey;
fn sample_peer_state() -> PeerState {
let secret = SecretKey::generate();
let public = secret.public();
let addr = iroh::EndpointAddr::from(public);
fn sample_peer_state_for(id: EndpointId) -> PeerState {
let addr = iroh::EndpointAddr::from(id);
PeerState {
name: "TestPeerGossip".to_string(),
is_muted: true,
@@ -563,7 +567,7 @@ mod tests {
fn test_gossip_payload_announce_round_trip() {
let secret = SecretKey::generate();
let topic = [9u8; 32];
let peer_state = sample_peer_state();
let peer_state = sample_peer_state_for(secret.public());
let payload = sign_gossip(&secret, &topic, 1000, GossipMessage::Announce(peer_state.clone()));
let serialized = serde_json::to_string(&payload).unwrap();
@@ -732,5 +736,18 @@ mod tests {
// Within the window (clock skew tolerance) → accepted.
assert!(verify_gossip(&p, &topic, 1_000_000 + GOSSIP_FRESHNESS_MS - 1, GOSSIP_FRESHNESS_MS).is_ok());
}
}
#[test]
fn verify_rejects_announce_with_address_for_another_identity() {
let signer = SecretKey::generate();
let advertised = SecretKey::generate();
let topic = [6u8; 32];
let state = sample_peer_state_for(advertised.public());
let p = sign_gossip(&signer, &topic, 5_000, GossipMessage::Announce(state));
assert_eq!(
verify_gossip(&p, &topic, 5_000, GOSSIP_FRESHNESS_MS),
Err(GossipReject::AnnounceAddressMismatch)
);
}
}