While integrating sshlib 0.3.1 as an SSH engine in Haven (per the migration discussed in GlassHaven/Haven#58), a capability spike against Apache MINA sshd 2.19.0 found client-initiated rekeying broken in both trigger modes:
1. Byte-limit rekey during in-flight SFTP writes kills the channel
val client = SshClient(SshClientConfig {
host = "127.0.0.1"; port = server.port
hostKeyVerifier = trustAll
rekeyBytesLimit = 256L * 1024
})
client.connect() // Success
client.authenticatePassword(...) // Success
// SFTP write loop, 32 KiB chunks, 2 MiB total:
sftp.write(handle, offset, chunk) // fails right past the limit:
// SftpResult.IoError(ChannelClosedException("SSH channel closed before complete SFTP packet"))
// at offset ~294912 (= just after 256 KiB)
2. Interval rekey wedges an idle session — a hang, not an error
val client = SshClient(SshClientConfig {
...
rekeyIntervalMs = 1_000L
})
client.connect(); client.authenticatePassword(...) // Success
delay(2_500) // ≥2 interval rekeys while idle
sftp.opendir("/") // suspends forever (no error, no timeout)
With the defaults (1 GiB / 1 h) this means any single transfer larger than 1 GiB dies mid-flight, and any session idle for more than an hour hangs on its next operation.
Both repros are plain JUnit tests against an in-process SshServer.setUpDefaultServer() (password auth, SftpSubsystemFactory, VirtualFileSystemFactory); the identical 2 MiB transfer passes with rekey thresholds left at defaults (no rekey triggered), so the rekey is the isolated variable. I haven't probed server-initiated rekey separately. Happy to contribute the fix if you can point me at where you'd want the in-flight-packet coordination to live — my guess is the outgoing packet queue isn't paused/drained around SSH_MSG_NEWKEYS, and the post-rekey wedge smells like a read loop stuck on stale cipher state.
The full probe suite (these two plus 16 other capability probes) lives in Haven at core/ssh/src/test/kotlin/sh/haven/core/ssh/sshlib/SshlibCapabilitySpikeTest.kt — the two rekey probes are written to fail when this is fixed, so we notice and drop our mitigation (we currently set both thresholds to Long.MAX_VALUE / 2).
Tested: sshlib 0.3.1 from Maven Central, JVM 21, MINA sshd 2.19.0, BC 1.84.
While integrating sshlib 0.3.1 as an SSH engine in Haven (per the migration discussed in GlassHaven/Haven#58), a capability spike against Apache MINA sshd 2.19.0 found client-initiated rekeying broken in both trigger modes:
1. Byte-limit rekey during in-flight SFTP writes kills the channel
2. Interval rekey wedges an idle session — a hang, not an error
With the defaults (1 GiB / 1 h) this means any single transfer larger than 1 GiB dies mid-flight, and any session idle for more than an hour hangs on its next operation.
Both repros are plain JUnit tests against an in-process
SshServer.setUpDefaultServer()(password auth,SftpSubsystemFactory,VirtualFileSystemFactory); the identical 2 MiB transfer passes with rekey thresholds left at defaults (no rekey triggered), so the rekey is the isolated variable. I haven't probed server-initiated rekey separately. Happy to contribute the fix if you can point me at where you'd want the in-flight-packet coordination to live — my guess is the outgoing packet queue isn't paused/drained around SSH_MSG_NEWKEYS, and the post-rekey wedge smells like a read loop stuck on stale cipher state.The full probe suite (these two plus 16 other capability probes) lives in Haven at
core/ssh/src/test/kotlin/sh/haven/core/ssh/sshlib/SshlibCapabilitySpikeTest.kt— the two rekey probes are written to fail when this is fixed, so we notice and drop our mitigation (we currently set both thresholds toLong.MAX_VALUE / 2).Tested: sshlib 0.3.1 from Maven Central, JVM 21, MINA sshd 2.19.0, BC 1.84.