fixed handling of SSL errors
This commit is contained in:
parent
cbfa9d97df
commit
4504861084
|
@ -515,13 +515,12 @@ class Connection(ConnectionHandlers):
|
||||||
'connection_types').split()
|
'connection_types').split()
|
||||||
else:
|
else:
|
||||||
self._connection_types = ['tls', 'ssl', 'plain']
|
self._connection_types = ['tls', 'ssl', 'plain']
|
||||||
#THEHACK
|
|
||||||
#self._connection_types = ['ssl', 'plain']
|
|
||||||
|
|
||||||
if self._proxy and self._proxy['type']=='bosh':
|
if self._proxy and self._proxy['type']=='bosh':
|
||||||
# with BOSH, we can't do TLS negotiation with <starttls>, we do only "plain"
|
# with BOSH, we can't do TLS negotiation with <starttls>, we do only "plain"
|
||||||
# connection and TLS with handshake right after TCP connecting ("ssl")
|
# connection and TLS with handshake right after TCP connecting ("ssl")
|
||||||
try: self._connection_types.remove('tls')
|
try:
|
||||||
|
self._connection_types.remove('tls')
|
||||||
except ValueError: pass
|
except ValueError: pass
|
||||||
|
|
||||||
host = self.select_next_host(self._hosts)
|
host = self.select_next_host(self._hosts)
|
||||||
|
@ -553,7 +552,12 @@ class Connection(ConnectionHandlers):
|
||||||
|
|
||||||
if self._current_type == 'ssl':
|
if self._current_type == 'ssl':
|
||||||
# SSL (force TLS on different port than plain)
|
# SSL (force TLS on different port than plain)
|
||||||
port = self._current_host['ssl_port']
|
# If we do TLS over BOSH, port of XMPP server should be the standard one
|
||||||
|
# and TLS should be negotiated because immediate TLS on 5223 is deprecated
|
||||||
|
if self._proxy and self._proxy['type']=='bosh':
|
||||||
|
port = self._current_host['port']
|
||||||
|
else:
|
||||||
|
port = self._current_host['ssl_port']
|
||||||
elif self._current_type == 'tls':
|
elif self._current_type == 'tls':
|
||||||
# TLS - negotiate tls after XMPP stream is estabilished
|
# TLS - negotiate tls after XMPP stream is estabilished
|
||||||
port = self._current_host['port']
|
port = self._current_host['port']
|
||||||
|
|
|
@ -113,9 +113,8 @@ class NonBlockingBOSH(NonBlockingTransport):
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return
|
return
|
||||||
|
|
||||||
print 'SSSSSSSSSSEEEEEEEEEND'
|
#Hack for making the non-secure warning dialog work
|
||||||
if hasattr(self._owner, 'NonBlockingNonSASL') or hasattr(self._owner, 'SASL'):
|
if hasattr(self._owner, 'NonBlockingNonSASL') or hasattr(self._owner, 'SASL'):
|
||||||
#FIXME: Hack for making the non-secure warning dialog work
|
|
||||||
self.send_BOSH(None)
|
self.send_BOSH(None)
|
||||||
else:
|
else:
|
||||||
self.http_socks[0]._plug_idle(writable=False, readable=True)
|
self.http_socks[0]._plug_idle(writable=False, readable=True)
|
||||||
|
@ -453,31 +452,31 @@ class AckChecker():
|
||||||
|
|
||||||
|
|
||||||
class KeyStack():
|
class KeyStack():
|
||||||
def __init__(self, count):
|
def __init__(self, count):
|
||||||
self.count = count
|
self.count = count
|
||||||
self.keys = []
|
self.keys = []
|
||||||
self.reset()
|
self.reset()
|
||||||
self.first_call = True
|
self.first_call = True
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
seed = str(get_rand_number())
|
seed = str(get_rand_number())
|
||||||
self.keys = [sha.new(seed).hexdigest()]
|
self.keys = [sha.new(seed).hexdigest()]
|
||||||
for i in range(self.count-1):
|
for i in range(self.count-1):
|
||||||
curr_seed = self.keys[i]
|
curr_seed = self.keys[i]
|
||||||
self.keys.append(sha.new(curr_seed).hexdigest())
|
self.keys.append(sha.new(curr_seed).hexdigest())
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
if self.first_call:
|
if self.first_call:
|
||||||
self.first_call = False
|
self.first_call = False
|
||||||
return (None, self.keys.pop())
|
return (None, self.keys.pop())
|
||||||
|
|
||||||
if len(self.keys)>1:
|
if len(self.keys)>1:
|
||||||
return (self.keys.pop(), None)
|
return (self.keys.pop(), None)
|
||||||
else:
|
else:
|
||||||
last_key = self.keys.pop()
|
last_key = self.keys.pop()
|
||||||
self.reset()
|
self.reset()
|
||||||
new_key = self.keys.pop()
|
new_key = self.keys.pop()
|
||||||
return (last_key, new_key)
|
return (last_key, new_key)
|
||||||
|
|
||||||
# http://www.xmpp.org/extensions/xep-0124.html#errorstatus-terminal
|
# http://www.xmpp.org/extensions/xep-0124.html#errorstatus-terminal
|
||||||
bosh_errors = {
|
bosh_errors = {
|
||||||
|
|
|
@ -23,7 +23,7 @@ These classes can be used for simple applications "AS IS" though.
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
import transports_nb, tls_nb, dispatcher_nb, auth_nb, roster_nb, protocol, bosh
|
import transports_nb, dispatcher_nb, auth_nb, roster_nb, protocol, bosh
|
||||||
from client import *
|
from client import *
|
||||||
|
|
||||||
from protocol import NS_TLS
|
from protocol import NS_TLS
|
||||||
|
@ -234,6 +234,7 @@ class NBCommonClient:
|
||||||
xmlns=NS_TLS)
|
xmlns=NS_TLS)
|
||||||
self.send('<starttls xmlns="%s"/>' % NS_TLS)
|
self.send('<starttls xmlns="%s"/>' % NS_TLS)
|
||||||
else:
|
else:
|
||||||
|
# we got <proceed> or <failure>
|
||||||
if tag.getNamespace() <> NS_TLS:
|
if tag.getNamespace() <> NS_TLS:
|
||||||
self._on_connect_failure('Unknown namespace: %s' % tag.getNamespace())
|
self._on_connect_failure('Unknown namespace: %s' % tag.getNamespace())
|
||||||
return
|
return
|
||||||
|
|
|
@ -110,9 +110,8 @@ class IdleQueue:
|
||||||
if alarm_time > current_time:
|
if alarm_time > current_time:
|
||||||
break
|
break
|
||||||
if self.alarms.has_key(alarm_time):
|
if self.alarms.has_key(alarm_time):
|
||||||
for cb in self.alarms[alarm_time]:
|
for cb in self.alarms[alarm_time]: cb()
|
||||||
cb()
|
if self.alarms.has_key(alarm_time): del(self.alarms[alarm_time])
|
||||||
del(self.alarms[alarm_time])
|
|
||||||
|
|
||||||
def plug_idle(self, obj, writable = True, readable = True):
|
def plug_idle(self, obj, writable = True, readable = True):
|
||||||
if obj.fd == -1:
|
if obj.fd == -1:
|
||||||
|
|
|
@ -20,7 +20,6 @@ I'm personally using it in many other separate projects. It is designed to be as
|
||||||
import xml.parsers.expat
|
import xml.parsers.expat
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger('gajim.c.x.simplexml')
|
log = logging.getLogger('gajim.c.x.simplexml')
|
||||||
#log.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
def XMLescape(txt):
|
def XMLescape(txt):
|
||||||
'''Returns provided string with symbols & < > " replaced by their respective XML entities.'''
|
'''Returns provided string with symbols & < > " replaced by their respective XML entities.'''
|
||||||
|
|
|
@ -150,7 +150,6 @@ class PyOpenSSLWrapper(SSLWrapper):
|
||||||
else: retval = self.sslobj.recv(bufsize, flags)
|
else: retval = self.sslobj.recv(bufsize, flags)
|
||||||
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
|
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
|
||||||
log.debug("Recv: Want-error: " + repr(e))
|
log.debug("Recv: Want-error: " + repr(e))
|
||||||
pass
|
|
||||||
except OpenSSL.SSL.SysCallError, e:
|
except OpenSSL.SSL.SysCallError, e:
|
||||||
log.debug("Recv: Got OpenSSL.SSL.SysCallError: " + repr(e), exc_info=True)
|
log.debug("Recv: Got OpenSSL.SSL.SysCallError: " + repr(e), exc_info=True)
|
||||||
#traceback.print_exc()
|
#traceback.print_exc()
|
||||||
|
@ -202,8 +201,7 @@ class StdlibSSLWrapper(SSLWrapper):
|
||||||
try:
|
try:
|
||||||
return self.sslobj.read(bufsize)
|
return self.sslobj.read(bufsize)
|
||||||
except socket.sslerror, e:
|
except socket.sslerror, e:
|
||||||
#log.debug("Recv: Caught socket.sslerror:", exc_info=True)
|
log.debug("Recv: Caught socket.sslerror:", exc_info=True)
|
||||||
#traceback.print_exc()
|
|
||||||
if e.args[0] not in (socket.SSL_ERROR_WANT_READ, socket.SSL_ERROR_WANT_WRITE):
|
if e.args[0] not in (socket.SSL_ERROR_WANT_READ, socket.SSL_ERROR_WANT_WRITE):
|
||||||
raise SSLWrapper.Error(self.sock or self.sslobj, e)
|
raise SSLWrapper.Error(self.sock or self.sslobj, e)
|
||||||
return None
|
return None
|
||||||
|
@ -213,8 +211,7 @@ class StdlibSSLWrapper(SSLWrapper):
|
||||||
try:
|
try:
|
||||||
return self.sslobj.write(data)
|
return self.sslobj.write(data)
|
||||||
except socket.sslerror, e:
|
except socket.sslerror, e:
|
||||||
#log.debug("Send: Caught socket.sslerror:", exc_info=True)
|
log.debug("Send: Caught socket.sslerror:", exc_info=True)
|
||||||
#traceback.print_exc()
|
|
||||||
if e.args[0] not in (socket.SSL_ERROR_WANT_READ, socket.SSL_ERROR_WANT_WRITE):
|
if e.args[0] not in (socket.SSL_ERROR_WANT_READ, socket.SSL_ERROR_WANT_WRITE):
|
||||||
raise SSLWrapper.Error(self.sock or self.sslobj, e)
|
raise SSLWrapper.Error(self.sock or self.sslobj, e)
|
||||||
return 0
|
return 0
|
||||||
|
@ -274,13 +271,12 @@ class NonBlockingTLS(PlugIn):
|
||||||
print >> stream, "PKey type: %s (%d)" % (typedict.get(pkey.type(), "Unknown"), pkey.type())
|
print >> stream, "PKey type: %s (%d)" % (typedict.get(pkey.type(), "Unknown"), pkey.type())
|
||||||
|
|
||||||
def _startSSL(self):
|
def _startSSL(self):
|
||||||
''' Immidiatedly switch socket to TLS mode. Used internally.'''
|
''' Immediatedly switch socket to TLS mode. Used internally.'''
|
||||||
log.debug("_startSSL called")
|
log.debug("_startSSL called")
|
||||||
if USE_PYOPENSSL: return self._startSSL_pyOpenSSL()
|
if USE_PYOPENSSL: return self._startSSL_pyOpenSSL()
|
||||||
else: return self._startSSL_stdlib()
|
else: return self._startSSL_stdlib()
|
||||||
|
|
||||||
def _startSSL_pyOpenSSL(self):
|
def _startSSL_pyOpenSSL(self):
|
||||||
#log.debug("_startSSL_pyOpenSSL called, thread id: %s", str(thread.get_ident()))
|
|
||||||
log.debug("_startSSL_pyOpenSSL called")
|
log.debug("_startSSL_pyOpenSSL called")
|
||||||
tcpsock = self._owner
|
tcpsock = self._owner
|
||||||
# FIXME: should method be configurable?
|
# FIXME: should method be configurable?
|
||||||
|
|
|
@ -21,7 +21,7 @@ from simplexml import ustr
|
||||||
from client import PlugIn
|
from client import PlugIn
|
||||||
from idlequeue import IdleObject
|
from idlequeue import IdleObject
|
||||||
from protocol import *
|
from protocol import *
|
||||||
from tls_nb import NonBlockingTLS
|
import tls_nb
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
@ -304,7 +304,7 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
|
|
||||||
def tls_init(self, on_succ, on_fail):
|
def tls_init(self, on_succ, on_fail):
|
||||||
cacerts, mycerts = self.certs
|
cacerts, mycerts = self.certs
|
||||||
result = NonBlockingTLS(cacerts, mycerts).PlugIn(self)
|
result = tls_nb.NonBlockingTLS(cacerts, mycerts).PlugIn(self)
|
||||||
if result: on_succ()
|
if result: on_succ()
|
||||||
else: on_fail()
|
else: on_fail()
|
||||||
|
|
||||||
|
@ -436,7 +436,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
|
|
||||||
def _do_receive(self):
|
def _do_receive(self):
|
||||||
''' Reads all pending incoming data. Calls owner's disconnected() method if appropriate.'''
|
''' Reads all pending incoming data. Calls owner's disconnected() method if appropriate.'''
|
||||||
ERR_DISCONN = -2 # Misc error signifying that we got disconnected
|
# Misc error signifying that we got disconnected
|
||||||
|
ERR_DISCONN = -2
|
||||||
|
# code for unknown/other errors
|
||||||
|
ERR_OTHER = -3
|
||||||
received = None
|
received = None
|
||||||
errnum = 0
|
errnum = 0
|
||||||
errstr = 'No Error Set'
|
errstr = 'No Error Set'
|
||||||
|
@ -444,9 +447,13 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
try:
|
try:
|
||||||
# get as many bites, as possible, but not more than RECV_BUFSIZE
|
# get as many bites, as possible, but not more than RECV_BUFSIZE
|
||||||
received = self._recv(RECV_BUFSIZE)
|
received = self._recv(RECV_BUFSIZE)
|
||||||
except (socket.error, socket.herror, socket.gaierror), (errnum, errstr):
|
except socket.error, (errnum, errstr):
|
||||||
# save exception number and message to errnum, errstr
|
# save exception number and message to errnum, errstr
|
||||||
log.info("_do_receive: got %s:" % received , exc_info=True)
|
log.info("_do_receive: got %s:" % received , exc_info=True)
|
||||||
|
except tls_nb.SSLWrapper.Error, e:
|
||||||
|
log.info("_do_receive, caugth SSL error: got %s:" % received , exc_info=True)
|
||||||
|
errnum = tls_nb.gattr(e, 'errno') or ERR_OTHER
|
||||||
|
errstr = tls_nb.gattr(e, 'exc_str')
|
||||||
|
|
||||||
if received == '':
|
if received == '':
|
||||||
errnum = ERR_DISCONN
|
errnum = ERR_DISCONN
|
||||||
|
@ -456,25 +463,24 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
# ECONNRESET - connection you are trying to access has been reset by the peer
|
# ECONNRESET - connection you are trying to access has been reset by the peer
|
||||||
# ENOTCONN - Transport endpoint is not connected
|
# ENOTCONN - Transport endpoint is not connected
|
||||||
# ESHUTDOWN - shutdown(2) has been called on a socket to close down the
|
# ESHUTDOWN - shutdown(2) has been called on a socket to close down the
|
||||||
# sending end of the transmision, and then data was attempted to be sent
|
# sending end of the transmision, and then data was attempted to be sent
|
||||||
log.error("Connection to %s lost: %s %s" % ( self.server, errnum, errstr), exc_info=True)
|
log.error("Connection to %s lost: %s %s" % ( self.server, errnum, errstr), exc_info=True)
|
||||||
if hasattr(self, 'on_remote_disconnect'): self.on_remote_disconnect()
|
if hasattr(self, 'on_remote_disconnect'): self.on_remote_disconnect()
|
||||||
else: self.disconnect()
|
else: self.disconnect()
|
||||||
return
|
return
|
||||||
|
|
||||||
if received is None:
|
if received is None:
|
||||||
# in case of SSL error - because there are two types of TLS wrappers, the TLS
|
# because there are two types of TLS wrappers, the TLS plugin recv method
|
||||||
# pluging recv method returns None in case of error
|
# returns None in case of error
|
||||||
print 'SSL ERROR'
|
|
||||||
if errnum != 0:
|
if errnum != 0:
|
||||||
log.error("CConnection to %s lost: %s %s" % (self.server, errnum, errstr))
|
log.error("CConnection to %s lost: %s %s" % (self.server, errnum, errstr))
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return
|
return
|
||||||
received = ''
|
received = ''
|
||||||
|
return
|
||||||
|
|
||||||
# we have received some bytes, stop the timeout!
|
# we have received some bytes, stop the timeout!
|
||||||
self.renew_send_timeout()
|
self.renew_send_timeout()
|
||||||
print '-->%s<--' % received
|
|
||||||
# pass received data to owner
|
# pass received data to owner
|
||||||
if self.on_receive:
|
if self.on_receive:
|
||||||
self.raise_event(DATA_RECEIVED, received)
|
self.raise_event(DATA_RECEIVED, received)
|
||||||
|
@ -732,7 +738,7 @@ class NBHTTPProxySocket(NBProxySocket):
|
||||||
return
|
return
|
||||||
if len(reply) != 2:
|
if len(reply) != 2:
|
||||||
pass
|
pass
|
||||||
NonBlockingT._on_connect(self)
|
NonBlockingTCP._on_connect(self)
|
||||||
#self.onreceive(self._on_proxy_auth)
|
#self.onreceive(self._on_proxy_auth)
|
||||||
|
|
||||||
def _on_proxy_auth(self, reply):
|
def _on_proxy_auth(self, reply):
|
||||||
|
|
Loading…
Reference in New Issue