open
https://gitlab.synchro.net/main/sbbs/-/issues/1225
## Symptom
A terminal-server node session over SSH was torn down mid-door with no user action, no idle timeout, and no crash of the external program. The client reconnected 11 seconds later on a fresh source port.
## Log
Node 11, SyncTERM client (CTerm 1.332) over SSH, running a graphics-heavy
door that streams sixel frames. Door name redacted as `<door>`.
```
22:33:43.29 <Digital Man> Executing external: <door> /sbbs/node11/DOOR32.SYS 22:33:45.52 <Digital Man> <door>: frames as sixel
22:33:46.18 SSH WARNING 'Invalid packet <Unknown type> (236), expected
SSH_MSG_CHANNEL_DATA (94)' (-32) popping data from input_thread 22:33:46.18 input thread terminated (received 123278 bytes in 13151 blocks) 22:33:46.18 output thread terminated (sent 179433865 bytes in 125287 blocks,
1432 average, 0 short)
22:33:46.18 passthru thread terminated
22:33:52.80 <Digital Man> external Timeout waiting for output buffer to empty 22:33:52.94 <Digital Man> logout initiated
```
Everything from 22:33:46.18 onward is fallout: the door kept rendering into a dead socket for 6.6 seconds, hit the output-buffer drain timeout, and then exited through postxtrn normally. No core file was written for it.
## What happens
cryptlib decrypted an inbound SSH packet header carrying message type 236
where channel data was expected, and returned CRYPT_ERROR_BADDATA (-32).
In `src/sbbs3/main.cpp`, `input_thread()` treats every `crypt_pop_channel_data()`
error other than CRYPT_ERROR_COMPLETE and CRYPT_ERROR_TIMEOUT as fatal: it
logs via GCES and breaks out of the loop, which ends the input thread and
takes the node down with it. So a single bad packet is unconditionally fatal.
That is defensible for SSH -- once the transport is out of frame there is nothing to resync to -- but it is worth confirming that is the intent rather than an accident of the error-handling structure, because the same path also catches errors that are not framing failures.
## Why the packet type is suspicious
In `3rdp/src/cl/session/ssh2_rd.c`, `readPacketSSH2()` peeks the pad length
and packet type out of the decrypted header and calls `checkPacketValid()` *before* the packet MAC is verified -- the "we've passed the crypto stage" comment sits after that check. So a bogus type here does not mean the peer authentically sent message 236; it is what a desynced or corrupted stream
looks like at the first decrypted block.
236 is in SSH's private-use message range (192-255). Nothing in the protocol sends it, and cryptlib does not implement SSH rekeying, so a mishandled
key re-exchange is not an explanation either.
The preceding padding-length and packet-length checks both passed, which constrains the corruption only weakly -- most random bytes pass those.
## Frequency
Exactly one occurrence of this message across three rotated log files
(roughly 15 GB, Aug 2 through Aug 10). The same client had pushed 517 MB through the same code path in the preceding session without incident. This
is not a recurring failure, and no reproduction is known.
## Notes on what it is not
- Not a crash of the external program: no core, normal startup logging, clean
exit through postxtrn afterwards.
- Not an inactivity timeout.
- Not a door writing to or reading from an inherited descriptor it should not
touch: the door in question obtains its socket through the same shared
DOOR32.SYS helper every other door here uses, and no other door has ever
produced this.
- TCP would have delivered the bytes in order, so the corruption is inside one
of the two cryptlib endpoints rather than on the wire.
## Suggested next steps
Filed to have a record rather than because a fix is obvious. To make progress if it recurs:
- raise SSHErrorLevel on the terminal server for more cryptlib detail
- capture the TCP stream for the affected client, which at least settles
whether the byte stream itself was intact
- consider logging the surrounding decrypted header bytes on BADDATA, so a
recurrence shows whether the stream is offset by a fixed amount (a framing
bug) or is garbage (a keystream or memory problem)
Possibly related, both closed: #302 (cryptlib internal consistency check failures affecting SSH/TLS).
-- *Authored by Claude (Claude Code), on behalf of @rswindell*
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)