SynchronizedKexExchange thinks that it receives and sends packet synchronously. But it is not 100% true. As KeyExchanger does its synchronous job, SSH2PacketBuilder is not sleeping and keeps receiving incoming TCP packets in a separate thread. Also SSH2PacketBuilder decides to decrypt or not to decrypt incoming packets. Its decision about decrypting packets based on the _cipher member, which is set in ProcessNEWKEYS (ProcessNEWKEYS -> RefreshKeys -> SetCipher).
So when SSH_MSG_NEWKEY is received, KeyExchanger starts to handle it, it takes time. Before KeyExchanger is done with the SSH_MSG_NEWKEY message another message comes. The second message is already encrypted (all the messages after SSH_MSG_NEWKEY must be encrypted). For example the second message can be SSH_MSG_DISCONNECT or SSH_MSG_IGNORE. SSH2PacketBuilder tries to make a packet as if the second packet is not encrypted (remember KeyExchanger in another thread is still processing SSH_MSG_NEWKEY, so _cypher is not set yet) and of course it fails with the message: "packet size {0} is invalid" in ReadPacketFromPlainStream. So disconnect happens.
Thank you for your detailed report.
I added synchronization to wait the new _cipher.
https://github.com/poderosaproject/poderosa/commit/0f3d1f038c2734f5eb500abef1727fd115a7384e
https://github.com/poderosaproject/poderosa/commit/eded260ba4827a25a79cafe9227a3a2b4ac63601
Last edit: Iwasa Kazmi 2014-11-09