Subject: Re: Potential remote listener bug

Re: Potential remote listener bug

From: Peter Stuge <peter_at_stuge.se>
Date: Mon, 26 Sep 2011 12:32:02 +0200

qus123_at_gmail.com wrote:
>> If the problem is the message framing issue over TCP I talked about then
>> it's really a bug in the application client program or server.
>
> So it's only a matter of coincidence that the problem doesn't exist in
> ssh and tunnelier?

Maybe, maybe not. It's also possible that they have taken extra
measures to try to avoid the problem. It might make sense for libssh2
to also do this, but I agree with Henrik that the real problem is in
the application that is being forwarded. I'll try to explain with an
example.

* Hypothesis: RDP is made up of frames with fixed or variable size
* RDP client sends one frame to the socket that is being forwarded
  using write(socket, frame_buffer, frame_buffer_length). Ie. it
  gives the operating system network stack the complete frame and
  asks that all of the frame be sent at once.
+ Here is the first bug. write() is never required to accept the
  complete data it is given. The OS may only be able to accept five
  out of 4096 bytes and will then only take five bytes, and the
  application must then send the remaining 4091 bytes later. If the
  bug is what Henrik describes then RDP would not tolerate this. That
  actually makes me somehow suspect that the problem lies elsewhere,
  because this is such a serious bug.
* Operating system accepts entire frame of bytes and sends it to your
  libssh2 application, which libssh2_write()s it to the direct-tcpip
  channel.
* The server is waiting for the server OS to receive data, the RDP
  server has called read(socket, frame_buffer, frame_length) and what
  Henrik means is that the RDP server depends on always receiving one
  complete frame here.
+ Here is the second bug. read() is exactly like write() and nothing
  can be assumed about the number of bytes that will be returned, the
  only thing you can be sure of with TCP is that the order of bytes
  will be the same as on the sender, and that no bytes will have been
  lost. Both sender and receiver operating systems and hardware and
  any number of network equipment between sender and receiver can
  cause asymmetry between number of bytes in write() and read() in
  this example. This is a hard fact of using TCP.
* Now, since the socket is not a direct connection but going through
  an ssh channel the one write has become two writes within the ssh
  layer, in order to fit ssh protocol requirements.
* The RDP server receives only half the frame from it's read() and
  starts processing it directly, without waiting for the second half
  of the frame to arrive, which it would do in a subsequent call to
  read().

This type of problem demonstrates fundamental lack of understanding
of TCP, and although Microsoft are not the most technically bright I
don't think they've made a mistake like this.

It would be good for you to do more tests with open source software.
In particular I suggest running an open source RDP client such as
http://www.rdesktop.org/ to get another data point and to be able to
do more in-depth debugging.

I suggest you also run wireshark on both sides of the tunnel to
investigate what goes in and comes out of the tunnel, and then
compare this with a straight RDP connection not using a tunnel.

//Peter
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2011-09-26