mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-22 07:48:26 +00:00
Fix identity cache miss during lookup response verification
Guard discovery triggers in handle_path_broken() and handle_coords_required() with has_cached_identity() check. When the XK responder receives an error signal before msg3 completes, the initiator's identity is unknown, making LookupResponse proof verification impossible. Skip discovery in this case — the handshake retry mechanism handles recovery. Downgrade the identity_cache miss log from ERROR to WARN since it's a known race condition, not a bug.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
use crate::node::{Node, RecentRequest};
|
||||
use crate::protocol::{LookupRequest, LookupResponse};
|
||||
use crate::{NodeAddr, PeerIdentity};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
impl Node {
|
||||
/// Handle an incoming LookupRequest from a peer.
|
||||
@@ -153,10 +153,10 @@ impl Node {
|
||||
let target_pubkey = match self.lookup_by_fips_prefix(&prefix) {
|
||||
Some((_addr, pubkey)) => pubkey,
|
||||
None => {
|
||||
error!(
|
||||
warn!(
|
||||
request_id = response.request_id,
|
||||
target = %self.peer_display_name(&target),
|
||||
"identity_cache miss for lookup target — this is a bug"
|
||||
"identity_cache miss for lookup target, cannot verify proof"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -731,7 +731,14 @@ impl Node {
|
||||
"CoordsRequired response rate-limited, skipping standalone CoordsWarmup");
|
||||
}
|
||||
|
||||
self.maybe_initiate_lookup(&msg.dest_addr).await;
|
||||
// Only trigger discovery if we have the target's identity cached —
|
||||
// otherwise we can't verify the LookupResponse proof.
|
||||
if self.has_cached_identity(&msg.dest_addr) {
|
||||
self.maybe_initiate_lookup(&msg.dest_addr).await;
|
||||
} else {
|
||||
debug!(dest = %msg.dest_addr,
|
||||
"Skipping discovery after CoordsRequired: no cached identity for target");
|
||||
}
|
||||
|
||||
// Reset coords warmup counter so the next N packets also include
|
||||
// COORDS_PRESENT, re-warming transit caches along the path.
|
||||
@@ -783,8 +790,16 @@ impl Node {
|
||||
// Invalidate stale cached coordinates
|
||||
self.coord_cache.remove(&msg.dest_addr);
|
||||
|
||||
// Trigger re-discovery to get fresh coordinates
|
||||
self.maybe_initiate_lookup(&msg.dest_addr).await;
|
||||
// Trigger re-discovery to get fresh coordinates, but only if we have
|
||||
// the target's identity cached — otherwise we can't verify the
|
||||
// LookupResponse proof. This avoids a race when the XK responder
|
||||
// receives PathBroken before msg3 completes (identity unknown).
|
||||
if self.has_cached_identity(&msg.dest_addr) {
|
||||
self.maybe_initiate_lookup(&msg.dest_addr).await;
|
||||
} else {
|
||||
debug!(dest = %msg.dest_addr,
|
||||
"Skipping discovery after PathBroken: no cached identity for target");
|
||||
}
|
||||
|
||||
// Reset coords warmup counter so the next N packets include
|
||||
// COORDS_PRESENT, re-warming transit caches along the new path.
|
||||
|
||||
@@ -963,6 +963,13 @@ impl Node {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a node's identity is in the cache (without LRU touch).
|
||||
pub(crate) fn has_cached_identity(&self, addr: &NodeAddr) -> bool {
|
||||
let mut prefix = [0u8; 15];
|
||||
prefix.copy_from_slice(&addr.as_bytes()[0..15]);
|
||||
self.identity_cache.contains_key(&prefix)
|
||||
}
|
||||
|
||||
/// Number of identity cache entries.
|
||||
pub fn identity_cache_len(&self) -> usize {
|
||||
self.identity_cache.len()
|
||||
|
||||
@@ -262,7 +262,7 @@ async fn test_response_proof_verification_failure() {
|
||||
#[tokio::test]
|
||||
async fn test_response_identity_cache_miss() {
|
||||
// Verify that a response is discarded when the origin lacks the
|
||||
// target's pubkey in identity_cache (should never happen in practice).
|
||||
// target's pubkey in identity_cache (e.g., XK responder before msg3).
|
||||
let mut node = make_node();
|
||||
let from = make_node_addr(0xAA);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user