otp icon indicating copy to clipboard operation
otp copied to clipboard

Character 0x03 causes an IO read interrupt on an SSH channel

Open david-naughton opened this issue 2 years ago • 1 comments

Describe the bug When transferring data over an SSH channel to an Erang SSH daemon, if the data contains a character 0x03 (end of text character), then the IO read of the data from the SSH channel returns {error, interrupted}. If the character is not present in the string, the string is read and returned correctly.

This was discovered in the context of an SCP file transfer implementation by calling the one-time execution of the SCP command on an Erlang SSH daemon. The file data is read from standard_io, and in the case that the file data contains a 0x03 character, the read was interrupted, and the file transfer failed (the file was a DER format certificate).

To Reproduce 1 - Start an Erlang SSH daemon, following the instructions in the Erlang SSH Getting Started guide: https://www.erlang.org/doc/apps/ssh/using_ssh.html. Do not disable one-time execution, or assign a function to handle it (so that it defaults to using the erlang shell)

2 - Set up SSH keys to allow ssh connection without password.

3 - From a file, read some text with the character 0x03 in it.

4 - Pipe this text into a one-time execution ssh command to read a user input using the standard IO.

The code for starting the SSH daemon:

ssh:start().
ssh:daemon({172, 17, 0, 2}, 2022, [{system_dir, '/workdir/tmp/ssh_daemon'}, {user_dir, '/workdir/tmp/otptest_user/.ssh'}]).

And for running the single execution in a console, with and with the 0x03 character:

:~$ echo $text1
hello.
:~$ echo $text1 | ssh 192.168.56.102 -p 2022 'io:read("write something: ").'
write something: {ok,hello}:~$ 
:~$ echo $text2
hello.
:~$ 
:~$ echo $text2 | ssh 192.168.56.102 -p 2022 'io:read("write something: ").'
write something: {error,interrupted}:~$ 

Expected behavior I believe that the character 0x03 should not interrupt an IO read of the data from the SSH channel, as I don't know how a file with this character can be transferred through an SSH connection.

Affected versions OTP Version: Erlang/OTP 24

Additional context Operating system: Ubuntu 18.04.3 LTS

The SSH debug on the server side for these two commands shows that the character is delivered correctly on the server side: This is from the information printed to the erlang shell after executing the functions ssh_dbg:on() and ssh_dbg.start()

First example (text1=hello.):

08:49:46.086376 <0.323.0> CLI conn <0.213.0> chan 0, req data
channel_id: 0
type: "0 (normal data)"
data: hello.

hex: 
Addr | Hexdump                                          | ASCII
-----+--------------------------------------------------+-----------------
0000 | 68 65 6c 6c 6f 2e 0a                             | hello..

         
08:49:46.086380 <0.323.0> Server Channel info returned:
{noreply,"#state{}"}

Second example (text2=hello.):

08:50:02.345175 <0.330.0> CLI conn <0.213.0> chan 0, req data
channel_id: 0
type: "0 (normal data)"
data: hel^Clo.

hex: 
Addr | Hexdump                                          | ASCII
-----+--------------------------------------------------+-----------------
0000 | 68 65 6c 03 6c 6f 2e 0a                          | hel.lo..

         
08:50:02.345182 <0.330.0> Server Channel info returned:
{noreply,"#state{}"}

The assumption is that this is related to the pseudoterminal that is used for SSH connections, as the character 0x03 (^C) is a breaking interrupt in a terminal, but I haven't been able to prove this.

david-naughton avatar Jul 04 '22 16:07 david-naughton

Hi, I don't quite follow. What do you mean with "calling the one-time execution of the SCP command on an Erlang SSH daemon"? Did you call "scp -P PORT ... HOST ..." where HOST:PORT is served by an Erlang SSH daemon?

The Erlang SSH daemon does not support the scp command of OpenSSH.

HansN avatar Aug 04 '22 13:08 HansN

To transfer a file an sftp operation is to prefer. In that case there is no problem with the ^C character since a file is read at the server and sent to the client without any interpretations of the contents.

When using the exec functionality - like in the examples above - the server is instructed to execute a command in the server's shell as similar as possible to opening a shell directly to the server without any ssh involved. Since the input to the shell contains a ^C (character 0x03), the shell is instructed to stop the execution and close down everything.

HansN avatar Aug 17 '22 15:08 HansN

@HansN , are there any plans to support OpenSSH SCP? While I know SFTP is the preferred protocol, SCP is still used.

alanj853 avatar Oct 18 '23 13:10 alanj853