Uncaught exception when SSL connection is reset during handshake
Hello,
I am using gajim (from svn, up to date) with Python 2.4.1, Pygtk 2.6, on DragonFly (a BSD variant based on FreeBSD 4).
I have found the following problem: when the TCP connection to the server is reset during the SSL handshake, a socket.sslerror exception is raised, but not caught:
Python produces the following trackback in the console (using gajim 0.8, but the code producing the error hasn't changed in svn, only the line numbers may vary).
Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/local/lib/python2.4/threading.py", line 442, in __bootstrap
self.run()
File "/usr/local/lib/python2.4/threading.py", line 422, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/local/share/gajim/src/common/connection.py", line 1419, in change_status2
self.connection = self.connect()
File "/usr/local/share/gajim/src/common/connection.py", line 1241, in connect
con_type = con.connect((h, p), proxy = proxy, secure=secur) #FIXME: blocking
File "/usr/local/share/gajim/src/common/xmpp/client.py", line 187, in connect
if not CommonClient.connect(self,server,proxy,secure) or secure\<>None and not secure: return self.connected
File "/usr/local/share/gajim/src/common/xmpp/client.py", line 167, in connect
transports.TLS().PlugIn(self,now=1)
File "/usr/local/share/gajim/src/common/xmpp/transports.py", line 229, in PlugIn
if now: return self._startSSL()
File "/usr/local/share/gajim/src/common/xmpp/transports.py", line 258, in _startSSL
tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None)
File "/usr/local/lib/python2.4/socket.py", line 74, in ssl
return _realssl(sock, keyfile, certfile)
sslerror: (8, 'EOF occurred in violation of protocol')
Since this exception is uncaught, the user gets no error message, and the application doesn't recover properly from the error.
I think this comes from the fact that transports.TLS.PlugIn returns None even if the connection is unsuccessful. Maybe it should return a boolean value indicating whether the connection has been successful or not ? I haven't found a good non-intrusive fix to this... Instead I use the following workaround, which cannot be considered as right since it imports the socket module in common/xmpp/client.py
--- gajim/src/common/xmpp/client.py 2005-09-01 16:19:19.000000000 +0200
+++ gajim.sslworkaround/src/common/xmpp/client.py 2005-09-01 16:18:26.000000000 +0200
@@ -21,6 +21,7 @@
These classes can be used for simple applications "AS IS" though.
"""
+import socket
import debug
Debug=debug
Debug.DEBUGGING_IS_ON=1
@@ -164,8 +165,11 @@
self._Server,self._Proxy=server,proxy
self.connected='tcp'
if (ssl is None and self.Connection.getPort() in (5223, 443)) or ssl:
+ try:
transports.TLS().PlugIn(self,now=1)
self.connected='ssl'
+ except socket.sslerror:
+ return
dispatcher.Dispatcher().PlugIn(self)
while self.Dispatcher.Stream._document_attrs is None:
if not self.Process(1): return
I had to modify common/connection.py as well...
--- gajim/src/common/connection.py 2005-09-01 16:19:23.000000000 +0200
+++ gajim.sslworkaround/src/common/connection.py 2005-09-01 16:13:48.000000000 +0200
@@ -1236,19 +1236,20 @@
if gajim.config.get_per('accounts', self.name, 'use_custom_host'):
h = gajim.config.get_per('accounts', self.name, 'custom_host')
p = gajim.config.get_per('accounts', self.name, 'custom_port')
con_type = con.connect((h, p), proxy = proxy, secure=secur) #FIXME: blocking
- self.peerhost = con.get_peerhost()
if not con_type:
gajim.log.debug("Couldn't connect to %s" % self.name)
self.connected = 0
self.dispatch('STATUS', 'offline')
self.dispatch('ERROR', (_('Could not connect to "%s"') % self.name,
_('Check your connection or try again later')))
return None
+ self.peerhost = con.get_peerhost() # if this line is put before the code that handles connections errors, it produces an exception if there is an error
+
gajim.log.debug(_('Connected to server with %s'), con_type)
# notify the gui about con_type
self.dispatch('CON_TYPE', con_type)
I hope this will help you :)
(If you want to reproduce the problem, you can use tcpnice (to slow the SSL handshake down) and tcpkill (to kill the TCP connection during the handshake) from dnsiff.)
Laurent Sartran