fixed handling of SSL errors

This commit is contained in:
tomk 2008-08-09 12:16:42 +00:00
parent cbfa9d97df
commit 4504861084
7 changed files with 50 additions and 46 deletions

View File

@ -515,13 +515,12 @@ class Connection(ConnectionHandlers):
'connection_types').split()
else:
self._connection_types = ['tls', 'ssl', 'plain']
#THEHACK
#self._connection_types = ['ssl', 'plain']
if self._proxy and self._proxy['type']=='bosh':
# with BOSH, we can't do TLS negotiation with <starttls>, we do only "plain"
# 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
host = self.select_next_host(self._hosts)
@ -553,7 +552,12 @@ class Connection(ConnectionHandlers):
if self._current_type == 'ssl':
# 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':
# TLS - negotiate tls after XMPP stream is estabilished
port = self._current_host['port']

View File

@ -113,9 +113,8 @@ class NonBlockingBOSH(NonBlockingTransport):
self.disconnect()
return
print 'SSSSSSSSSSEEEEEEEEEND'
#Hack for making the non-secure warning dialog work
if hasattr(self._owner, 'NonBlockingNonSASL') or hasattr(self._owner, 'SASL'):
#FIXME: Hack for making the non-secure warning dialog work
self.send_BOSH(None)
else:
self.http_socks[0]._plug_idle(writable=False, readable=True)
@ -453,31 +452,31 @@ class AckChecker():
class KeyStack():
def __init__(self, count):
self.count = count
self.keys = []
self.reset()
def __init__(self, count):
self.count = count
self.keys = []
self.reset()
self.first_call = True
def reset(self):
seed = str(get_rand_number())
self.keys = [sha.new(seed).hexdigest()]
for i in range(self.count-1):
curr_seed = self.keys[i]
self.keys.append(sha.new(curr_seed).hexdigest())
def reset(self):
seed = str(get_rand_number())
self.keys = [sha.new(seed).hexdigest()]
for i in range(self.count-1):
curr_seed = self.keys[i]
self.keys.append(sha.new(curr_seed).hexdigest())
def get(self):
def get(self):
if self.first_call:
self.first_call = False
return (None, self.keys.pop())
if len(self.keys)>1:
return (self.keys.pop(), None)
else:
last_key = self.keys.pop()
self.reset()
new_key = self.keys.pop()
return (last_key, new_key)
if len(self.keys)>1:
return (self.keys.pop(), None)
else:
last_key = self.keys.pop()
self.reset()
new_key = self.keys.pop()
return (last_key, new_key)
# http://www.xmpp.org/extensions/xep-0124.html#errorstatus-terminal
bosh_errors = {

View File

@ -23,7 +23,7 @@ These classes can be used for simple applications "AS IS" though.
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 protocol import NS_TLS
@ -234,6 +234,7 @@ class NBCommonClient:
xmlns=NS_TLS)
self.send('<starttls xmlns="%s"/>' % NS_TLS)
else:
# we got <proceed> or <failure>
if tag.getNamespace() <> NS_TLS:
self._on_connect_failure('Unknown namespace: %s' % tag.getNamespace())
return

View File

@ -110,9 +110,8 @@ class IdleQueue:
if alarm_time > current_time:
break
if self.alarms.has_key(alarm_time):
for cb in self.alarms[alarm_time]:
cb()
del(self.alarms[alarm_time])
for cb in self.alarms[alarm_time]: cb()
if self.alarms.has_key(alarm_time): del(self.alarms[alarm_time])
def plug_idle(self, obj, writable = True, readable = True):
if obj.fd == -1:

View File

@ -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 logging
log = logging.getLogger('gajim.c.x.simplexml')
#log.setLevel(logging.DEBUG)
def XMLescape(txt):
'''Returns provided string with symbols & < > " replaced by their respective XML entities.'''

View File

@ -150,7 +150,6 @@ class PyOpenSSLWrapper(SSLWrapper):
else: retval = self.sslobj.recv(bufsize, flags)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
log.debug("Recv: Want-error: " + repr(e))
pass
except OpenSSL.SSL.SysCallError, e:
log.debug("Recv: Got OpenSSL.SSL.SysCallError: " + repr(e), exc_info=True)
#traceback.print_exc()
@ -202,8 +201,7 @@ class StdlibSSLWrapper(SSLWrapper):
try:
return self.sslobj.read(bufsize)
except socket.sslerror, e:
#log.debug("Recv: Caught socket.sslerror:", exc_info=True)
#traceback.print_exc()
log.debug("Recv: Caught socket.sslerror:", exc_info=True)
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)
return None
@ -213,8 +211,7 @@ class StdlibSSLWrapper(SSLWrapper):
try:
return self.sslobj.write(data)
except socket.sslerror, e:
#log.debug("Send: Caught socket.sslerror:", exc_info=True)
#traceback.print_exc()
log.debug("Send: Caught socket.sslerror:", exc_info=True)
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)
return 0
@ -274,13 +271,12 @@ class NonBlockingTLS(PlugIn):
print >> stream, "PKey type: %s (%d)" % (typedict.get(pkey.type(), "Unknown"), pkey.type())
def _startSSL(self):
''' Immidiatedly switch socket to TLS mode. Used internally.'''
''' Immediatedly switch socket to TLS mode. Used internally.'''
log.debug("_startSSL called")
if USE_PYOPENSSL: return self._startSSL_pyOpenSSL()
else: return self._startSSL_stdlib()
def _startSSL_pyOpenSSL(self):
#log.debug("_startSSL_pyOpenSSL called, thread id: %s", str(thread.get_ident()))
log.debug("_startSSL_pyOpenSSL called")
tcpsock = self._owner
# FIXME: should method be configurable?

View File

@ -21,7 +21,7 @@ from simplexml import ustr
from client import PlugIn
from idlequeue import IdleObject
from protocol import *
from tls_nb import NonBlockingTLS
import tls_nb
import sys
import os
@ -304,7 +304,7 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
def tls_init(self, on_succ, on_fail):
cacerts, mycerts = self.certs
result = NonBlockingTLS(cacerts, mycerts).PlugIn(self)
result = tls_nb.NonBlockingTLS(cacerts, mycerts).PlugIn(self)
if result: on_succ()
else: on_fail()
@ -436,7 +436,10 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
def _do_receive(self):
''' 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
errnum = 0
errstr = 'No Error Set'
@ -444,9 +447,13 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
try:
# get as many bites, as possible, but not more than 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
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 == '':
errnum = ERR_DISCONN
@ -456,25 +463,24 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
# ECONNRESET - connection you are trying to access has been reset by the peer
# ENOTCONN - Transport endpoint is not connected
# 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)
if hasattr(self, 'on_remote_disconnect'): self.on_remote_disconnect()
else: self.disconnect()
return
if received is None:
# in case of SSL error - because there are two types of TLS wrappers, the TLS
# pluging recv method returns None in case of error
print 'SSL ERROR'
# because there are two types of TLS wrappers, the TLS plugin recv method
# returns None in case of error
if errnum != 0:
log.error("CConnection to %s lost: %s %s" % (self.server, errnum, errstr))
self.disconnect()
return
received = ''
return
# we have received some bytes, stop the timeout!
self.renew_send_timeout()
print '-->%s<--' % received
# pass received data to owner
if self.on_receive:
self.raise_event(DATA_RECEIVED, received)
@ -732,7 +738,7 @@ class NBHTTPProxySocket(NBProxySocket):
return
if len(reply) != 2:
pass
NonBlockingT._on_connect(self)
NonBlockingTCP._on_connect(self)
#self.onreceive(self._on_proxy_auth)
def _on_proxy_auth(self, reply):