[ 
https://issues.apache.org/jira/browse/SSHD-1197?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Thomas Wolf reassigned SSHD-1197:
---------------------------------

    Assignee: Thomas Wolf

> Race condition in KEX
> ---------------------
>
>                 Key: SSHD-1197
>                 URL: https://issues.apache.org/jira/browse/SSHD-1197
>             Project: MINA SSHD
>          Issue Type: Bug
>    Affects Versions: 2.7.0
>            Reporter: Thomas Wolf
>            Assignee: Thomas Wolf
>            Priority: Critical
>
> There is a race condition in the KEX implementation. A simple reproducer can 
> be obtained by modifying {{SftpTransferTest}} by inserting the following in 
> method {{doTestTransferIntegrity()}} just before the main {{try-finally}}:
> {code:java}
> CoreModuleProperties.REKEY_BLOCKS_LIMIT.set(client, Long.valueOf(65536));
> CoreModuleProperties.REKEY_BLOCKS_LIMIT.set(sshd, Long.valueOf(65536));
> try (ClientSession session = createAuthenticatedClientSession();
>     ...
> {code}
> This forces rekeying every 512kB; the test roundtrips a 10Mb file twice, 
> which gives ample opportunity to run into this race condition. Typically the 
> test fails very quickly and hangs.
> The hang is always caused by an async write not being cancelled when the 
> session gets disconnected. The session disconnects during KEX because KEX 
> state is corrupted because of the race condition.
> Most of the time the race condition causes a signature verification failure 
> during KEX, but I also got 
> "Disconnecting(ClientSessionImpl[testTransferIntegrity@/127.0.0.1:62186]): 
> SSH2_DISCONNECT_KEY_EXCHANGE_FAILED - Unable to negotiate key exchange for 
> mac algorithms (server to client) (client: null / server: 
> [email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1)",
>  which is easier to understand than the signature verification failure.
> The precise sequence of events in that case is
> {code:java}
>     Server                                                    Client
> 1.  thread-nio-4 requestNewKeyExchange DONE->INIT
> 2.  thread-nio-4 sendKexInit
> 3.                                                            main            
> requestNewKeyExchange DONE->INIT
> 4.                                                            thread-nio-3    
> handleKexInit
> 5.                                                            thread-nio-3    
>   doKexNegotiation INIT->RUN
> 6.                                                            thread-nio-3    
>     negotiate -> Exception: client proposal null
> 7.                                                            main            
> sendKexInit
> 8.  thread-nio-2 receive KEX_INIT      INIT->RUN
> 9.                                                            thread-nio-3    
> Exception caught
> 10.                                                           thread-nio-3    
> Disconnecting
> 11. thread-nio-5 process SSH_MSG_DISCONNECT (KexState RUN)
> {code}
> There is window between steps 3 and 7 in 
> {{AbstractSession.requestNewKeyExchange()}} during which the KEX state is 
> INIT, but the client proposal isn't initialized yet; it's initialized only 
> after {{sendKexInit()}} has been done. However, the client already got the 
> server's KEX_INIT message, and in {{doKexNegotiation()}} proceeds as if the 
> client proposal was already set up.
> So, theres' two problems here:
>  # KEX fails due to a race condition.
>  # The client hangs after disconnecting because an async write future is not 
> terminated.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to