Harden native auth and SDK datagram handling
This commit is contained in:
+74
-4
@@ -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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user