* protocols/kad: Do not attempt to store expired record in record store
`Kademlia::record_received` calculates the expiration time of a record
before inserting it into the record store. Instead of inserting the
record into the record store in any case, with this patch the record is
only inserted if it is not expired. If the record is expired a
`KademliaHandlerIn::Reset` for the given (sub) stream is triggered.
This would serve as a tiny defense mechanism against an attacker trying
to fill a node's record store with expired records before the record
store's clean up procedure removes the records.
* protocols/kad: Send regular ack when record discarded due to expiration
With this commit the remote receives a
[`KademliaHandlerIn::PutRecordRes`] even in the case where the record is
discarded due to being expired. Given that the remote sent the local
node a [`KademliaHandlerEvent::PutRecord`] request, the remote perceives
the local node as one node among the k closest nodes to the target.
Returning a [`KademliaHandlerIn::Reset`] instead of an
[`KademliaHandlerIn::PutRecordRes`] to have the remote try another node
would only result in the remote node to contact an even more distant
node. In addition returning [`KademliaHandlerIn::PutRecordRes`] does not
reveal any internal information to a possibly malicious remote node.
* protocols/kad/src/behaviour: Use `now` and reword expiration comment
Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
* protocols/kad: Add test to reproduce right shift overflow panic
* protocols/kad: Fix right shift overflow panic in record_received
Within `Behaviour::record_received` the exponentially decreasing
expiration based on the distance to the target for a record is
calculated as following:
1. Calculate the amount of nodes between us and the record key beyond
the k replication constant as `n`.
2. Shift the configured record time-to-live `n` times to the right to
calculate an exponentially decreasing expiration.
The configured record time-to-live is a u64. If `n` is larger or equal
to 64 the right shift will lead to an overflow which panics in debug
mode.
This patch uses a checked right shift instead, defaulting to 0 (`now +
0`) for the expiration on overflow.
* protocols/kad: Put attribute below comment
* protocols/kad: Extract shifting logic and rework test
Extract right shift into isolated function and replace complex
regression test with small isolated one.
* protocols/kad/src/behaviour: Refactor exp_decr_expiration
Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>