- PyOpenSSL branch merged to trunk

Welcome to the world of PyOpenSSL! Please install PyOpenSSL, thanks!

svn merge -r 7426:HEAD svn://svn.gajim.org/gajim/branches/pyopenssl
This commit is contained in:
junglecow 2006-12-20 21:52:40 +00:00
commit 62350adb36
5 changed files with 409 additions and 47 deletions

View File

@ -123,8 +123,12 @@ class NBCommonClient(CommonClient):
self.on_connect_failure(retry) self.on_connect_failure(retry)
def _on_connected(self): def _on_connected(self):
# connect succeded, so no need of this callback anymore # FIXME: why was this needed? Please note that we're working
self.on_connect_failure = None # in nonblocking mode, and this handler is actually called
# as soon as connection is initiated, NOT when connection
# succeeds, as the name suggests.
# # connect succeeded, so no need of this callback anymore
# self.on_connect_failure = None
self.connected = 'tcp' self.connected = 'tcp'
if self._Ssl: if self._Ssl:
transports_nb.NonBlockingTLS().PlugIn(self, now=1) transports_nb.NonBlockingTLS().PlugIn(self, now=1)

View File

@ -135,7 +135,6 @@ class Dispatcher(PlugIn):
self._owner.Connection.disconnect() self._owner.Connection.disconnect()
return 0 return 0
except ExpatError: except ExpatError:
sys.exc_clear()
self.DEBUG('Invalid XML received from server. Forcing disconnect.', 'error') self.DEBUG('Invalid XML received from server. Forcing disconnect.', 'error')
self._owner.Connection.pollend() self._owner.Connection.pollend()
return 0 return 0

View File

@ -24,6 +24,34 @@ from transports import *
import sys import sys
import os import os
import errno import errno
import time
import traceback
import thread
import logging
h = logging.StreamHandler()
f = logging.Formatter('%(asctime)s %(name)s: %(levelname)s: %(message)s')
h.setFormatter(f)
log = logging.getLogger('Gajim.transports')
log.addHandler(h)
log.setLevel(logging.DEBUG)
log.propagate = False
del h, f
USE_PYOPENSSL = False
try:
#raise ImportError("Manually disabled PyOpenSSL")
import OpenSSL.SSL
import OpenSSL.crypto
USE_PYOPENSSL = True
log.info("PyOpenSSL loaded")
except ImportError:
# FIXME: Remove these prints before release, replace with a warning dialog.
print >> sys.stderr, "=" * 79
print >> sys.stderr, "PyOpenSSL not found, falling back to Python builtin SSL objects (insecure)."
print >> sys.stderr, "=" * 79
# timeout to connect to the server socket, it doesn't include auth # timeout to connect to the server socket, it doesn't include auth
CONNECT_TIMEOUT_SECONDS = 30 CONNECT_TIMEOUT_SECONDS = 30
@ -33,7 +61,178 @@ DISCONNECT_TIMEOUT_SECONDS = 10
# size of the buffer which reads data from server # size of the buffer which reads data from server
# if lower, more stanzas will be fragmented and processed twice # if lower, more stanzas will be fragmented and processed twice
RECV_BUFSIZE = 1048576 RECV_BUFSIZE = 32768 # 2x maximum size of ssl packet, should be plenty
#RECV_BUFSIZE = 16 # FIXME: (#2634) gajim breaks with this setting: it's inefficient but should work.
def torf(cond, tv, fv):
if cond: return tv
return fv
def gattr(obj, attr, default=None):
try:
return getattr(obj, attr)
except:
return default
class SSLWrapper:
class Error(IOError):
def __init__(self, sock=None, exc=None, errno=None, strerror=None, peer=None):
self.parent = IOError
errno = errno or gattr(exc, 'errno')
strerror = strerror or gattr(exc, 'strerror') or gattr(exc, 'args')
if not isinstance(strerror, basestring): strerror = repr(strerror)
self.sock = sock
self.exc = exc
self.peer = peer
self.exc_name = None
self.exc_args = None
self.exc_str = None
self.exc_repr = None
if self.exc is not None:
self.exc_name = str(self.exc.__class__)
self.exc_args = gattr(self.exc, 'args')
self.exc_str = str(self.exc)
self.exc_repr = repr(self.exc)
if not errno:
try:
if isinstance(exc, OpenSSL.SSL.SysCallError):
if self.exc_args[0] > 0:
errno = self.exc_args[0]
strerror = self.exc_args[1]
except: pass
self.parent.__init__(self, errno, strerror)
if self.peer is None and sock is not None:
try:
ppeer = self.sock.getpeername()
if len(ppeer) == 2 and isinstance(ppeer[0], basestring) \
and isinstance(ppeer[1], int):
self.peer = ppeer
except: pass
def __str__(self):
s = str(self.__class__)
if self.peer: s += " for %s:%d" % self.peer
if self.errno is not None: s += ": [Errno: %d]" % self.errno
if self.strerror: s += " (%s)" % self.strerror
if self.exc_name:
s += ", Caused by %s" % self.exc_name
if self.exc_str:
if self.strerror: s += "(%s)" % self.exc_str
else: s += "(%s)" % str(self.exc_args)
return s
def __init__(self, sslobj, sock=None):
self.sslobj = sslobj
self.sock = sock
log.debug("%s.__init__ called with %s", self.__class__, sslobj)
def recv(self, data, flags=None):
""" Receive wrapper for SSL object
We can return None out of this function to signal that no data is
available right now. Better than an exception, which differs
depending on which SSL lib we're using. Unfortunately returning ''
can indicate that the socket has been closed, so to be sure, we avoid
this by returning None. """
raise NotImplementedException()
def send(self, data, flags=None):
raise NotImplementedException()
class PyOpenSSLWrapper(SSLWrapper):
'''Wrapper class for PyOpenSSL's recv() and send() methods'''
def __init__(self, *args):
self.parent = SSLWrapper
self.parent.__init__(self, *args)
def is_numtoolarge(self, e):
t = ('asn1 encoding routines', 'a2d_ASN1_OBJECT', 'first num too large')
return isinstance(e.args, (list, tuple)) and len(e.args) == 1 and \
isinstance(e.args[0], (list, tuple)) and len(e.args[0]) == 2 and \
e.args[0][0] == e.args[0][1] == t
def recv(self, bufsize, flags=None):
retval = None
try:
if flags is None: retval = self.sslobj.recv(bufsize)
else: retval = self.sslobj.recv(bufsize, flags)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
pass
# log.debug("Recv: " + repr(e))
except OpenSSL.SSL.SysCallError, e:
log.error("Recv: Got OpenSSL.SSL.SysCallError: " + repr(e), exc_info=True)
#traceback.print_exc()
raise SSLWrapper.Error(self.sock or self.sslobj, e)
except OpenSSL.SSL.Error, e:
if self.is_numtoolarge(e):
# warn, but ignore this exception
log.warning("Recv: OpenSSL: asn1enc: first num too large (ignored)")
else:
log.error("Recv: Caught OpenSSL.SSL.Error:", exc_info=True)
#traceback.print_exc()
#print "Current Stack:"
#traceback.print_stack()
raise SSLWrapper.Error(self.sock or self.sslobj, e)
return retval
def send(self, data, flags=None):
try:
if flags is None: return self.sslobj.send(data)
else: return self.sslobj.send(data, flags)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
#log.debug("Send: " + repr(e))
time.sleep(0.1) # prevent 100% CPU usage
except OpenSSL.SSL.SysCallError, e:
log.error("Send: Got OpenSSL.SSL.SysCallError: " + repr(e), exc_info=True)
#traceback.print_exc()
raise SSLWrapper.Error(self.sock or self.sslobj, e)
except OpenSSL.SSL.Error, e:
if self.is_numtoolarge(e):
# warn, but ignore this exception
log.warning("Send: OpenSSL: asn1enc: first num too large (ignored)")
else:
log.error("Send: Caught OpenSSL.SSL.Error:", exc_info=True)
#traceback.print_exc()
#print "Current Stack:"
#traceback.print_stack()
raise SSLWrapper.Error(self.sock or self.sslobj, e)
return 0
class StdlibSSLWrapper(SSLWrapper):
'''Wrapper class for Python's socket.ssl read() and write() methods'''
def __init__(self, *args):
self.parent = SSLWrapper
self.parent.__init__(self, *args)
def recv(self, bufsize, flags=None):
# we simply ignore flags since ssl object doesn't support it
try:
return self.sslobj.read(bufsize)
except socket.sslerror, e:
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):
raise SSLWrapper.Error(self.sock or self.sslobj, e)
return None
def send(self, data, flags=None):
# we simply ignore flags since ssl object doesn't support it
try:
return self.sslobj.write(data)
except socket.sslerror, e:
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):
raise SSLWrapper.Error(self.sock or self.sslobj, e)
return 0
class NonBlockingTcp(PlugIn, IdleObject): class NonBlockingTcp(PlugIn, IdleObject):
''' This class can be used instead of transports.Tcp in threadless implementations ''' ''' This class can be used instead of transports.Tcp in threadless implementations '''
@ -53,6 +252,7 @@ class NonBlockingTcp(PlugIn, IdleObject):
self.on_connect_failure = on_connect_failure self.on_connect_failure = on_connect_failure
self.on_receive = None self.on_receive = None
self.on_disconnect = None self.on_disconnect = None
self.printed_error = False
# 0 - not connected # 0 - not connected
# 1 - connected # 1 - connected
@ -82,6 +282,7 @@ class NonBlockingTcp(PlugIn, IdleObject):
Also registers self.disconnected method in the owner's dispatcher. Also registers self.disconnected method in the owner's dispatcher.
Called internally. ''' Called internally. '''
self.idlequeue = owner.idlequeue self.idlequeue = owner.idlequeue
self.printed_error = False
if not self._server: if not self._server:
self._server=(self._owner.Server,5222) self._server=(self._owner.Server,5222)
if self.connect(self._server) is False: if self.connect(self._server) is False:
@ -104,6 +305,7 @@ class NonBlockingTcp(PlugIn, IdleObject):
server=self._server server=self._server
else: else:
self._server = server self._server = server
self.printed_error = False
self.state = 0 self.state = 0
try: try:
for ai in socket.getaddrinfo(server[0],server[1],socket.AF_UNSPEC,socket.SOCK_STREAM): for ai in socket.getaddrinfo(server[0],server[1],socket.AF_UNSPEC,socket.SOCK_STREAM):
@ -118,7 +320,8 @@ class NonBlockingTcp(PlugIn, IdleObject):
#for all errors, we try other addresses #for all errors, we try other addresses
continue continue
except: except:
sys.exc_clear() log.error("Exception trying to connect to %s:", self.getName(), exc_info=True)
#traceback.print_exc()
if self.on_connect_failure: if self.on_connect_failure:
self.on_connect_failure() self.on_connect_failure()
return False return False
@ -152,7 +355,11 @@ class NonBlockingTcp(PlugIn, IdleObject):
def pollin(self): def pollin(self):
self._do_receive() self._do_receive()
def pollend(self, retry = False): def pollend(self, retry=False):
if not self.printed_error:
self.printed_error = True
try: self._do_receive(errors_only=True)
except: log.error("pollend: Got exception from _do_receive:", exc_info=True)
conn_failure_cb = self.on_connect_failure conn_failure_cb = self.on_connect_failure
self.disconnect() self.disconnect()
if conn_failure_cb: if conn_failure_cb:
@ -168,10 +375,11 @@ class NonBlockingTcp(PlugIn, IdleObject):
self.idlequeue.unplug_idle(self.fd) self.idlequeue.unplug_idle(self.fd)
try: try:
self._sock.shutdown(socket.SHUT_RDWR) self._sock.shutdown(socket.SHUT_RDWR)
self._sock.close() except socket.error, e:
except: if e[0] != errno.ENOTCONN:
# socket is already closed log.error("Error shutting down socket for %s:", self.getName(), exc_info=True)
sys.exc_clear() try: self._sock.close()
except: log.error("Error closing socket for %s:", self.getName(), exc_info=True)
# socket descriptor cannot be (un)plugged anymore # socket descriptor cannot be (un)plugged anymore
self.fd = -1 self.fd = -1
if self.on_disconnect: if self.on_disconnect:
@ -211,38 +419,60 @@ class NonBlockingTcp(PlugIn, IdleObject):
if not recv_handler(None) and _tmp == self.on_receive: if not recv_handler(None) and _tmp == self.on_receive:
self.on_receive = recv_handler self.on_receive = recv_handler
def _do_receive(self): def _do_receive(self, errors_only=False):
''' Reads all pending incoming data. Calls owner's disconnected() method if appropriate.''' ''' Reads all pending incoming data. Calls owner's disconnected() method if appropriate.'''
received = '' ERR_DISCONN = -2 # Misc error signifying that we got disconnected
ERR_OTHER = -1 # Other error
received = None
errnum = 0 errnum = 0
errtxt = 'No Error Set'
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 Exception, e: except (socket.error, socket.herror, socket.gaierror), e:
if len(e.args) > 0 and isinstance(e.args[0], int): log.error("_do_receive: got %s:", e.__class__, exc_info=True)
#traceback.print_exc()
#print "Current Stack:"
#traceback.print_stack()
errnum = e[0] errnum = e[0]
sys.exc_clear() errtxt = str(errnum) + ':' + e[1]
# "received" will be empty anyhow except socket.sslerror, e:
if errnum == socket.SSL_ERROR_WANT_READ: log.error("_do_receive: got unknown %s:", e.__class__, exc_info=True)
pass #traceback.print_exc()
elif errnum == errno.ECONNRESET: #print "Current Stack:"
self.pollend(True) #traceback.print_stack()
# don't proccess result, caus it will raise error errnum = ERR_OTHER
return errtxt = repr("socket.sslerror: " + e.args)
elif errnum in [errno.ENOTCONN, errno.ESHUTDOWN]: except SSLWrapper.Error, e:
self.pollend() log.debug("Caught: %s", str(e))
# don't proccess result, caus it will raise error errnum = gattr(e, 'errno', ERR_OTHER)
return if not errnum: errnum = ERR_OTHER # unset, but we must put a status
elif not received : errtxt = gattr(e, 'strerror') or repr(e.args)
if errnum != socket.SSL_ERROR_EOF:
# 8 EOF occurred in violation of protocol if received == '':
self.DEBUG('Socket error while receiving data', 'error') errnum = ERR_DISCONN
self.pollend(True) errtxt = "Connection closed unexpectedly"
if self.state >= 0:
self.disconnect() if errnum in (ERR_DISCONN, errno.ECONNRESET, errno.ENOTCONN, errno.ESHUTDOWN):
self.DEBUG(errtxt, 'error')
log.error("Connection to %s lost: %s [%d]", self.getName(), errtxt, errnum)
self.printed_error = True
if not errors_only:
self.pollend(retry=(errnum in (ERR_DISCONN, errno.ECONNRESET)))
# don't process result, because it will raise an error
return return
if self.state < 0: if received is None:
if errnum != 0:
self.DEBUG(errtxt, 'error')
log.error("Connection to %s lost: %s [%d]", self.getName(), errtxt, errnum)
self.printed_error = True
if not errors_only and self.state >= 0:
self.pollend(retry=True)
return
received = ''
if errors_only or self.state < 0:
return return
# we have received some bites, stop the timeout! # we have received some bites, stop the timeout!
@ -281,9 +511,10 @@ class NonBlockingTcp(PlugIn, IdleObject):
self._plug_idle() self._plug_idle()
self._on_send() self._on_send()
except socket.error, e: except socket.error, e:
sys.exc_clear()
if e[0] == socket.SSL_ERROR_WANT_WRITE: if e[0] == socket.SSL_ERROR_WANT_WRITE:
return True return True
log.error("_do_send:", exc_info=True)
#traceback.print_exc()
if self.state < 0: if self.state < 0:
self.disconnect() self.disconnect()
return return
@ -296,12 +527,16 @@ class NonBlockingTcp(PlugIn, IdleObject):
if self.state != 0: if self.state != 0:
return return
self._sock.setblocking(False) self._sock.setblocking(False)
self._send = self._sock.send
self._recv = self._sock.recv
errnum = 0 errnum = 0
try: try:
self._sock.connect(self._server) self._sock.connect(self._server)
except socket.error, e: except socket.error, e:
errnum = e[0] errnum = e[0]
sys.exc_clear() if errnum != errno.EINPROGRESS:
log.error("_do_connect:", exc_info=True)
#traceback.print_exc()
# in progress, or would block # in progress, or would block
if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK): if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
return return
@ -317,8 +552,6 @@ class NonBlockingTcp(PlugIn, IdleObject):
self.state = 1 self.state = 1
self._sock.setblocking(False) self._sock.setblocking(False)
self._send = self._sock.send
self._recv = self._sock.recv
self._plug_idle() self._plug_idle()
if self.on_connect: if self.on_connect:
self.on_connect() self.on_connect()
@ -368,12 +601,27 @@ class NonBlockingTcp(PlugIn, IdleObject):
''' Return the 'host' value that is connection is [will be] made to.''' ''' Return the 'host' value that is connection is [will be] made to.'''
return self._server[0] return self._server[0]
def getName(self):
''' Return the server's name, or 'getHost()' if not available.'''
retval = None
retval = gattr(self._owner, 'name')
if retval: return retval
return self.getHost()
def getPort(self): def getPort(self):
''' Return the 'port' value that is connection is [will be] made to.''' ''' Return the 'port' value that is connection is [will be] made to.'''
return self._server[1] return self._server[1]
class NonBlockingTLS(PlugIn): class NonBlockingTLS(PlugIn):
''' TLS connection used to encrypts already estabilished tcp connection.''' ''' TLS connection used to encrypts already estabilished tcp connection.'''
# from ssl.h (partial extract)
ssl_h_bits = { "SSL_ST_CONNECT": 0x1000, "SSL_ST_ACCEPT": 0x2000,
"SSL_CB_LOOP": 0x01, "SSL_CB_EXIT": 0x02,
"SSL_CB_READ": 0x04, "SSL_CB_WRITE": 0x08,
"SSL_CB_ALERT": 0x4000,
"SSL_CB_HANDSHAKE_START": 0x10, "SSL_CB_HANDSHAKE_DONE": 0x20}
def PlugIn(self, owner, now=0, on_tls_start = None): def PlugIn(self, owner, now=0, on_tls_start = None):
''' If the 'now' argument is true then starts using encryption immidiatedly. ''' If the 'now' argument is true then starts using encryption immidiatedly.
If 'now' in false then starts encryption as soon as TLS feature is If 'now' in false then starts encryption as soon as TLS feature is
@ -388,6 +636,8 @@ class NonBlockingTLS(PlugIn):
try: try:
res = self._startSSL() res = self._startSSL()
except Exception, e: except Exception, e:
log.error("PlugIn: while trying _startSSL():", exc_info=True)
#traceback.print_exc()
self._owner.socket.pollend() self._owner.socket.pollend()
return return
self.tls_start() self.tls_start()
@ -429,18 +679,126 @@ class NonBlockingTLS(PlugIn):
self.tls_start() self.tls_start()
raise NodeProcessed raise NodeProcessed
def _dumpX509(self, cert, stream=sys.stderr):
print >> stream, "Digest (SHA-1):", cert.digest("sha1")
print >> stream, "Digest (MD5):", cert.digest("md5")
print >> stream, "Serial #:", cert.get_serial_number()
print >> stream, "Version:", cert.get_version()
print >> stream, "Expired:", torf(cert.has_expired(), "Yes", "No")
print >> stream, "Subject:"
self._dumpX509Name(cert.get_subject(), stream)
print >> stream, "Issuer:"
self._dumpX509Name(cert.get_issuer(), stream)
self._dumpPKey(cert.get_pubkey(), stream)
def _dumpX509Name(self, name, stream=sys.stderr):
print >> stream, "X509Name:", str(name)
def _dumpPKey(self, pkey, stream=sys.stderr):
typedict = {OpenSSL.crypto.TYPE_RSA: "RSA", OpenSSL.crypto.TYPE_DSA: "DSA"}
print >> stream, "PKey bits:", pkey.bits()
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.''' ''' Immidiatedly switch socket to TLS mode. Used internally.'''
log.debug("_startSSL called")
if USE_PYOPENSSL: return self._startSSL_pyOpenSSL()
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.Connection
# FIXME: should method be configurable?
#tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
tcpsock._sslContext.set_info_callback(self._ssl_info_callback)
tcpsock._sslObj = OpenSSL.SSL.Connection(tcpsock._sslContext, tcpsock._sock)
tcpsock._sslObj.set_connect_state() # set to client mode
wrapper = PyOpenSSLWrapper(tcpsock._sslObj)
tcpsock._recv = wrapper.recv
tcpsock._send = wrapper.send
log.debug("Initiating handshake...")
#tcpsock._sslObj.setblocking(True)
try:
self.starttls='in progress'
tcpsock._sslObj.do_handshake()
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
pass
#tcpsock._sslObj.setblocking(False)
#print "Done handshake"
log.debug("Async handshake started...")
# fake it, for now
self.starttls='success'
def _on_ssl_handshake_done(self):
log.debug("Handshake done!")
#self.starttls='success'
tcpsock = self._owner.Connection
cert = tcpsock._sslObj.get_peer_certificate()
peer = cert.get_subject()
issuer = cert.get_issuer()
tcpsock._sslIssuer = unicode(issuer)
tcpsock._sslServer = unicode(peer)
# FIXME: remove debug prints
peercert = tcpsock._sslObj.get_peer_certificate()
ciphers = tcpsock._sslObj.get_cipher_list()
print >> sys.stderr, "Ciphers:", ciphers
print >> sys.stderr, "Peer cert:", peercert
self._dumpX509(peercert)
print >> sys.stderr, OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, peercert)
def _startSSL_stdlib(self):
log.debug("_startSSL_stdlib called")
tcpsock=self._owner.Connection tcpsock=self._owner.Connection
tcpsock._sock.setblocking(True) tcpsock._sock.setblocking(True)
tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None) tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None)
tcpsock._sock.setblocking(False) tcpsock._sock.setblocking(False)
tcpsock._sslIssuer = tcpsock._sslObj.issuer() tcpsock._sslIssuer = tcpsock._sslObj.issuer()
tcpsock._sslServer = tcpsock._sslObj.server() tcpsock._sslServer = tcpsock._sslObj.server()
tcpsock._recv = tcpsock._sslObj.read wrapper = StdlibSSLWrapper(tcpsock._sslObj, tcpsock._sock)
tcpsock._send = tcpsock._sslObj.write tcpsock._recv = wrapper.recv
tcpsock._send = wrapper.send
self.starttls='success' self.starttls='success'
def _ssl_info_callback(self, sslconn, type, st):
# Exceptions can't propagate up through this callback, so print them here.
try:
self._ssl_info_callback_guarded(sslconn, type, st)
except:
log.error("Exception caught in _ssl_info_callback:", exc_info=True)
traceback.print_exc() # Make sure something is printed, even if log is disabled.
def _ssl_info_callback_guarded(self, sslconn, type, st):
b = self.ssl_h_bits
#if type & b['SSL_CB_LOOP']:
# if type & SSL_ST_CONNECT: tls_state = "connect"
# elif type & SSL_ST_ACCEPT: tls_state = "accept"
# else: tls_state = "undefined"
# print "tls_state: %s: %s" % (tls_state, sslconn.state_string())
#if type & b['SSL_CB_ALERT']:
# if type & SSL_CB_READ: rdwr = "read"
# elif type & SSL_CB_WRITE: rdwr = "write"
# else: rdwr = "unknown"
# print "tls_alert: %s:%d: %s" % (rdwr, st, sslconn.state_string())
#mask = ""
#for k, v in b.iteritems():
# if type & v: mask += " " + k
#print "mask:", mask, st
if type & b['SSL_CB_HANDSHAKE_DONE']:
self._on_ssl_handshake_done()
def StartTLSHandler(self, conn, starttls): def StartTLSHandler(self, conn, starttls):
''' Handle server reply if TLS is allowed to process. Behaves accordingly. ''' Handle server reply if TLS is allowed to process. Behaves accordingly.
Used internally.''' Used internally.'''
@ -454,6 +812,8 @@ class NonBlockingTLS(PlugIn):
try: try:
self._startSSL() self._startSSL()
except Exception, e: except Exception, e:
log.error("StartTLSHandler:", exc_info=True)
#traceback.print_exc()
self._owner.socket.pollend() self._owner.socket.pollend()
return return
self._owner.Dispatcher.PlugOut() self._owner.Dispatcher.PlugOut()
@ -512,6 +872,8 @@ class NBHTTPPROXYsocket(NonBlockingTcp):
try: try:
proto, code, desc = reply.split('\n')[0].split(' ', 2) proto, code, desc = reply.split('\n')[0].split(' ', 2)
except: except:
log.error("_on_headers_sent:", exc_info=True)
#traceback.print_exc()
raise error('Invalid proxy reply') raise error('Invalid proxy reply')
if code <> '200': if code <> '200':
self.DEBUG('Invalid proxy reply: %s %s %s' % (proto, code, desc),'error') self.DEBUG('Invalid proxy reply: %s %s %s' % (proto, code, desc),'error')

View File

@ -376,7 +376,6 @@ class P2PConnection(IdleObject, PlugIn):
except Exception, e: except Exception, e:
if len(e.args) > 0 and isinstance(e.args[0], int): if len(e.args) > 0 and isinstance(e.args[0], int):
errnum = e[0] errnum = e[0]
sys.exc_clear()
# "received" will be empty anyhow # "received" will be empty anyhow
if errnum == socket.SSL_ERROR_WANT_READ: if errnum == socket.SSL_ERROR_WANT_READ:
pass pass
@ -456,7 +455,6 @@ class P2PConnection(IdleObject, PlugIn):
self._on_send() self._on_send()
except socket.error, e: except socket.error, e:
sys.exc_clear()
if e[0] == socket.SSL_ERROR_WANT_WRITE: if e[0] == socket.SSL_ERROR_WANT_WRITE:
return True return True
if self.state < 0: if self.state < 0:

View File

@ -27,7 +27,6 @@ from common import i18n
try: try:
PREFERRED_ENCODING = locale.getpreferredencoding() PREFERRED_ENCODING = locale.getpreferredencoding()
except: except:
sys.exc_clear()
PREFERRED_ENCODING = 'UTF-8' PREFERRED_ENCODING = 'UTF-8'
def send_error(error_message): def send_error(error_message):