From 12e9f5a79fe1ca6076ecb48196c8ee6e60a7b4c7 Mon Sep 17 00:00:00 2001 From: Paul Howarth Date: Fri, 16 Mar 2012 19:24:44 +0000 Subject: [PATCH] Fix libssh2 failing key re-exchange when write channel is saturated (#804156) --- libssh2-1.4.0-cc4f9d.patch | 58 ++++++++++++++++++++++++++++++++++++++ libssh2.spec | 14 ++++++--- 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 libssh2-1.4.0-cc4f9d.patch diff --git a/libssh2-1.4.0-cc4f9d.patch b/libssh2-1.4.0-cc4f9d.patch new file mode 100644 index 0000000..33e5e4d --- /dev/null +++ b/libssh2-1.4.0-cc4f9d.patch @@ -0,0 +1,58 @@ +commit cc4f9d5679278ce41cd5480fab3f5e71dba163ed +Author: Matthew Booth +Date: Fri Mar 16 16:29:00 2012 +0100 + + transport_send: Finish in-progress key exchange before sending data + + _libssh2_channel_write() first reads outstanding packets before writing + new data. If it reads a key exchange request, it will immediately start + key re-exchange, which will require sending a response. If the output + socket is full, this will result in a return from + _libssh2_transport_read() of LIBSSH2_ERROR_EAGAIN. In order not to block + a write because there is no data to read, this error is explicitly + ignored and the code continues marshalling a packet for sending. When it + is sent, the remote end immediately drops the connection because it was + expecting a continuation of the key exchange, but got a data packet. + + This change adds the same check for key exchange to + _libssh2_transport_send() that is in _libssh2_transport_read(). This + ensures that key exchange is completed before any data packet is sent. + +diff --git a/src/transport.c b/src/transport.c +index 057dcf5..95b9a3a 100644 +--- a/src/transport.c ++++ b/src/transport.c +@@ -296,7 +296,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) + * is done! + */ + _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the" +- " key re-exchange"); ++ " key re-exchange from _libssh2_transport_read"); + rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); + if (rc) + return rc; +@@ -687,6 +687,24 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, + const unsigned char *orgdata = data; + size_t orgdata_len = data_len; + ++ /* ++ * If the last read operation was interrupted in the middle of a key ++ * exchange, we must complete that key exchange before continuing to write ++ * further data. ++ * ++ * See the similar block in _libssh2_transport_read for more details. ++ */ ++ if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS && ++ !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) { ++ /* Don't write any new packets if we're still in the middle of a key ++ * exchange. */ ++ _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the" ++ " key re-exchange from _libssh2_transport_send"); ++ rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); ++ if (rc) ++ return rc; ++ } ++ + debugdump(session, "libssh2_transport_write plain", data, data_len); + if(data2) + debugdump(session, "libssh2_transport_write plain2", data2, data2_len); diff --git a/libssh2.spec b/libssh2.spec index 791b37e..7627806 100644 --- a/libssh2.spec +++ b/libssh2.spec @@ -9,7 +9,7 @@ Name: libssh2 Version: 1.4.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A library implementing the SSH2 protocol Group: System Environment/Libraries License: BSD @@ -17,6 +17,7 @@ URL: http://www.libssh2.org/ Source0: http://libssh2.org/download/libssh2-%{version}.tar.gz Patch0: libssh2-1.2.9-utf8.patch Patch1: libssh2-1.4.0-c4a0e0.patch +Patch2: libssh2-1.4.0-cc4f9d.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -nu) BuildRequires: openssl-devel BuildRequires: zlib-devel @@ -69,6 +70,10 @@ developing applications that use libssh2. # Fix undefined reference to _libssh_error in libgcrypt (upstream patch) %patch1 -p1 +# Fix libssh2 failing key re-exchange when write channel is saturated +# (upstream patch, #804156) +%patch2 -p1 + # Make sshd transition appropriately if building in an SELinux environment chcon $(/usr/sbin/matchpathcon -n /etc/rc.d/init.d/sshd) tests/ssh2.sh || : chcon -R $(/usr/sbin/matchpathcon -n /etc) tests/etc || : @@ -113,18 +118,15 @@ rm -rf %{buildroot} %postun -p /sbin/ldconfig %files -%defattr(-,root,root,-) %doc AUTHORS ChangeLog COPYING README NEWS %{_libdir}/libssh2.so.1 %{_libdir}/libssh2.so.1.* %files docs -%defattr(-,root,root,-) %doc HACKING %{_mandir}/man3/libssh2_*.3* %files devel -%defattr(-,root,root,-) %doc example/ %{_includedir}/libssh2.h %{_includedir}/libssh2_publickey.h @@ -133,6 +135,10 @@ rm -rf %{buildroot} %{_libdir}/pkgconfig/libssh2.pc %changelog +* Fri Mar 16 2012 Paul Howarth 1.4.0-2 +- fix libssh2 failing key re-exchange when write channel is saturated (#804156) +- drop %%defattr, redundant since rpm 4.4 + * Wed Feb 1 2012 Paul Howarth 1.4.0-1 - update to 1.4.0 - added libssh2_session_supported_algs()