Harden native auth and SDK datagram handling

This commit is contained in:
DuProcess
2026-07-05 18:00:31 -04:00
parent 92c94176bd
commit f205e0c128
3 changed files with 236 additions and 14 deletions
+74 -4
View File
@@ -737,11 +737,17 @@ impl DoshTransport {
if packet.header.conn_id != self.conn_id {
continue;
}
let plain = match protocol::decrypt_body(
&packet,
&self.session_key,
self.role.recv_direction(),
) {
Ok(plain) => plain,
Err(_) => continue,
};
if !self.replay.accept(packet.header.seq) {
continue;
}
let plain =
protocol::decrypt_body(&packet, &self.session_key, self.role.recv_direction())?;
self.peer_addr = peer;
self.ack_seq = self.ack_seq.max(packet.header.seq);
self.last_contact = Instant::now();
@@ -756,14 +762,21 @@ impl DoshTransport {
datagram: &[u8],
peer: SocketAddr,
) -> Result<SessionEvent> {
let packet = protocol::decode(datagram)?;
let packet = match protocol::decode(datagram) {
Ok(packet) => packet,
Err(_) => return Ok(SessionEvent::Ignored),
};
if packet.header.conn_id != self.conn_id {
return Ok(SessionEvent::Ignored);
}
let plain =
match protocol::decrypt_body(&packet, &self.session_key, self.role.recv_direction()) {
Ok(plain) => plain,
Err(_) => return Ok(SessionEvent::Ignored),
};
if !self.replay.accept(packet.header.seq) {
return Ok(SessionEvent::Ignored);
}
let plain = protocol::decrypt_body(&packet, &self.session_key, self.role.recv_direction())?;
self.peer_addr = peer;
self.ack_seq = self.ack_seq.max(packet.header.seq);
self.last_contact = Instant::now();
@@ -1130,4 +1143,61 @@ mod tests {
assert!(matches!(server.recv().await.unwrap(), SessionEvent::Ping));
assert_eq!(server.peer_addr(), roaming_addr);
}
#[tokio::test]
async fn unauthenticated_datagram_does_not_poison_replay_window() {
let socket = UdpSocket::bind("127.0.0.1:0").await.unwrap();
let peer: SocketAddr = "127.0.0.1:9".parse().unwrap();
let key = [11u8; 32];
let wrong_key = [12u8; 32];
let conn_id = [4u8; 16];
let mut transport = DoshTransport::new_owned(
socket,
SessionTransportConfig {
role: SessionRole::Client,
conn_id,
session_key: key,
peer_addr: peer,
initial_send_seq: 1,
initial_ack: 0,
stream: TransportConfig::default(),
},
);
let bad = protocol::encode_encrypted(
PacketKind::Pong,
conn_id,
9,
0,
&wrong_key,
SERVER_TO_CLIENT,
b"",
)
.unwrap();
let valid = protocol::encode_encrypted(
PacketKind::Pong,
conn_id,
9,
0,
&key,
SERVER_TO_CLIENT,
b"",
)
.unwrap();
assert!(matches!(
transport
.handle_datagram(b"not a dosh packet", peer)
.await
.unwrap(),
SessionEvent::Ignored
));
assert!(matches!(
transport.handle_datagram(&bad, peer).await.unwrap(),
SessionEvent::Ignored
));
assert!(matches!(
transport.handle_datagram(&valid, peer).await.unwrap(),
SessionEvent::Pong
));
}
}