From c7fb9e6a4359b8ea4fca53eb5bd43da306de5478 Mon Sep 17 00:00:00 2001 From: mailchuck Date: Fri, 13 Nov 2015 17:01:09 +0100 Subject: [PATCH] SSL fixes - uses constants for service flags - requires SSL to use TLSv1 version (protection against POODLE-style attacks) - retry if sock.recv incomplete --- src/class_receiveDataThread.py | 10 +++++----- src/class_sendDataThread.py | 2 +- src/shared.py | 6 +++++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/class_receiveDataThread.py b/src/class_receiveDataThread.py index 737872d1..059bce87 100644 --- a/src/class_receiveDataThread.py +++ b/src/class_receiveDataThread.py @@ -81,7 +81,7 @@ class receiveDataThread(threading.Thread): shared.numberOfBytesReceivedLastSecond = 0 dataLen = len(self.data) try: - if (self.services & 2 == 2) and self.connectionIsOrWasFullyEstablished: + if (self.services & shared.NODE_SSL == shared.NODE_SSL) and self.connectionIsOrWasFullyEstablished: dataRecv = self.sslSock.recv(1024) else: dataRecv = self.sock.recv(1024) @@ -93,11 +93,11 @@ class receiveDataThread(threading.Thread): print 'Timeout occurred waiting for data from', self.peer, '. Closing receiveData thread. (ID:', str(id(self)) + ')' break except Exception as err: - if (sys.platform == 'win32' and err.errno == 10035) or (sys.platform != 'win32' and err.errno == errno.EWOULDBLOCK): + if (sys.platform == 'win32' and err.errno in ([2, 10035])) or (sys.platform != 'win32' and err.errno == errno.EWOULDBLOCK): select.select([self.sslSock], [], []) continue with shared.printLock: - print 'sock.recv error. Closing receiveData thread (' + str(self.peer) + ', Thread ID:', str(id(self)) + ').', err + print 'sock.recv error. Closing receiveData thread (' + str(self.peer) + ', Thread ID:', str(id(self)) + ').', str(err.errno), "/", err break # print 'Received', repr(self.data) if len(self.data) == dataLen: # If self.sock.recv returned no data: @@ -265,8 +265,8 @@ class receiveDataThread(threading.Thread): self.connectionIsOrWasFullyEstablished = True self.sslSock = self.sock - if (self.services & 2 == 2): - self.sslSock = ssl.wrap_socket(self.sock, keyfile = os.path.join(shared.codePath(), 'sslkeys', 'key.pem'), certfile = os.path.join(shared.codePath(), 'sslkeys', 'cert.pem'), server_side = not self.initiatedConnection, ssl_version=ssl.PROTOCOL_SSLv23, do_handshake_on_connect=False, ciphers='AECDH-AES256-SHA') + if (self.services & shared.NODE_SSL == shared.NODE_SSL): + self.sslSock = ssl.wrap_socket(self.sock, keyfile = os.path.join(shared.codePath(), 'sslkeys', 'key.pem'), certfile = os.path.join(shared.codePath(), 'sslkeys', 'cert.pem'), server_side = not self.initiatedConnection, ssl_version=ssl.PROTOCOL_TLSv1, do_handshake_on_connect=False, ciphers='AECDH-AES256-SHA') while True: try: self.sslSock.do_handshake() diff --git a/src/class_sendDataThread.py b/src/class_sendDataThread.py index fedd4833..4ee88399 100644 --- a/src/class_sendDataThread.py +++ b/src/class_sendDataThread.py @@ -83,7 +83,7 @@ class sendDataThread(threading.Thread): uploadRateLimitBytes = 999999999 # float("inf") doesn't work else: uploadRateLimitBytes = shared.config.getint('bitmessagesettings', 'maxuploadrate') * 1000 - if self.services & 2 == 2 and self.connectionIsOrWasFullyEstablished: + if self.services & shared.NODE_SSL == shared.NODE_SSL and self.connectionIsOrWasFullyEstablished: amountSent = self.sslSock.send(data[:1000]) else: amountSent = self.sock.send(data[:1000]) diff --git a/src/shared.py b/src/shared.py index 0b5f0c01..6f6d5a1c 100644 --- a/src/shared.py +++ b/src/shared.py @@ -120,6 +120,10 @@ trustedPeer = None #New code should use CreatePacket instead of Header.pack Header = Struct('!L12sL4s') +#Service flags +NODE_NETWORK = 1 +NODE_SSL = 2 + #Create a packet def CreatePacket(command, payload=''): payload_length = len(payload) @@ -144,7 +148,7 @@ def encodeHost(host): def assembleVersionMessage(remoteHost, remotePort, myStreamNumber): payload = '' payload += pack('>L', 3) # protocol version. - payload += pack('>q', 3) # bitflags of the services I offer. + payload += pack('>q', NODE_NETWORK|NODE_SSL) # bitflags of the services I offer. payload += pack('>q', int(time.time())) payload += pack(