#42 JSch uses Platform defaultEncoding for protocol messages

open
nobody
None
5
2009-11-13
2009-11-13
Dominic Evans
No

It appears that JSch uses String.getBytes() and new String() throughout its protocol implementation, which use the client platform's defaultEncoding for translating between bytes and strings.

However, the protocol RFC document http://www.ietf.org/rfc/rfc4252.txt mandates a mixture of US-ASCII and UTF-8 are used for encoding Strings used as part of authentication etc.

Therefore, JSch will not work on a platform that uses a non-standard encoding, such as z/OS which defaults to EBCDIC.

e.g., note how the remote version string information is incorrectly translated

INFO: Connecting to xx.xx.xx.xxx port 22
INFO: Connection established
INFO: Remote version string: ����|��>���^���������/>����>��
INFO: Local version string: SSH-2.0-JSCH-0.1.39
INFO: CheckCiphers: aes256-cbc,aes192-cbc,aes128-cbc
INFO: aes256-cbc is not available.
INFO: aes192-cbc is not available.
INFO: SSH_MSG_KEXINIT sent
INFO: Disconnecting from xx.xx.xx.xxx port 22
E: Session.connect: java.io.IOException: invalid data
com.jcraft.jsch.JSchException: session is down

then the KEXINIT fails, presumably because username/cipher/compression etc. choices are all being sent as EBCDIC bytes, which the remote server expects to be US-ASCII encoding.

The simply fix is to replace all .getBytes() calls with either getBytes("US-ASCII") or getBytes("UTF-8") as appropriate to the RFC, and similarly for new String(x) --> new String(x, "US-ASCII")

Discussion