kx_advertised: every message after the exchange, not the first alone

The contract named the server's first message after the key exchange. That
frame sits at a position an attacker needs no key to find, so one who had
lowered the advertisement in the clear only had to drop it to be rid of
the check for the whole session. With every message carrying the echo,
being rid of it means dropping them all, which is a plain DoS.

The client already kept the check armed until an echo arrived; this is the
wording the server side is written to.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
This commit is contained in:
rustdesk
2026-09-21 18:33:33 +08:00
co-authored by Claude Fable 5.1
parent 445486ccaa
commit 1266b56150
2 changed files with 5 additions and 3 deletions
+4 -2
View File
@@ -297,9 +297,11 @@ message RendezvousMessage {
HttpProxyResponse http_proxy_response = 28;
IceCandidate ice_candidate = 29;
}
// From the server, on its first message after a key exchange: the version it advertised,
// From the server, on every message after a key exchange: the version it advertised,
// repeated inside the encrypted channel where nothing in transit can alter it. A client that
// was shown a different value in the clear knows the handshake was altered and refuses the
// stream. Absent from servers that predate versions.
// stream. Every message and not the first alone, so that dropping one frame at a position
// that needs no key to find does not rid an attacker of the check; dropping them all is a
// plain DoS. Absent from servers that predate versions.
uint32 kx_advertised = 30;
}