Hi,

I think I encountered a serious bug in ssh 1.2.27. There seems to be
a race condition where the ssh daemon (sshd) drops data when it has
to send it over a slow line. I sent this bug report to [EMAIL PROTECTED]
and [EMAIL PROTECTED] on 27/03 but have heard nothing from either so
far.

I'll try to clarify what happens:

There are two machines, server and client. Both machines run Solaris.
The client makes an ssh connection to the server to download a file:

server% ls -l /tmp/DATA
-rw-r--r--   1 wout  staff     200000 Mar 23 11:20 DATA

client% ssh server cat /tmp/DATA > /tmp/DATA
client% ls -l /tmp/DATA
-rw-r--r--   1 wout  staff     194560 Mar 24 17:10 /tmp/DATA


This would copy a file '/tmp/DATA' from server to /tmp/DATA on client.
In this particular case file DATA was 200000 bytes. The size has
to be larger then the buffers used inside sshd.

When the command is run, most data is sent over the line as it should
be. However, when the 'cat' process dies, sshd receives a SIGCHLD and
then fails to read the data left in the pipe to the 'cat' program.

To be more precise, sshd only reads the data left in the pipe to 'cat'
if it has space for it in the outgoing buffer (the buffer that is used
to store data going back to the client).

So the following happens (all in serverloop.c):

 1. For a while sshd reads data from the 'cat' command. This data is
    transmitted to the client, where it is put in /tmp/DATA.
 2. cat writes the final data to the pipe to sshd and exits.
 3. sshd receives a SIGCHLD and sets child_terminated and
    child_just_terminated to 1.
 4. sshd falls out of the select() (line 413) it was in
    (it usually receives the signal during the select() call).
    select() returns -1 because it was interrupted by the signal.
 5. sshd empties readset and writeset (lines 415-422 serverloop.c).
 6. The if statements on lines 426 and 446 fail.
 7. sshd does its usual stuff and then calls
    wait_until_can_do_something().
 8. The call to packet_not_very_much_data_to_write() on line 353
    returns false (because the outgoing buffer contains more than
    16384 bytes). This causes fdout and fderr not to be set in the
    readset file descriptor set (lines 355-358).
 9. select() on line 413 returns 0 again (due to slow network
    connection to client). This time the if statement on line
    426 succeeds (child_just_terminated has been set to 0 earlier).
10. Descriptor fdout, fderr and fdin are closed (lines 432-442)
    causing the data available to fdout never being read.

The change I made to fix this is in a patch (diff on original
serverloop.c and modified serverloop.c) you will find attached
to this mail. It changes lines 432-439. Instead of blindly closing
the fdout and fderr descriptors when select() returns 0, it only
closes them if the fdout_eof and fderr_eof flags have been set,
respectively. The bug was that the code in lines 426-443 assumed
that select() always provides information on fdout and fderr, which
is not the case as they had not been set in the readset.

For completeness, I also attach the 'sshd -d' output for a faulty
session (original sshd 1.2.27, data is lost) and output for a session
after having applied my patch.

Please let me know what you make of this.

Wout van Albada
Software Engineer

[EMAIL PROTECTED]
--- serverloop.c.ORIG   Sun Mar 26 13:20:14 2000
+++ serverloop.c        Sun Mar 26 13:25:15 2000
@@ -429,14 +429,14 @@
       if (cleanup_context)
         pty_cleanup_proc(cleanup_context);
       
-      if (fdout != -1)
+      if (fdout != -1 && fdout_eof) {
         close(fdout);
-      fdout = -1;
-      fdout_eof = 1;
-      if (fderr != -1)
+       fdout = -1;
+      }
+      if (fderr != -1 && fderr_eof) {
         close(fderr);
-      fderr = -1;
-      fderr_eof = 1;
+        fderr = -1;
+      }
       if (fdin != -1)
         close(fdin);
       fdin = -1;
Original sshd 1.2.27 session (server):

13:39 [wout@dnp2] /usr/local/sbin 18#./sshd1.orig-2000.03.27 -p 5544 -d
debug: sshd version 1.2.27 [i386-unknown-solaris2.6]
debug: Initializing random number generator; seed file /etc/ssh_random_seed
log: Server listening on port 5544.
log: Generating 768 bit RSA key.
Generating p:  ............++ (distance 180)
Generating q:  ....++ (distance 62)
Computing the keys...
Testing the keys...
Key generation complete.
log: RSA key generation complete.
debug: Server will not fork when running in debugging mode.
log: Connection from 194.42.244.44 port 1022
debug: Client protocol version 1.5; client software version 1.2.27
debug: Sent 768 bit public key and 1024 bit host key.
debug: Encryption type: idea
debug: Received session key; encryption turned on.
debug: Installing crc compensation attack detector.
debug: Attempting authentication for wout.
debug: Trying rhosts with RSA host authentication for wout
debug: RhostsRSA authentication failed for 'wout', remote 'wout', host 
'lisa.365.co.uk'.
log: RSA authentication for wout accepted.
debug: Received request for X11 forwarding with auth spoofing.
debug: bind port 6010: Address already in use
debug: Allocated channel 0 of type 1.
debug: Received authentication agent forwarding request.
debug: Allocated channel 1 of type 10.
debug: Executing command 'cat /tmp/DATA'
debug: Entering interactive session.
debug: Received SIGCHLD.
debug: End of interactive session; stdin 0, stdout (read 194560, sent 194560), stderr 
567 bytes.
debug: Command exited with status 0.
debug: Received exit confirmation.
log: Closing connection to 194.42.244.44


Corresponding ssh output (client):

13:39 [wout@lisa] /tmp 32>ssh -v -p 5544 dnp2.football365.co.uk cat /tmp/DATA > 
/tmp/DATA-orig-sshd
SSH Version 1.2.27 [sparc-sun-solaris2.7], protocol version 1.5.
Standard version.  Does not use RSAREF.
lisa: Reading configuration data /etc/ssh_config
lisa: ssh_connect: getuid 1000 geteuid 0 anon 0
lisa: Connecting to dnp2.football365.co.uk [212.2.1.2] port 5544.
lisa: Allocated local port 1022.
lisa: Connection established.
lisa: Remote protocol version 1.5, remote software version 1.2.27
lisa: Waiting for server public key.
lisa: Received server public key (768 bits) and host key (1024 bits).
lisa: Host 'dnp2.football365.co.uk' is known and matches the host key.
lisa: Initializing random; seed file /home/wout/.ssh/random_seed
lisa: Encryption type: idea
lisa: Sent encrypted session key.
lisa: Installing crc compensation attack detector.
lisa: Received encrypted confirmation.
lisa: Trying rhosts or /etc/hosts.equiv with RSA host authentication.
lisa: Remote: Rhosts/hosts.equiv authentication refused: client user 'wout', server 
user 'wout', client host 'lisa.365.co.uk'.
lisa: Server refused our rhosts authentication or host key.
lisa: Connection to authentication agent opened.
lisa: Trying RSA authentication via agent with '[EMAIL PROTECTED]'
lisa: Received RSA challenge from server.
lisa: Sending response to RSA challenge.
lisa: Remote: RSA authentication accepted.
lisa: RSA authentication accepted by server.
lisa: Failed to get local xauth data.
lisa: Requesting X11 forwarding with authentication spoofing.
lisa: Requesting authentication agent forwarding.
lisa: Sending command: cat /tmp/DATA
lisa: Entering interactive session.
log: executing remote command as user wout
Environment:
  HOME=/homes/home/wout
  USER=wout
  LOGNAME=wout
  PATH=/bin:/usr/bin:/usr/ucb:/usr/bin/X11:/usr/local/bin:/usr/local/bin
  MAIL=/var/mail/wout
  SHELL=/bin/tcsh
  TZ=GB
  SSH_CLIENT=194.42.244.44 1022 5544
  DISPLAY=dnp2.football365.co.uk:11.0
  SSH_AUTH_SOCK=/tmp/ssh-wout/ssh-17388-agent

Running /usr/openwin/bin/xauth add dnp2.football365.co.uk:11.0 MIT-MAGIC-COOKIE-1 
213d7f173bd7c5698930191fa6ad6f21
Running /usr/openwin/bin/xauth add 212.2.1.2:11.0 MIT-MAGIC-COOKIE-1 
213d7f173bd7c5698930191fa6ad6f21
lisa: Transferred: stdin 0, stdout 195127, stderr 0 bytes in 15.4 seconds
lisa: Bytes per second: stdin 0.0, stdout 12677.5, stderr 0.0
lisa: Exit status 0

13:40 [wout@lisa] /tmp 33>ls -l /tmp/DATA-orig-sshd
-rw-r--r--   1 wout     staff     194560 Mar 27 13:40 /tmp/DATA-orig-sshd

13:41 [wout@lisa] /tmp 34>sum /tmp/DATA-orig-sshd                               11522 
380 /tmp/DATA-orig-sshd


And on server:

13:43 [wout@dnp2] /usr/local/sbin 20#ls -l /tmp/DATA 
-rw-r--r--   1 root     other     200000 Mar 23 11:20 /tmp/DATA

13:43 [wout@dnp2] /usr/local/sbin 21#sum /tmp/DATA 
57919 391 /tmp/DATA


Patched sshd 1.2.27 session (server):

13:41 [wout@dnp2] /usr/local/sbin 19#./sshd -p 5544 -d
debug: sshd version 1.2.27 [i386-unknown-solaris2.6]
debug: Initializing random number generator; seed file /etc/ssh_random_seed
log: Server listening on port 5544.
log: Generating 768 bit RSA key.
Generating p:  .............++ (distance 218)
Generating q:  ...........++ (distance 196)
Computing the keys...
Testing the keys...
Key generation complete.
log: RSA key generation complete.
debug: Server will not fork when running in debugging mode.
log: Connection from 194.42.244.44 port 1021
debug: Client protocol version 1.5; client software version 1.2.27
debug: Sent 768 bit public key and 1024 bit host key.
debug: Encryption type: idea
debug: Received session key; encryption turned on.
debug: Installing crc compensation attack detector.
debug: Attempting authentication for wout.
debug: Trying rhosts with RSA host authentication for wout
debug: RhostsRSA authentication failed for 'wout', remote 'wout', host 
'lisa.365.co.uk'.
log: RSA authentication for wout accepted.
debug: Received request for X11 forwarding with auth spoofing.
debug: bind port 6010: Address already in use
debug: Allocated channel 0 of type 1.
debug: Received authentication agent forwarding request.
debug: Allocated channel 1 of type 10.
debug: Executing command 'cat /tmp/DATA'
debug: Entering interactive session.
debug: Received SIGCHLD.
debug: End of interactive session; stdin 0, stdout (read 200000, sent 200000), stderr 
567 bytes.
debug: Command exited with status 0.
debug: Received exit confirmation.
log: Closing connection to 194.42.244.44


Corresponding ssh output (client):

13:41 [wout@lisa] /tmp 35>ssh -v -p 5544 dnp2.football365.co.uk cat /tmp/DATA > 
/tmp/DATA-patched-sshd
SSH Version 1.2.27 [sparc-sun-solaris2.7], protocol version 1.5.
Standard version.  Does not use RSAREF.
lisa: Reading configuration data /etc/ssh_config
lisa: ssh_connect: getuid 1000 geteuid 0 anon 0
lisa: Connecting to dnp2.football365.co.uk [212.2.1.2] port 5544.
lisa: Allocated local port 1021.
lisa: Connection established.
lisa: Remote protocol version 1.5, remote software version 1.2.27
lisa: Waiting for server public key.
lisa: Received server public key (768 bits) and host key (1024 bits).
lisa: Host 'dnp2.football365.co.uk' is known and matches the host key.
lisa: Initializing random; seed file /home/wout/.ssh/random_seed
lisa: Encryption type: idea
lisa: Sent encrypted session key.
lisa: Installing crc compensation attack detector.
lisa: Received encrypted confirmation.
lisa: Trying rhosts or /etc/hosts.equiv with RSA host authentication.
lisa: Remote: Rhosts/hosts.equiv authentication refused: client user 'wout', server 
user 'wout', client host 'lisa.365.co.uk'.
lisa: Server refused our rhosts authentication or host key.
lisa: Connection to authentication agent opened.
lisa: Trying RSA authentication via agent with '[EMAIL PROTECTED]'
lisa: Received RSA challenge from server.
lisa: Sending response to RSA challenge.
lisa: Remote: RSA authentication accepted.
lisa: RSA authentication accepted by server.
lisa: Failed to get local xauth data.
lisa: Requesting X11 forwarding with authentication spoofing.
lisa: Requesting authentication agent forwarding.
lisa: Sending command: cat /tmp/DATA
lisa: Entering interactive session.
log: executing remote command as user wout
Environment:
  HOME=/homes/home/wout
  USER=wout
  LOGNAME=wout
  PATH=/bin:/usr/bin:/usr/ucb:/usr/bin/X11:/usr/local/bin:/usr/local/bin
  MAIL=/var/mail/wout
  SHELL=/bin/tcsh
  TZ=GB
  SSH_CLIENT=194.42.244.44 1021 5544
  DISPLAY=dnp2.football365.co.uk:11.0
  SSH_AUTH_SOCK=/tmp/ssh-wout/ssh-17462-agent

Running /usr/openwin/bin/xauth add dnp2.football365.co.uk:11.0 MIT-MAGIC-COOKIE-1 
89baa674c215da2f6c290a8e9442426d
Running /usr/openwin/bin/xauth add 212.2.1.2:11.0 MIT-MAGIC-COOKIE-1 
89baa674c215da2f6c290a8e9442426d
lisa: Transferred: stdin 0, stdout 200567, stderr 0 bytes in 14.8 seconds
lisa: Bytes per second: stdin 0.0, stdout 13547.2, stderr 0.0
lisa: Exit status 0

13:42 [wout@lisa] /tmp 36>ls -l /tmp/DATA-patched-sshd 
-rw-r--r--   1 wout     staff     200000 Mar 27 13:42 /tmp/DATA-patched-sshd

13:43 [wout@lisa] /tmp 37>sum /tmp/DATA-patched-sshd 
57919 391 /tmp/DATA-patched-sshd


And on server:

13:43 [wout@dnp2] /usr/local/sbin 20#ls -l /tmp/DATA 
-rw-r--r--   1 root     other     200000 Mar 23 11:20 /tmp/DATA

13:43 [wout@dnp2] /usr/local/sbin 21#sum /tmp/DATA 
57919 391 /tmp/DATA

Reply via email to