@@ -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