fixed handling of SSL errors
This commit is contained in:
		
							parent
							
								
									cbfa9d97df
								
							
						
					
					
						commit
						4504861084
					
				
					 7 changed files with 50 additions and 46 deletions
				
			
		|  | @ -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'] | ||||
|  |  | |||
|  | @ -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 = { | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
|  | @ -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.''' | ||||
|  |  | |||
|  | @ -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? | ||||
|  |  | |||
|  | @ -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): | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue