From 2b4c6b67a8e60bb87af8e3d9d6435ce0bbd8dbea Mon Sep 17 00:00:00 2001
From: Atheros1 <git@jonwarren.org>
Date: Mon, 26 Nov 2012 14:18:52 -0500
Subject: [PATCH] fixed potential attack vector (attaching a bad version
 message as message ack data)

---
 bitmessagemain.py | 34 ++++++----------------------------
 1 file changed, 6 insertions(+), 28 deletions(-)

diff --git a/bitmessagemain.py b/bitmessagemain.py
index 19a9900c..f992e31f 100644
--- a/bitmessagemain.py
+++ b/bitmessagemain.py
@@ -647,7 +647,7 @@ class receiveDataThread(QThread):
                         sqlReturnQueue.get()
                         sqlLock.release()
 
-                        blockMessage = False #Set to True if the user shouldn't see the message according to black or white lists.
+                        blockMessage = False #Gets set to True if the user shouldn't see the message according to black or white lists.
                         fromAddress = encodeAddress(sendersAddressVersionNumber,sendersStreamNumber,ripe.digest())
                         if config.get('bitmessagesettings', 'blackwhitelist') == 'black':
                             t = (fromAddress,) 
@@ -790,15 +790,6 @@ class receiveDataThread(QThread):
             return
 
         #We must check to make sure the proof of work is sufficient.
-        #POW, = unpack('>Q',hashlib.sha512(hashlib.sha512(self.data[24:24+self.payloadLength]).digest()).digest()[4:12])
-        #print 'POW:', POW
-        #if POW > 2**64 / ((self.payloadLength+payloadLengthExtraBytes) * averageProofOfWorkNonceTrialsPerByte):
-        #    printLock.acquire()
-        #    print 'The Proof of Work in the pubkey message is insufficient. Ignoring it.'
-        #    print 'pubkey payload length:', len(self.data[24:self.payloadLength+24])
-        #    print repr(self.data[24:self.payloadLength+24])
-        #    printLock.release()
-        #    return
         if not self.isProofOfWorkSufficient():
             print 'Proof of work in pubkey message insufficient.'
             return
@@ -1022,7 +1013,6 @@ class receiveDataThread(QThread):
                     if queryreturn <> []:
                         for row in queryreturn:
                             objectType, payload = row
-                        print 'Sending data out of inventory that came from sql.' #todo: remove line
                         self.sendData(objectType,payload)
                     else:
                         print 'Someone asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. That shouldn\'t have happened.'
@@ -1256,9 +1246,9 @@ class receiveDataThread(QThread):
     #We have received a version message
     def recversion(self):
         if self.payloadLength < 83:
-            self.data = ''
+            #This version message is unreasonably short. Forget it.
             return
-        else:
+        elif not self.verackSent: #There is a potential exploit if we don't check to make sure that we have not already received and accepted a version message: An attacker could connect directly to us, send a msg message with the ackdata set to an invalid version message which would cause us to close the connection to the attacker thus proving that we were able to decode the message. Checking the connectionIsOrWasFullyEstablished variable would also suffice.
             self.remoteProtocolVersion, = unpack('>L',self.data[24:28])
             #print 'remoteProtocolVersion', self.remoteProtocolVersion
             self.myExternalIP = socket.inet_ntoa(self.data[64:68])
@@ -1308,18 +1298,6 @@ class receiveDataThread(QThread):
             self.sendverack()
             if self.initiatedConnection == False:
                 self.sendversion()
-            '''#Now that we have a friendly connection with this peer, we should advertise it to our other peers
-            payload = '\x01'
-            payload +=  pack('>I',int(time.time()))
-            payload += pack('>I',self.streamNumber)
-            payload += pack('>q',1) #service bit flags offered by this node
-            payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + socket.inet_aton(self.HOST)
-            payload += pack('>H',self.remoteNodeIncomingPort)#remote port
-            datatosend = '\xE9\xBE\xB4\xD9addr\x00\x00\x00\x00\x00\x00\x00\x00'
-            datatosend += pack('>L',len(payload)) #payload length
-            datatosend += hashlib.sha512(payload).digest()[0:4]
-            datatosend += payload
-            broadcastToSendDataQueues((self.streamNumber, 'send', datatosend))'''
 
     #Sends a version message
     def sendversion(self):
@@ -1449,9 +1427,9 @@ class sendDataThread(QThread):
                         self.streamNumber = specifiedStreamNumber
                 elif command == 'send':
                     try:
-                        #To prevent some network analysis, 'leak' the data out to our peer after waiting a sort random amount of time.
+                        #To prevent some network analysis, 'leak' the data out to our peer after waiting a random amount of time.
                         random.seed()
-                        #time.sleep(random.randrange(0, 5)) todo: uncomment this line.
+                        time.sleep(random.randrange(0, 5)) 
                         self.sock.sendall(data)
                         self.lastTimeISentData = int(time.time())
                     except:
@@ -1845,7 +1823,7 @@ class singleWorker(QThread):
             payload += messageToTransmit
 
             #Later, if anyone impliments clients that don't send the ack_data, then we should probably check here to make sure that the receiver will make use of this ack_data and not attach it if not.
-            fullAckPayload = self.generateFullAckMessage(ackdata,fromStreamNumber)
+            fullAckPayload = self.generateFullAckMessage(ackdata,toStreamNumber)
             payload += encodeVarint(len(fullAckPayload))
             payload += fullAckPayload
             sendersPrivKey = rsa.PrivateKey(config.getint(fromaddress, 'n'),config.getint(fromaddress, 'e'),config.getint(fromaddress, 'd'),config.getint(fromaddress, 'p'),config.getint(fromaddress, 'q'))