adium 5118:9c2f63e75aca: Work around buggy TLS implementations i...

commits at adium.im commits at adium.im
Tue Oct 16 22:11:59 UTC 2012


details:	http://hg.adium.im/adium/rev/9c2f63e75aca
revision:	5118:9c2f63e75aca
branch:		adium-1.5.4
author:		Evan Kinney <emkinney at gmail.com>
date:		Tue Oct 16 15:26:52 2012 -0400

Work around buggy TLS implementations in certain older XMPP servers by disabling TLS 1.1 and above on reconnect.
Subject: adium 5119:5a20bccaab6f: Change the following things for Evan's previous patch:

details:	http://hg.adium.im/adium/rev/5a20bccaab6f
revision:	5119:5a20bccaab6f
branch:		adium-1.5.4
author:		Thijs Alkemade <thijsalkemade at gmail.com>
date:		Wed Oct 17 00:11:16 2012 +0200

Change the following things for Evan's previous patch:

- Don't permanently workaround buggy servers, try normally once every run, if that fails, activate the workaround.
- Only automatically reconnect if the handshake failed and we might need the workaround, so we don't spam buggy servers that also happen to be offline.

Fixes #16081

diffs (195 lines):

diff -r 24a33c054027 -r 5a20bccaab6f ChangeLogs/Changes.txt
--- a/ChangeLogs/Changes.txt	Tue Oct 16 23:34:24 2012 +0200
+++ b/ChangeLogs/Changes.txt	Wed Oct 17 00:11:16 2012 +0200
@@ -8,6 +8,7 @@
  * Fixed a problem where accepting a group chat invite on Sametime 8.5.1 would crash Adium. (Jonathan Rice and Jere Krischel) (#16114)
  * Fixed a problem where accepting a group chat invite on HipChat's XMPP server would crash Adium. (#16007)
  * Fix a problem preventing Adium from executing Applescripts when Gatekeeper is enabled.
+ * Added routines to make Secure Transport (on 10.8 and above) work around buggy TLS implementations in certain older XMPP servers. (#16081)
 
 
 Version 1.5.3 (8/12/2012)
diff -r 24a33c054027 -r 5a20bccaab6f Plugins/Purple Service/ESPurpleJabberAccount.h
--- a/Plugins/Purple Service/ESPurpleJabberAccount.h	Tue Oct 16 23:34:24 2012 +0200
+++ b/Plugins/Purple Service/ESPurpleJabberAccount.h	Wed Oct 17 00:11:16 2012 +0200
@@ -30,6 +30,8 @@
 #define KEY_JABBER_VERIFY_CERTS         @"Jabber:Verify Certificates"
 #define KEY_JABBER_FT_PROXIES			@"Jabber:File Transfer Proxies"
 
+#define PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND "ssl_cdsa_buggy_tls_workaround"
+
 @class AMXMLConsoleController, AMPurpleJabberServiceDiscoveryBrowsing, AMPurpleJabberAdHocServer;
 
 @interface ESPurpleJabberAccount : CBPurpleAccount <AIAccount_Files> {
diff -r 24a33c054027 -r 5a20bccaab6f Plugins/Purple Service/ESPurpleJabberAccount.m
--- a/Plugins/Purple Service/ESPurpleJabberAccount.m	Tue Oct 16 23:34:24 2012 +0200
+++ b/Plugins/Purple Service/ESPurpleJabberAccount.m	Wed Oct 17 00:11:16 2012 +0200
@@ -127,6 +127,19 @@
 	return supportedPropertyKeys;
 }
 
+- (PurpleAccount *)purpleAccount
+{
+	if (!account) {
+		/* Lets be optimistic and hope they've fixed their buggy server today.
+		 * Do this here, so we only do it once for every run of Adium.
+		 */
+		account = [super purpleAccount];
+		purple_account_set_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, false);
+	}
+	
+	return account;
+}
+
 - (void)configurePurpleAccount
 {
 	[super configurePurpleAccount];
@@ -486,7 +499,13 @@
 		[self serverReportedInvalidPassword];
 		shouldAttemptReconnect = AIReconnectImmediately;
 	}
- 
+#ifdef HAVE_CDSA
+	else if (purple_account_get_bool([self purpleAccount],PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND,false) &&
+			 [*disconnectionError isEqualToString:[NSString stringWithUTF8String:_("SSL Handshake Failed")]]) {
+		AILog(@"%@: Reconnecting immediately to try to work around buggy TLS stacks",self);
+		shouldAttemptReconnect = AIReconnectImmediately;
+	}
+#endif
 	return shouldAttemptReconnect;
 }
 
diff -r 24a33c054027 -r 5a20bccaab6f Plugins/Purple Service/libpurple_extensions/ssl-cdsa.c
--- a/Plugins/Purple Service/libpurple_extensions/ssl-cdsa.c	Tue Oct 16 23:34:24 2012 +0200
+++ b/Plugins/Purple Service/libpurple_extensions/ssl-cdsa.c	Wed Oct 17 00:11:16 2012 +0200
@@ -51,6 +51,8 @@
 #define PURPLE_SSL_CDSA_DATA(gsc) ((PurpleSslCDSAData *)gsc->private_data)
 #define PURPLE_SSL_CONNECTION_IS_VALID(gsc) (g_list_find(connections, (gsc)) != NULL)
 
+#define PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND "ssl_cdsa_buggy_tls_workaround"
+
 /*
  * query_cert_chain - callback for letting the user review the certificate before accepting it
  *
@@ -130,6 +132,7 @@
 ssl_cdsa_handshake_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PurpleSslConnection *gsc = (PurpleSslConnection *)data;
+	PurpleAccount *account = gsc->account;
 	PurpleSslCDSAData *cdsa_data = PURPLE_SSL_CDSA_DATA(gsc);
     OSStatus err;
 	
@@ -140,66 +143,22 @@
 	 * here and there.
 	 */
 	err = SSLHandshake(cdsa_data->ssl_ctx);
-    if (err == errSSLPeerBadRecordMac) {
+    if (err == errSSLPeerBadRecordMac
+		&& !purple_account_get_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, false)
+		&& !strcmp(purple_account_get_protocol_id(account),"prpl-jabber")) {
         /*
-         * try explicitly forcing TLS 1.0/SSL 3.0 to (maybe) make buggy servers work
+         * Set a flag so we know to explicitly disable TLS 1.1 and 1.2 on our next (immediate) connection attempt for this account.
+         * Some XMPP servers use buggy TLS stacks that incorrectly report their capabilities, which breaks things with 10.8's new support
+         * for TLS 1.1 and 1.2.
          */
-        purple_debug_info("cdsa", "SSLHandshake reported bad MAC, forcing TLS 1.0/SSL 3.0\n");
-        
-        ssl_cdsa_close(gsc);
-        ssl_cdsa_create_context(gsc);
-        cdsa_data = PURPLE_SSL_CDSA_DATA(gsc);
-        
-        OSStatus protoErr;
-        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocolAll, false);
-        if (protoErr != noErr) {
-            fprintf(stderr, "cdsa: failed to disable protocols: error %d\n",(int)protoErr);
-            purple_debug_error("cdsa", "failed to disable protocols: error %d\n",(int)protoErr);
-            if (gsc->error_cb != NULL)
-                gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
-                              gsc->connect_cb_data);
-            
-            purple_ssl_close(gsc);
-            return;
-        }
-        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kTLSProtocol1, true);
-        if (protoErr != noErr) {
-            fprintf(stderr, "cdsa: failed to enable TLS 1.0: error %d\n",(int)protoErr);
-            purple_debug_error("cdsa", "failed to enable TLS 1.0: error %d\n",(int)protoErr);
-            if (gsc->error_cb != NULL)
-                gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
-                              gsc->connect_cb_data);
-            
-            purple_ssl_close(gsc);
-            return;
-        }
-        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocol3, true);
-        if (protoErr != noErr) {
-            fprintf(stderr, "cdsa: failed to enable SSL 3.0: error %d\n",(int)protoErr);
-            purple_debug_error("cdsa", "failed to enable SSL 3.0: error %d\n",(int)protoErr);
-            if (gsc->error_cb != NULL)
-                gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
-                              gsc->connect_cb_data);
-            
-            purple_ssl_close(gsc);
-            return;
-        }
-        
-        purple_debug_info("cdsa", "retrying SSLHandshake\n");
-        err = SSLHandshake(cdsa_data->ssl_ctx);
-        if (err != noErr) {
-            if(err == errSSLWouldBlock)
-                return;
-            fprintf(stderr,"cdsa: SSLHandshake failed after forcing protocol versions with error %d\n",(int)err);
-            purple_debug_error("cdsa", "SSLHandshake failed after forcing protocol versions with error %d\n",(int)err);
-            if (gsc->error_cb != NULL)
-                gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED,
-                              gsc->connect_cb_data);
-            
-            purple_ssl_close(gsc);
-            return;
-        }
-        purple_debug_info("cdsa", "SSLHandshake succeeded after forcing protocol versions, continuing ssl_connect\n");
+        purple_debug_info("cdsa", "SSLHandshake reported that the server rejected our MAC, which most likely means it lied about the TLS versions it supports.");
+        purple_debug_info("cdsa", "Setting a flag in this account to only use TLS 1.0 and below on the next connection attempt.");
+    
+        purple_account_set_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, true);
+        if (gsc->error_cb != NULL)
+            gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data);
+        purple_ssl_close(gsc);
+        return;
     } else if (err != noErr) {
 		if(err == errSSLWouldBlock)
 			return;
@@ -347,6 +306,7 @@
 static void
 ssl_cdsa_create_context(gpointer data) {
     PurpleSslConnection *gsc = (PurpleSslConnection *)data;
+    PurpleAccount *account = gsc->account;
 	PurpleSslCDSAData *cdsa_data;
     OSStatus err;
     
@@ -444,6 +404,24 @@
         return;
     }
     
+    if (purple_account_get_bool(account, PURPLE_SSL_CDSA_BUGGY_TLS_WORKAROUND, false)) {
+        purple_debug_info("cdsa", "Explicitly disabling TLS 1.1 and above to try and work around buggy TLS stacks\n");
+        
+        OSStatus protoErr;
+        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocolAll, false);
+        if (protoErr != noErr) {
+            purple_debug_error("cdsa", "SSLSetProtocolVersionEnabled failed to disable protocols\n");
+            if (gsc->error_cb != NULL)
+                gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data);
+            purple_ssl_close(gsc);
+            return;
+        }
+        
+        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocol2, true);
+        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kSSLProtocol3, true);
+        protoErr = SSLSetProtocolVersionEnabled(cdsa_data->ssl_ctx, kTLSProtocol1, true);
+    }
+    
     if(gsc->host) {
         /*
          * Set the peer's domain name so CDSA can check the certificate's CN




More information about the commits mailing list