Skip to content

Commit ed8401b

Browse files
committed
fix(net_crypto): handle a handshake for an existent connection from a different UDP address
1 parent 0c28fa0 commit ed8401b

File tree

1 file changed

+287
-5
lines changed

1 file changed

+287
-5
lines changed

src/toxcore/net_crypto/mod.rs

Lines changed: 287 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,46 @@ impl NetCrypto {
505505
return Either::A(future::err(HandlePacketErrorKind::UnexpectedCryptoHandshake.into()));
506506
}
507507

508+
let mut connections = self.connections.write();
509+
510+
let kill_future = if let Some(connection) = connections.get(&cookie.real_pk) {
511+
let mut connection = connection.write();
512+
if connection.peer_dht_pk != cookie.dht_pk {
513+
// We received a handshake packet for an existent connection
514+
// from a new address and this packet contains a different DHT
515+
// PublicKey. In this case we kill the old connection and create
516+
// a new one.
517+
518+
self.clear_keys_by_addr(&connection);
519+
let status_future = self.send_connection_status(&connection, false)
520+
.map_err(|e| e.context(HandlePacketErrorKind::SendToConnectionStatus).into());
521+
let kill_future = if connection.is_established() || connection.is_not_confirmed() {
522+
let packet_number = connection.send_array.buffer_end;
523+
Either::A(self.send_data_packet(&mut connection, vec![PACKET_ID_KILL], packet_number)
524+
.map_err(|e| e.context(HandlePacketErrorKind::SendTo).into()))
525+
} else {
526+
Either::B(future::ok(()))
527+
};
528+
Either::A(kill_future.join(status_future).map(|_| ()))
529+
} else {
530+
// We received a handshake packet for an existent connection
531+
// from a new address and this packet contains the same DHT
532+
// PublicKey. In this case we reject this packet if we already
533+
// received a handshake from the old connection and accept it
534+
// otherwise.
535+
536+
if connection.is_established() || connection.is_not_confirmed() {
537+
return Either::A(future::err(HandlePacketErrorKind::UnexpectedCryptoHandshake.into()));
538+
}
539+
540+
self.clear_keys_by_addr(&connection);
541+
542+
Either::B(future::ok(()))
543+
}
544+
} else {
545+
Either::B(future::ok(()))
546+
};
547+
508548
let mut connection = CryptoConnection::new_not_confirmed(
509549
&self.real_sk,
510550
cookie.real_pk,
@@ -519,14 +559,16 @@ impl NetCrypto {
519559
self.keys_by_addr.write().insert((addr.ip(), addr.port()), cookie.real_pk);
520560
}
521561
let connection = Arc::new(RwLock::new(connection));
522-
self.connections.write().insert(cookie.real_pk, connection);
562+
connections.insert(cookie.real_pk, connection);
523563

524-
if let Some(ref dht_pk_tx) = *self.dht_pk_tx.read() {
525-
Either::B(send_to(dht_pk_tx, (cookie.real_pk, cookie.dht_pk))
564+
let dht_pk_future = if let Some(ref dht_pk_tx) = *self.dht_pk_tx.read() {
565+
Either::A(send_to(dht_pk_tx, (cookie.real_pk, cookie.dht_pk))
526566
.map_err(|e| e.context(HandlePacketErrorKind::SendToDhtpk).into()))
527567
} else {
528-
Either::A(future::ok(()))
529-
}
568+
Either::B(future::ok(()))
569+
};
570+
571+
Either::B(kill_future.join(dht_pk_future).map(|_| ()))
530572
}
531573

532574
/// Handle `CryptoHandshake` packet received from UDP socket
@@ -1951,6 +1993,246 @@ mod tests {
19511993
assert_eq!(payload.cookie_hash, cookie.hash());
19521994
}
19531995

1996+
#[test]
1997+
fn handle_udp_crypto_handshake_new_address_new_dht_pk() {
1998+
let (udp_tx, udp_rx) = mpsc::channel(1);
1999+
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2000+
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2001+
let (dht_pk, dht_sk) = gen_keypair();
2002+
let (real_pk, real_sk) = gen_keypair();
2003+
let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2004+
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
2005+
udp_tx,
2006+
lossless_tx,
2007+
lossy_tx,
2008+
dht_pk,
2009+
dht_sk: dht_sk.clone(),
2010+
real_pk,
2011+
real_sk,
2012+
precomputed_keys,
2013+
});
2014+
2015+
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
2016+
let (peer_real_pk, peer_real_sk) = gen_keypair();
2017+
2018+
net_crypto.add_friend(peer_real_pk);
2019+
2020+
let dht_precomputed_key = precompute(&peer_dht_pk, &dht_sk);
2021+
let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2022+
2023+
let received_nonce = gen_nonce();
2024+
let sent_nonce = gen_nonce();
2025+
let (peer_session_pk, _peer_session_sk) = gen_keypair();
2026+
let (_session_pk, session_sk) = gen_keypair();
2027+
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
2028+
connection.status = ConnectionStatus::Established {
2029+
sent_nonce,
2030+
received_nonce,
2031+
session_precomputed_key: session_precomputed_key.clone(),
2032+
};
2033+
2034+
let addr = "127.0.0.1:12345".parse().unwrap();
2035+
connection.set_udp_addr(addr);
2036+
2037+
net_crypto.connections.write().insert(peer_real_pk, Arc::new(RwLock::new(connection)));
2038+
net_crypto.keys_by_addr.write().insert((addr.ip(), addr.port()), peer_real_pk);
2039+
2040+
let (new_peer_dht_pk, _new_peer_dht_sk) = gen_keypair();
2041+
let real_precomputed_key = precompute(&real_pk, &peer_real_sk);
2042+
let base_nonce = gen_nonce();
2043+
let session_pk = gen_keypair().0;
2044+
let our_cookie = Cookie::new(peer_real_pk, new_peer_dht_pk);
2045+
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, &our_cookie);
2046+
let cookie = EncryptedCookie {
2047+
nonce: secretbox::gen_nonce(),
2048+
payload: vec![43; 88]
2049+
};
2050+
let crypto_handshake_payload = CryptoHandshakePayload {
2051+
base_nonce,
2052+
session_pk,
2053+
cookie_hash: our_encrypted_cookie.hash(),
2054+
cookie: cookie.clone()
2055+
};
2056+
let crypto_handshake = CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2057+
2058+
let new_addr = "127.0.0.2:12345".parse().unwrap();
2059+
net_crypto.handle_udp_crypto_handshake(&crypto_handshake, new_addr).wait().unwrap();
2060+
2061+
// the old connection should be replaced with the new one
2062+
2063+
let connections = net_crypto.connections.read();
2064+
let connection = connections.get(&peer_real_pk).unwrap().read().clone();
2065+
2066+
assert_eq!(connection.peer_dht_pk, new_peer_dht_pk);
2067+
assert_eq!(connection.get_udp_addr_v4(), Some(new_addr));
2068+
2069+
let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
2070+
assert_eq!(received_nonce, base_nonce);
2071+
2072+
let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
2073+
let packet = unpack!(packet.dht_packet(), Packet::CryptoHandshake);
2074+
assert_eq!(packet.cookie, cookie);
2075+
2076+
let payload = packet.get_payload(&real_precomputed_key).unwrap();
2077+
assert_eq!(payload.cookie_hash, cookie.hash());
2078+
2079+
assert!(!net_crypto.keys_by_addr.read().contains_key(&(addr.ip(), addr.port())));
2080+
assert!(net_crypto.keys_by_addr.read().contains_key(&(new_addr.ip(), new_addr.port())));
2081+
2082+
// the old connection should be killed
2083+
2084+
let (received, _udp_rx) = udp_rx.into_future().wait().unwrap();
2085+
let (received, addr_to_send) = received.unwrap();
2086+
2087+
assert_eq!(addr_to_send, addr);
2088+
2089+
let packet = unpack!(received, Packet::CryptoData);
2090+
let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2091+
assert_eq!(payload.buffer_start, 0);
2092+
assert_eq!(payload.packet_number, 0);
2093+
assert_eq!(payload.data, vec![PACKET_ID_KILL]);
2094+
}
2095+
2096+
#[test]
2097+
fn handle_udp_crypto_handshake_new_address_old_dht_pk() {
2098+
let (udp_tx, _udp_rx) = mpsc::channel(1);
2099+
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2100+
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2101+
let (dht_pk, dht_sk) = gen_keypair();
2102+
let (real_pk, real_sk) = gen_keypair();
2103+
let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2104+
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
2105+
udp_tx,
2106+
lossless_tx,
2107+
lossy_tx,
2108+
dht_pk,
2109+
dht_sk: dht_sk.clone(),
2110+
real_pk,
2111+
real_sk,
2112+
precomputed_keys,
2113+
});
2114+
2115+
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
2116+
let (peer_real_pk, peer_real_sk) = gen_keypair();
2117+
2118+
net_crypto.add_friend(peer_real_pk);
2119+
2120+
let dht_precomputed_key = precompute(&peer_dht_pk, &dht_sk);
2121+
let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2122+
2123+
let addr = "127.0.0.1:12345".parse().unwrap();
2124+
connection.set_udp_addr(addr);
2125+
2126+
net_crypto.connections.write().insert(peer_real_pk, Arc::new(RwLock::new(connection)));
2127+
net_crypto.keys_by_addr.write().insert((addr.ip(), addr.port()), peer_real_pk);
2128+
2129+
let real_precomputed_key = precompute(&real_pk, &peer_real_sk);
2130+
let base_nonce = gen_nonce();
2131+
let session_pk = gen_keypair().0;
2132+
let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
2133+
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, &our_cookie);
2134+
let cookie = EncryptedCookie {
2135+
nonce: secretbox::gen_nonce(),
2136+
payload: vec![43; 88]
2137+
};
2138+
let crypto_handshake_payload = CryptoHandshakePayload {
2139+
base_nonce,
2140+
session_pk,
2141+
cookie_hash: our_encrypted_cookie.hash(),
2142+
cookie: cookie.clone()
2143+
};
2144+
let crypto_handshake = CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2145+
2146+
let new_addr = "127.0.0.2:12345".parse().unwrap();
2147+
net_crypto.handle_udp_crypto_handshake(&crypto_handshake, new_addr).wait().unwrap();
2148+
2149+
// the old connection should be updated with a new address
2150+
2151+
let connections = net_crypto.connections.read();
2152+
let connection = connections.get(&peer_real_pk).unwrap().read().clone();
2153+
2154+
assert_eq!(connection.get_udp_addr_v4(), Some(new_addr));
2155+
2156+
let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
2157+
assert_eq!(received_nonce, base_nonce);
2158+
2159+
let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
2160+
let packet = unpack!(packet.dht_packet(), Packet::CryptoHandshake);
2161+
assert_eq!(packet.cookie, cookie);
2162+
2163+
let payload = packet.get_payload(&real_precomputed_key).unwrap();
2164+
assert_eq!(payload.cookie_hash, cookie.hash());
2165+
2166+
assert!(!net_crypto.keys_by_addr.read().contains_key(&(addr.ip(), addr.port())));
2167+
assert!(net_crypto.keys_by_addr.read().contains_key(&(new_addr.ip(), new_addr.port())));
2168+
}
2169+
2170+
#[test]
2171+
fn handle_udp_crypto_handshake_new_address_old_dht_pk_established() {
2172+
let (udp_tx, _udp_rx) = mpsc::channel(1);
2173+
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2174+
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2175+
let (dht_pk, dht_sk) = gen_keypair();
2176+
let (real_pk, real_sk) = gen_keypair();
2177+
let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2178+
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
2179+
udp_tx,
2180+
lossless_tx,
2181+
lossy_tx,
2182+
dht_pk,
2183+
dht_sk: dht_sk.clone(),
2184+
real_pk,
2185+
real_sk,
2186+
precomputed_keys,
2187+
});
2188+
2189+
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
2190+
let (peer_real_pk, peer_real_sk) = gen_keypair();
2191+
2192+
net_crypto.add_friend(peer_real_pk);
2193+
2194+
let dht_precomputed_key = precompute(&peer_dht_pk, &dht_sk);
2195+
let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2196+
2197+
let received_nonce = gen_nonce();
2198+
let sent_nonce = gen_nonce();
2199+
let (peer_session_pk, _peer_session_sk) = gen_keypair();
2200+
let (_session_pk, session_sk) = gen_keypair();
2201+
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
2202+
connection.status = ConnectionStatus::Established {
2203+
sent_nonce,
2204+
received_nonce,
2205+
session_precomputed_key: session_precomputed_key.clone(),
2206+
};
2207+
2208+
let addr = "127.0.0.1:12345".parse().unwrap();
2209+
connection.set_udp_addr(addr);
2210+
2211+
net_crypto.connections.write().insert(peer_real_pk, Arc::new(RwLock::new(connection)));
2212+
net_crypto.keys_by_addr.write().insert((addr.ip(), addr.port()), peer_real_pk);
2213+
2214+
let real_precomputed_key = precompute(&real_pk, &peer_real_sk);
2215+
let base_nonce = gen_nonce();
2216+
let session_pk = gen_keypair().0;
2217+
let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
2218+
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, &our_cookie);
2219+
let cookie = EncryptedCookie {
2220+
nonce: secretbox::gen_nonce(),
2221+
payload: vec![43; 88]
2222+
};
2223+
let crypto_handshake_payload = CryptoHandshakePayload {
2224+
base_nonce,
2225+
session_pk,
2226+
cookie_hash: our_encrypted_cookie.hash(),
2227+
cookie: cookie.clone()
2228+
};
2229+
let crypto_handshake = CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2230+
2231+
let new_addr = "127.0.0.2:12345".parse().unwrap();
2232+
let error = net_crypto.handle_udp_crypto_handshake(&crypto_handshake, new_addr).wait().err().unwrap();
2233+
assert_eq!(*error.kind(), HandlePacketErrorKind::UnexpectedCryptoHandshake);
2234+
}
2235+
19542236
#[test]
19552237
fn handle_udp_crypto_handshake_unexpected() {
19562238
crypto_init().unwrap();

0 commit comments

Comments
 (0)