diff options
author | Jake McGinty <me@jake.su> | 2018-02-12 16:52:32 +0000 |
---|---|---|
committer | Jake McGinty <me@jake.su> | 2018-02-12 16:54:59 +0000 |
commit | cffba769212e40892a54222d8bebedc550582af3 (patch) | |
tree | 7be4da438df63a9557318ba86dfccef1523a6a6c /src | |
parent | let Peer process its incoming handshake (diff) | |
download | wireguard-rs-cffba769212e40892a54222d8bebedc550582af3.tar.xz wireguard-rs-cffba769212e40892a54222d8bebedc550582af3.zip |
validate incoming handshake timestamps
Diffstat (limited to 'src')
-rw-r--r-- | src/interface/peer_server.rs | 5 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/protocol/peer.rs | 16 | ||||
-rw-r--r-- | src/tai64n.rs | 36 |
4 files changed, 50 insertions, 8 deletions
diff --git a/src/interface/peer_server.rs b/src/interface/peer_server.rs index 5fe6bc3..2ad363a 100644 --- a/src/interface/peer_server.rs +++ b/src/interface/peer_server.rs @@ -129,8 +129,9 @@ impl PeerServer { &state.interface_info.private_key.ok_or_else(|| format_err!("no private key!"))?)?; let mut timestamp = [0u8; 12]; - let _ = noise.read_message(&packet[8..116], &mut timestamp) + let len = noise.read_message(&packet[8..116], &mut timestamp) .map_err(SyncFailure::new)?; + ensure!(len == 12, "incorrect handshake payload length"); let mut peer_ref = { let their_pubkey = noise.get_remote_static().expect("must have remote static key"); @@ -141,7 +142,7 @@ impl PeerServer { }; let mut peer = peer_ref.borrow_mut(); - let (response, next_index, dead_index) = peer.process_incoming_handshake(addr, their_index, ×tamp, noise)?; + let (response, next_index, dead_index) = peer.process_incoming_handshake(addr, their_index, timestamp.into(), noise)?; let _ = state.index_map.insert(next_index, peer_ref.clone()); if let Some(index) = dead_index { let _ = state.index_map.remove(&index); diff --git a/src/main.rs b/src/main.rs index 36eb5d7..ddade34 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,7 @@ mod protocol; mod types; mod anti_replay; mod router; +mod tai64n; mod ip_packet; use std::path::PathBuf; diff --git a/src/protocol/peer.rs b/src/protocol/peer.rs index 6c2fe9f..d8e0433 100644 --- a/src/protocol/peer.rs +++ b/src/protocol/peer.rs @@ -15,6 +15,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use std::thread::JoinHandle; use base64; use hex; +use tai64n::TAI64N; use time; use rand::{self, Rng}; use snow; @@ -31,6 +32,7 @@ pub struct Peer { pub tx_bytes: u64, pub rx_bytes: u64, pub last_handshake: Option<SystemTime>, + pub last_handshake_tai64n: Option<TAI64N>, } impl PartialEq for Peer { @@ -205,16 +207,13 @@ impl Peer { } pub fn get_handshake_packet(&mut self) -> Result<Vec<u8>, Error> { - let now = time::get_time(); - let mut tai64n = [0; 12]; - BigEndian::write_i64(&mut tai64n[0..], 4611686018427387914 + now.sec); - BigEndian::write_i32(&mut tai64n[8..], now.nsec); + let tai64n = TAI64N::now(); let mut initiation_packet = vec![0; 148]; initiation_packet[0] = 1; /* Type: Initiation */ let next = self.sessions.next.as_mut().ok_or_else(|| format_err!("missing next session"))?; LittleEndian::write_u32(&mut initiation_packet[4..], next.our_index); - next.noise.write_message(&tai64n, &mut initiation_packet[8..]).map_err(SyncFailure::new)?; + next.noise.write_message(&*tai64n, &mut initiation_packet[8..]).map_err(SyncFailure::new)?; let mut mac_key_input = [0; 40]; memcpy(&mut mac_key_input, b"mac1----"); @@ -230,9 +229,13 @@ impl Peer { /// and generates a response. /// /// Returns: the response packet (type 0x02), and an optional dead session index that was removed. - pub fn process_incoming_handshake(&mut self, addr: SocketAddr, their_index: u32, timestamp: &[u8], mut noise: snow::Session) + pub fn process_incoming_handshake(&mut self, addr: SocketAddr, their_index: u32, timestamp: TAI64N, mut noise: snow::Session) -> Result<(Vec<u8>, u32, Option<u32>), Error> { + if let Some(ref last_tai64n) = self.last_handshake_tai64n { + ensure!(×tamp > last_tai64n, "handshake timestamp earlier than last handshake's timestamp"); + } + // TODO: verify timestamp // TODO: hacked up API until it's officially supported in snow. match noise { @@ -250,6 +253,7 @@ impl Peer { let dead_index = self.ratchet_session()?.map(|session| session.our_index); self.info.endpoint = Some(addr); // update peer endpoint after successful authentication + self.last_handshake_tai64n = Some(timestamp); Ok((response_packet, next_index, dead_index)) } diff --git a/src/tai64n.rs b/src/tai64n.rs new file mode 100644 index 0000000..818d57d --- /dev/null +++ b/src/tai64n.rs @@ -0,0 +1,36 @@ +use byteorder::{ByteOrder, BigEndian}; +use std::time::{SystemTime, UNIX_EPOCH}; +use std::ops::Deref; +use time; + +const TAI64N_BASE: i64 = 4611686018427387914; + +#[derive(PartialEq, PartialOrd)] +pub struct TAI64N { + tai64n: [u8; 12] +} + +impl TAI64N { + pub fn now() -> TAI64N { + let mut tai64n = [0u8; 12]; + let now = time::get_time(); + BigEndian::write_i64(&mut tai64n[0..], TAI64N_BASE + now.sec); + BigEndian::write_i32(&mut tai64n[8..], now.nsec); + + TAI64N { tai64n } + } +} + +impl Deref for TAI64N { + type Target = [u8; 12]; + + fn deref(&self) -> &[u8; 12] { + &self.tai64n + } +} + +impl From<[u8; 12]> for TAI64N { + fn from(tai64n: [u8; 12]) -> Self { + TAI64N { tai64n } + } +} |