/pidgin/main: 42ba908c25c7: Fix Yahoo login when using the GnuTL...

Mark Doliner mark at kingant.net
Mon Jul 7 03:09:19 EDT 2014


Changeset: 42ba908c25c7682aecede15b94936e27266c471d
Author:	 Mark Doliner <mark at kingant.net>
Date:	 2014-07-07 00:09 -0700
Branch:	 release-2.x.y
URL: https://hg.pidgin.im/pidgin/main/rev/42ba908c25c7

Description:

Fix Yahoo login when using the GnuTLS library for TLS connections.

I changed our gnutls plugin to always treat a closed TCP connection
as if the remote server cleanly terminated the SSL session. I think
it's sad that this is necessary, but I also think it's fairly
harmless. See my comments in the code for details.

diffstat:

 ChangeLog                          |   3 ++
 libpurple/plugins/ssl/ssl-gnutls.c |  53 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 0 deletions(-)

diffs (76 lines):

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,9 @@ version 2.10.10 (?/?/?):
 	XMPP:
 	* Fix Facebook XMPP roster quirks. (#15041, #15957)
 
+	Yahoo:
+	* Fix login when using the GnuTLS library for TLS connections. (#16172)
+
 version 2.10.9 (2/2/2014):
 	XMPP:
 	* Fix problems logging into some servers including jabber.org and
diff --git a/libpurple/plugins/ssl/ssl-gnutls.c b/libpurple/plugins/ssl/ssl-gnutls.c
--- a/libpurple/plugins/ssl/ssl-gnutls.c
+++ b/libpurple/plugins/ssl/ssl-gnutls.c
@@ -468,6 +468,59 @@ ssl_gnutls_read(PurpleSslConnection *gsc
 	if(s == GNUTLS_E_AGAIN || s == GNUTLS_E_INTERRUPTED) {
 		s = -1;
 		errno = EAGAIN;
+
+#ifdef GNUTLS_E_PREMATURE_TERMINATION
+	} else if (s == GNUTLS_E_PREMATURE_TERMINATION) {
+		purple_debug_warning("gnutls", "Received a FIN on the TCP socket "
+				"for %s. This either means that the remote server closed "
+				"the socket without sending us a Close Notify alert or a "
+				"man-in-the-middle injected a FIN into the TCP stream. "
+				"Assuming it's the former.\n", gsc->host);
+#else
+	} else if (s == GNUTLS_E_UNEXPECTED_PACKET_LENGTH) {
+		purple_debug_warning("gnutls", "Received packet of unexpected "
+				"length on the TCP socket for %s. Among other "
+				"possibilities this might mean that the remote server "
+				"closed the socket without sending us a Close Notify alert. "
+				"Assuming that's the case for compatibility, however, note "
+				"that it's quite possible that we're incorrectly ignoing "
+				"a real error.\n", gsc->host);
+#endif
+		/*
+		 * Summary:
+		 * Always treat a closed TCP connection as if the remote server cleanly
+		 * terminated the SSL session.
+		 *
+		 * Background:
+		 * Most TLS servers send a Close Notify alert before sending TCP FIN
+		 * when closing a session. This informs us at the TLS layer that the
+		 * connection is being cleanly closed. Without this it's more
+		 * difficult for us to determine whether the session was closed
+		 * cleanly (we would need to resort to having the application layer
+		 * perform this check, e.g. by looking at the Content-Length HTTP
+		 * header for HTTP connections).
+		 *
+		 * There ARE servers that don't send Close Notify and we want to be
+		 * compatible with them. And so we don't require Close Notify. This
+		 * seems to match the behavior of libnss. This is a slightly
+		 * unfortunate situation. It means a malicious MITM can inject a FIN
+		 * into our TCP stream and cause our encrypted session to termiate
+		 * and we won't indicate any problem to the user.
+		 *
+		 * GnuTLS < 3.0.0 returned the UNEXPECTED_PACKET_LENGTH error on EOF.
+		 * GnuTLS >= 3.0.0 added the PREMATURE_TERMINATION error to allow us
+		 * to detect the problem more specifically.
+		 *
+		 * For historical discussion see:
+		 * https://developer.pidgin.im/ticket/16172
+		 * http://trac.adiumx.com/intertrac/ticket%3A16678
+		 * https://bugzilla.mozilla.org/show_bug.cgi?id=508698#c4
+		 * http://lists.gnu.org/archive/html/gnutls-devel/2008-03/msg00058.html
+		 * Or search for GNUTLS_E_UNEXPECTED_PACKET_LENGTH or
+		 * GNUTLS_E_PREMATURE_TERMINATION
+		 */
+		s = 0;
+
 	} else if(s < 0) {
 		purple_debug_error("gnutls", "receive failed: %s\n",
 				gnutls_strerror(s));



More information about the Commits mailing list