def handle_bank_relay(self, msg):
   """Send a message to the bank on behalf of someone else, then send the reply onward
   @param msg:  the message to relay
   @type  msg:  str"""
   version, msg = Basic.read_byte(msg)
   assert version == 1, "only accepts version 1 of PAR protocol"
   responseHop, msg = Basic.read_byte(msg)
   bankMsg, msg = Basic.read_lenstr(msg)
   responseMsg, msg = Basic.read_lenstr(msg)
   payment = UDPPayment.UDPPayment(self.bank, bankMsg)
   paymentDeferred = payment.get_deferred()
   def success(response, responseMsg=responseMsg, responseHop=responseHop):
     responseMsg += response
     if responseHop != 0:
       self.send_direct_tor_message(responseMsg, "payment", True, responseHop)
     else:
       self.handle_payment(responseMsg)
   paymentDeferred.addCallback(success)
   def failure(error):
     if error and hasattr(error, "value") and issubclass(type(error.value), TimeoutError):
       #TODO:  this indicates that the bank is down, or something is wrong with their network?
       log_msg("Relayed payment timed out  :(", 0, "par")
     else:
       log_ex(error, "Relaying payment message failed!")
   paymentDeferred.addErrback(failure)
Exemple #2
0
 def stringReceived(self, data):
     """Called when the login response arrives"""
     self.factory.done = True
     self.responseReceived = True
     text = None
     try:
         protocol, data = Basic.read_byte(data)
         if protocol == 1:
             returnCode, data = Basic.read_byte(data)
             if returnCode == 1:
                 format = '!IIII4sI'
                 (balance, currentACoinInterval,
                  currentACoinIntervalExpiration,
                  nextAcoinIntervalExpiration, host,
                  port), blob = Basic.read_message(format, data)
                 size = struct.calcsize(SymmetricKey.MESSAGE_FORMAT)
                 authBlob = blob[:size]
                 text = blob[size:]
                 host = socket.inet_ntoa(host)
                 self.factory.bank.on_new_info(
                     balance, currentACoinInterval,
                     currentACoinIntervalExpiration,
                     nextAcoinIntervalExpiration)
                 self.factory.bank.on_login_success(balance, authBlob, host,
                                                    port, text)
             else:
                 size = struct.calcsize('!I')
                 timeout = struct.unpack('!I', data[:size])[0]
                 text = data[size:]
                 raise BadLoginPasswordError(timeout)
         else:
             raise Exception('unknown protocol: %s' % (protocol))
     except Exception, error:
         self.factory.bank.on_login_failure(error, text)
Exemple #3
0
 def datagramReceived(self, datagram, address):
   try:
     self.address = address
     log_msg('Datagram received from %s:%s!'%address, 3)
     msgType, msg = Basic.read_byte(datagram)
     #for compatability really
     if msgType == 1:
       #is it a replay?
       if not cache.has_key(msg):
         self.request = msg
         self.symKey = EncryptedDatagram.ServerSymKey(Globals.GENERIC_KEY)
         msg = self.symKey.decrypt(msg)
         #for compatability really
         request_type, msg = Basic.read_byte(msg)
         if request_type == 3:
           self.handler = ACoinMessages.Payment(self.reply, self.address) 
           self.handler.on_message(msg)
         else:
           raise Exception("Unknown request_type:  %s" % (request_type))
       else:
         self.reply(cache[msg], putInQueue=False)
         return
     else:
       raise Exception("Unknown msgType:  %s" % (msgType))
   except Exception, e:
     self.err(e)
Exemple #4
0
 def stringReceived(self, data):
   """Called when the login response arrives"""
   self.factory.done = True
   self.responseReceived = True
   text = None
   try:
     protocol, data = Basic.read_byte(data)
     if protocol == 1:
       returnCode, data = Basic.read_byte(data)
       if returnCode == 1:
         format = '!IIII4sI'
         (balance, currentACoinInterval, currentACoinIntervalExpiration, nextAcoinIntervalExpiration, host, port), blob = Basic.read_message(format, data)
         size = struct.calcsize(SymmetricKey.MESSAGE_FORMAT)
         authBlob = blob[:size]
         text = blob[size:]
         host = socket.inet_ntoa(host)
         self.factory.bank.on_new_info(balance, currentACoinInterval, currentACoinIntervalExpiration, nextAcoinIntervalExpiration)
         self.factory.bank.on_login_success(balance, authBlob, host, port, text)
       else:
         size = struct.calcsize('!I')
         timeout = struct.unpack('!I', data[:size])[0]
         text = data[size:]
         raise BadLoginPasswordError(timeout)
     else:
       raise Exception('unknown protocol: %s'%(protocol))
   except Exception, error:
     self.factory.bank.on_login_failure(error, text)
Exemple #5
0
    def handle_bank_relay(self, msg):
        """Send a message to the bank on behalf of someone else, then send the reply onward
    @param msg:  the message to relay
    @type  msg:  str"""
        version, msg = Basic.read_byte(msg)
        assert version == 1, "only accepts version 1 of PAR protocol"
        responseHop, msg = Basic.read_byte(msg)
        bankMsg, msg = Basic.read_lenstr(msg)
        responseMsg, msg = Basic.read_lenstr(msg)
        payment = UDPPayment.UDPPayment(self.bank, bankMsg)
        paymentDeferred = payment.get_deferred()

        def success(response,
                    responseMsg=responseMsg,
                    responseHop=responseHop):
            responseMsg += response
            if responseHop != 0:
                self.send_direct_tor_message(responseMsg, "payment", True,
                                             responseHop)
            else:
                self.handle_payment(responseMsg)

        paymentDeferred.addCallback(success)

        def failure(error):
            if error and hasattr(error, "value") and issubclass(
                    type(error.value), TimeoutError):
                #TODO:  this indicates that the bank is down, or something is wrong with their network?
                log_msg("Relayed payment timed out  :(", 0, "par")
            else:
                log_ex(error, "Relaying payment message failed!")

        paymentDeferred.addErrback(failure)
Exemple #6
0
 def datagramReceived(self, datagram, address):
     try:
         self.address = address
         log_msg('Datagram received from %s:%s!' % address, 3)
         msgType, msg = Basic.read_byte(datagram)
         #for compatability really
         if msgType == 1:
             #is it a replay?
             if not cache.has_key(msg):
                 self.request = msg
                 self.symKey = EncryptedDatagram.ServerSymKey(
                     Globals.GENERIC_KEY)
                 msg = self.symKey.decrypt(msg)
                 #for compatability really
                 request_type, msg = Basic.read_byte(msg)
                 if request_type == 3:
                     self.handler = ACoinMessages.Payment(
                         self.reply, self.address)
                     self.handler.on_message(msg)
                 else:
                     raise Exception("Unknown request_type:  %s" %
                                     (request_type))
             else:
                 self.reply(cache[msg], putInQueue=False)
                 return
         else:
             raise Exception("Unknown msgType:  %s" % (msgType))
     except Exception, e:
         self.err(e)
Exemple #7
0
 def _read_header(self, data, msgName):
   #read the version
   version, data = Basic.read_byte(data)
   assert version == self.VERSION, "Bad version number: %s" % (version)
   #read the message type:
   msgType, data = Basic.read_byte(data)
   assert msgType == self.MESSAGES[msgName], "Bad message type: %s" % (msgType)
   return data
Exemple #8
0
 def _read_header(self, data, msgName):
     #read the version
     version, data = Basic.read_byte(data)
     assert version == self.VERSION, "Bad version number: %s" % (version)
     #read the message type:
     msgType, data = Basic.read_byte(data)
     assert msgType == self.MESSAGES[msgName], "Bad message type: %s" % (
         msgType)
     return data
Exemple #9
0
    def handle_dht_request(self, data):
        log_msg("Got remote DHT request", 4, "dht")
        #unpack and validate the message:
        version, data = Basic.read_byte(data)
        assert version == Node.VERSION
        #read the infohash:
        vals, data = Basic.read_message("20s", data)
        infohash = vals[0]
        #read each peer:
        peers = set()
        while len(data) > 0:
            #what type of peer?  (ip or url)
            peerType, data = Basic.read_byte(data)
            #IP peer:
            if peerType == 0:
                vals, data = Basic.read_message("!4sH", data)
                host = socket.inet_ntoa(vals[0])
                port = vals[1]
            #URL peer:
            elif peerType == 1:
                host, data = Basic.read_lenstr(data)
                port, data = Basic.read_short(data)
            #bad peer type:
            else:
                raise Exception("Unknown peer address type:  %s" % (peerType))
            peers.add((host, port))
        #note that there is a new transaction:
        transactionId = self.currentTransactionId
        self.responses[transactionId] = ""
        self.currentTransactionId += 1
        #now add each peer:
        for host, port in peers:
            #make sure it's not one of our defaults
            #TODO:  in the future, make sure we don't already know about it anyway?  Eh, maybe that will break DHT somehow?
            if (host, port) not in Node.BOOTSTRAP_NODES:
                log_msg("Neat, someone told us about a new DHT node", 2)
                self.dhtNode.add_contact(host, port)
        #and then send out the request:
        def response(data, transactionId=transactionId):
            #is this the last message?
            if len(data) <= 0:
                #then send the response for this transaction:
                self._send_peers(transactionId)
            #otherwise, just accumulate the data for later:
            else:
                self.responses[transactionId] += "".join(data[0])

        self.dhtNode.get_peers(infohash, response)
Exemple #10
0
 def on_login_failure(self, bankApp, err, optionalServerResponse=None):
     text = None
     self.dia.window.raise_()
     eType = type(err)
     if eType is BadLoginPasswordError:
         text = str(err)
     elif eType is Failure:
         eType = type(err.value)
         if issubclass(eType, ConnectionDone) or issubclass(
                 eType, ConnectionLost):
             text = "The login server is temporarily offline.  We are sorry for the inconvenience.  Please try again later."
     if not text:
         text = "Login failed for an unknown reason.  Please try again."
     text += "\nNOTE: You must restart the program to change users."
     if optionalServerResponse:
         force, optionalServerResponse = Basic.read_byte(
             optionalServerResponse)
         #concatenate
         if force is 0:
             text += '\n' + optionalServerResponse
         #nuke it
         else:
             text = optionalServerResponse
     self.label.set_text(text)
     self.nameEntry.set_sensitive(True)
     self.pwEntry.set_sensitive(True)
     self.loginButton.set_sensitive(True)
     self.quitButton.set_sensitive(True)
Exemple #11
0
 def sym_decrypt(self, msg):
   """this is disgusting because we use two different systems for symmetric encryption
   type 0 uses SmmetricKey while
   type 1 uses EncryptedDatagram
   quirks: 
   0 must also update the nonce stored in the db
   1 performs heavy crypto and has non symmetric client/server side encryption/decryption"""
   if not self.symKey:
     msgType, msg = Basic.read_byte(msg)
     if msgType is 0:
       #get the tor fingerprint so we know how to decrypt the message
       (binId,), msg = Basic.read_message('!20s', msg)
       #convert the tor fingerprint back into hex
       self.hexId = binascii.hexlify(binId).upper()
       #get the symmetric key out of the database:
       sql = "SELECT Owner, Public_Key, Msgnum, auth_blob FROM Relays WHERE Tor_Id = %s"
       inj = (self.hexId,)
       d = db.read(sql, inj)
       #get the sym key from the db and decrypt the msg
       d.addCallback(self.fetch_sym_key, msg)
       #update the message number in the database
       d.addCallback(self.update_db)
     elif msgType is 1:
       self.symKey = EncryptedDatagram.ServerSymKey(Globals.GENERIC_KEY)
       d = threads.deferToThread(self.get_sym_key_value, msg)
     else:
       raise Exception("Unknown msgType:  %s" % (msgType))
   else:
     raise Exception('Passing more than one message per tcp connection is currently not supported')
   return d
Exemple #12
0
 def on_login_failure(self, bankApp, err, optionalServerResponse=None):
   text = None
   self.dia.window.raise_()
   eType = type(err)
   if eType is BadLoginPasswordError:
     text = str(err)
   elif eType is Failure:
     eType = type(err.value)
     if issubclass(eType, ConnectionDone) or issubclass(eType, ConnectionLost):
       text = "The login server is temporarily offline.  We are sorry for the inconvenience.  Please try again later."
   if not text:
     text = "Login failed for an unknown reason.  Please try again."
   text += "\nNOTE: You must restart the program to change users."
   if optionalServerResponse:
     force, optionalServerResponse = Basic.read_byte(optionalServerResponse)
     #concatenate
     if force is 0:
       text += '\n'+optionalServerResponse
     #nuke it
     else:
       text = optionalServerResponse
   self.label.set_text(text)
   self.nameEntry.set_sensitive(True)
   self.pwEntry.set_sensitive(True)
   self.loginButton.set_sensitive(True)
   self.quitButton.set_sensitive(True)
Exemple #13
0
 def message_arrived(self, msg):
   """Called when a payment message is received via the controller.
   Is responsible for piecing it back together into the actual message.
   @param msg:  the data received from Tor
   @type  msg:  str"""
   self.buffer += msg
   #is the whole message here?
   msgLen, msgData = Basic.read_short(self.buffer)
   if len(msgData) >= msgLen:
     msgData = msgData[:msgLen]
     #we just discard the rest of the cell, two messages are never packed in the same cell currently
     self.buffer = ""
     #what type of message is this?
     msgType, msgData = Basic.read_byte(msgData)
     #ok, now handle that message:
     for msgName in MESSAGE_CODES.keys():
       if msgType == MESSAGE_CODES[msgName]:
         #if we don't know how to handle this message, just close the circuit
         if msgName not in self.messageHandlers:
           log_msg("Remote request for %s, which we do not know how to handle" % (msgName), 1)
           self.close()
           return
         #get the handler:
         handler = self.messageHandlers[msgName]
         #get the handler function:
         funcName = "handle_%s" % (msgName)
         if not hasattr(handler, funcName):
           raise Exception("%s cannot handle %s payment message?" % (handler, msgName))
         f = getattr(handler, funcName)
         f(msgData)
         return
     #uhh, not sure how to handle this message:
     raise Exception("Unknown message type for payment message:  %s" % (msgType))
Exemple #14
0
 def sym_decrypt(self, msg):
     """this is disgusting because we use two different systems for symmetric encryption
 type 0 uses SmmetricKey while
 type 1 uses EncryptedDatagram
 quirks: 
 0 must also update the nonce stored in the db
 1 performs heavy crypto and has non symmetric client/server side encryption/decryption"""
     if not self.symKey:
         msgType, msg = Basic.read_byte(msg)
         if msgType is 0:
             #get the tor fingerprint so we know how to decrypt the message
             (binId, ), msg = Basic.read_message('!20s', msg)
             #convert the tor fingerprint back into hex
             self.hexId = binascii.hexlify(binId).upper()
             #get the symmetric key out of the database:
             sql = "SELECT Owner, Public_Key, Msgnum, auth_blob FROM Relays WHERE Tor_Id = %s"
             inj = (self.hexId, )
             d = db.read(sql, inj)
             #get the sym key from the db and decrypt the msg
             d.addCallback(self.fetch_sym_key, msg)
             #update the message number in the database
             d.addCallback(self.update_db)
         elif msgType is 1:
             self.symKey = EncryptedDatagram.ServerSymKey(
                 Globals.GENERIC_KEY)
             d = threads.deferToThread(self.get_sym_key_value, msg)
         else:
             raise Exception("Unknown msgType:  %s" % (msgType))
     else:
         raise Exception(
             'Passing more than one message per tcp connection is currently not supported'
         )
     return d
 def handle_setup_reply(self, msg):
   """Handle a setup reply.  Send it to the appropriate PaymentStream, then check if they are all done"""
   log_msg("circ=%d:  PAR setup done." % (self.circ.id), 3, "par")
   #unpack the messages:
   forwardParVersion, msg = Basic.read_byte(msg)
   if forwardParVersion < self.parVersion:
     self.parVersion = forwardParVersion
   payStream, msg = self.get_payment_stream(msg)
   payStream.handle_setup_reply(forwardParVersion, msg)
   if self.all_setup_done():
     initialTokensDeferred = self.add_start_tokens()
     #this usually happens if the circuit is already closed, if not, an exception will already be logged
     if not initialTokensDeferred:
       self.circ.on_done()
       return
     def initial_tokens_added(result):
       self.circ.initialTokensAdded = True
       self._add_tokens_callback(result, PaymentMessageHandler.START_READ_TOKENS, PaymentMessageHandler.START_WRITE_TOKENS)
       return result
     initialTokensDeferred.addCallback(initial_tokens_added)
     initialTokensDeferred.addErrback(self.generic_error_handler)
     self.setupDone = True
     #send any payment requests that are waiting on the setup:
     reads = self.queuedReadTokens
     writes = self.queuedWriteTokens
     self.queuedReadTokens = 0
     self.queuedWriteTokens = 0
     if self.queuedReadTokens or self.queuedWriteTokens:
       self.send_payment_request(reads, writes)
     self.circ.on_par_ready()
 def stringReceived(self, encryptedMsg):
   self.responseReceived = True
   self.transport.loseConnection()
   blob = self.factory.bank.decrypt_message(encryptedMsg)
   log_msg("ACoin REQUEST response received.", 4)
   responseCode, blob = Basic.read_byte(blob)
   #we had enough credits in our account
   if responseCode == 0:
     (newBalance, number), coins = Basic.read_message('!II', blob)
     #update the balance
     self.factory.bank.on_new_balance_from_bank(newBalance)
     acoinStrFormat = "%ss" % (Globals.ACOIN_KEY_BYTES)
     format = '!' + (acoinStrFormat * number)
     sigs = list(struct.unpack(format, coins))
     while len(self.factory.requests) > 0:
       request = self.factory.requests.pop(0)
       sig = sigs.pop(0)
       coin = BankMessages.parse_acoin_response(self.factory.bank, sig, request, ProgramState.DEBUG)
       if coin:
         self.factory.bank.add_acoin(coin)
       else:
         log_msg("Got an invalid ACoin from the bank!?", 3)
   #the bank could not check out the coins because our account doesn't have enough credits!
   else:
     (newBalance,), blob = Basic.read_message('!I', blob)
     self.factory.bank.on_new_balance_from_bank(newBalance)
Exemple #17
0
 def message_arrived(self, msg):
     """Called when a payment message is received via the controller.
 Is responsible for piecing it back together into the actual message.
 @param msg:  the data received from Tor
 @type  msg:  str"""
     self.buffer += msg
     # is the whole message here?
     msgLen, msgData = Basic.read_short(self.buffer)
     if len(msgData) >= msgLen:
         msgData = msgData[:msgLen]
         # we just discard the rest of the cell, two messages are never packed in the same cell currently
         self.buffer = ""
         # what type of message is this?
         msgType, msgData = Basic.read_byte(msgData)
         # ok, now handle that message:
         for msgName in MESSAGE_CODES.keys():
             if msgType == MESSAGE_CODES[msgName]:
                 # if we don't know how to handle this message, just close the circuit
                 if msgName not in self.messageHandlers:
                     log_msg("Remote request for %s, which we do not know how to handle" % (msgName), 1)
                     self.close()
                     return
                 # get the handler:
                 handler = self.messageHandlers[msgName]
                 # get the handler function:
                 funcName = "handle_%s" % (msgName)
                 if not hasattr(handler, funcName):
                     raise Exception("%s cannot handle %s payment message?" % (handler, msgName))
                 f = getattr(handler, funcName)
                 f(msgData)
                 return
         # uhh, not sure how to handle this message:
         raise Exception("Unknown message type for payment message:  %s" % (msgType))
    def handle_setup_reply(self, msg):
        """Handle a setup reply.  Send it to the appropriate PaymentStream, then check if they are all done"""
        log_msg("circ=%d:  PAR setup done." % (self.circ.id), 3, "par")
        #unpack the messages:
        forwardParVersion, msg = Basic.read_byte(msg)
        if forwardParVersion < self.parVersion:
            self.parVersion = forwardParVersion
        payStream, msg = self.get_payment_stream(msg)
        payStream.handle_setup_reply(forwardParVersion, msg)
        if self.all_setup_done():
            initialTokensDeferred = self.add_start_tokens()
            #this usually happens if the circuit is already closed, if not, an exception will already be logged
            if not initialTokensDeferred:
                self.circ.on_done()
                return

            def initial_tokens_added(result):
                self.circ.initialTokensAdded = True
                self._add_tokens_callback(
                    result, PaymentMessageHandler.START_READ_TOKENS,
                    PaymentMessageHandler.START_WRITE_TOKENS)
                return result

            initialTokensDeferred.addCallback(initial_tokens_added)
            initialTokensDeferred.addErrback(self.generic_error_handler)
            self.setupDone = True
            #send any payment requests that are waiting on the setup:
            reads = self.queuedReadTokens
            writes = self.queuedWriteTokens
            self.queuedReadTokens = 0
            self.queuedWriteTokens = 0
            if self.queuedReadTokens or self.queuedWriteTokens:
                self.send_payment_request(reads, writes)
            self.circ.on_par_ready()
Exemple #19
0
 def handle_dht_request(self, data):
   log_msg("Got remote DHT request", 4, "dht")
   #unpack and validate the message:
   version, data = Basic.read_byte(data)
   assert version == Node.VERSION
   #read the infohash:
   vals, data = Basic.read_message("20s", data)
   infohash = vals[0]
   #read each peer:
   peers = set()
   while len(data) > 0:
     #what type of peer?  (ip or url)
     peerType, data = Basic.read_byte(data)
     #IP peer:
     if peerType == 0:
       vals, data = Basic.read_message("!4sH", data)
       host = socket.inet_ntoa(vals[0])
       port = vals[1]
     #URL peer:
     elif peerType == 1:
       host, data = Basic.read_lenstr(data)
       port, data = Basic.read_short(data)
     #bad peer type:
     else:
       raise Exception("Unknown peer address type:  %s" % (peerType))
     peers.add((host, port))
   #note that there is a new transaction:
   transactionId = self.currentTransactionId
   self.responses[transactionId] = ""
   self.currentTransactionId += 1
   #now add each peer:
   for host, port in peers:
     #make sure it's not one of our defaults
     #TODO:  in the future, make sure we don't already know about it anyway?  Eh, maybe that will break DHT somehow?
     if (host, port) not in Node.BOOTSTRAP_NODES:
       log_msg("Neat, someone told us about a new DHT node", 2)
       self.dhtNode.add_contact(host, port)
   #and then send out the request:
   def response(data, transactionId=transactionId):
     #is this the last message?
     if len(data) <= 0:
       #then send the response for this transaction:
       self._send_peers(transactionId)
     #otherwise, just accumulate the data for later:
     else:
       self.responses[transactionId] += "".join(data[0])
   self.dhtNode.get_peers(infohash, response)
Exemple #20
0
    def success(result, request=request):
      log_msg("success")
      self.payments += 1
#      self.start_payment_loop()
      #validate the ACoin
      code, sig = Basic.read_byte(result)
      coin = BankMessages.parse_acoin_response(Bank.get(), sig, request, False)
      if not coin:
        log_msg("Invalid ACoin sent for payment!")
      else:
        Bank.get().on_earned_coin(coin)
Exemple #21
0
 def success(result, request=request):
     log_msg("success")
     self.payments += 1
     #      self.start_payment_loop()
     #validate the ACoin
     code, sig = Basic.read_byte(result)
     coin = BankMessages.parse_acoin_response(Bank.get(), sig, request,
                                              False)
     if not coin:
         log_msg("Invalid ACoin sent for payment!")
     else:
         Bank.get().on_earned_coin(coin)
Exemple #22
0
 def read_request(self, data, host, transport):
   try:
     #read the header:
     data = self._read_header(data, "request")
     #read the protocol type:
     protocolType, data = Basic.read_byte(data)
     assert protocolType in self.TEST_TYPES, "Unknown echo protocol:  %s" % (protocolType)
     protocol = self.TEST_TYPES[protocolType]
     #read the port:
     port, data = Basic.read_short(data)
   except AssertionError, error:
     raise BadEchoMessageFormat(str(error))
Exemple #23
0
 def read_request(self, data, host, transport):
     try:
         #read the header:
         data = self._read_header(data, "request")
         #read the protocol type:
         protocolType, data = Basic.read_byte(data)
         assert protocolType in self.TEST_TYPES, "Unknown echo protocol:  %s" % (
             protocolType)
         protocol = self.TEST_TYPES[protocolType]
         #read the port:
         port, data = Basic.read_short(data)
     except AssertionError, error:
         raise BadEchoMessageFormat(str(error))
Exemple #24
0
 def on_login_success(self, balance, authBlob, host, port, text):
     """Called when we successfully log in to the bank server, passed the response message
 @param balance:  how many credits we have at the bank
 @type  balance:  int
 @param authBlob:  the symmetric key to use for subsequent messages
 @type  authBlob:  str
 @param host:  where to send subsequent messages
 @type  host:  str (ip addr)
 @param port:  where to send subsequent messages
 @type  port:  int (port)
 @param text:  a status code and message from the bank to possibly show the user.
 @type  text:  str"""
     if not self.startupDeferred:
         return
     log_msg("login was successful: \nServer says: %s" % (text), 4)
     if text:
         #If the code is non-zero, display the text
         code, text = Basic.read_byte(text)
         if code == 0:
             text = None
     self.loginInProgress = False
     #figure out the shared symmetric key from the bank (for use encrypting all later messages)
     self.secretKey = SymmetricKey.SymmetricKey(authBlob)
     self.host = host
     self.port = port
     if not self.isLoggedIn:
         self.isLoggedIn = True
         #determine some file names based on the username:
         self.ACOIN_FILE_NAME = os.path.join(Globals.USER_DATA_DIR,
                                             "acoins.txt")
         self.DEPOSITED_FILE_NAME = os.path.join(Globals.USER_DATA_DIR,
                                                 "acoins_in_deposit.txt")
         #inform the gui that we've logged in:
         self._trigger_event("login_success", text)
         #load any coins we stored when we shut down previously:
         self.load_coins()
         log_msg("Bank login successful!", 3)
         #make sure we have enough ACoins:
         self.check_wallet_balance()
         #let other parts of the program react to the fact that we just logged in
         GlobalEvents.throw_event("login")
         #notify anyone waiting on the startup deferred:
         self.startupDeferred.callback(True)
         self.startupDeferred = None
         self._trigger_event("started")
     else:
         log_ex("already logged in",
                "The bank should not be started more than once")
Exemple #25
0
 def handle_message(self, msg):
   request_type, msg = Basic.read_byte(msg)
   #attach the correct handler
   if request_type == 1:
     self.handler =  ACoinMessages.Request(self.encrypted_reply, self.owner, self.hexId)
   elif request_type == 2:
     self.handler = ACoinMessages.Deposit(self.encrypted_reply, self.owner, self.hexId)
   elif request_type == 3:
     self.owner = self.transport.getPeer()
     self.handler =  ACoinMessages.Payment(self.reply, self.owner) 
   else:
     log_msg('invalid request: %s, %s' % (request_type, msg), 1)
     self.reply('invalid request: %s' % (request_type))
     #self.drop_connection()
     return
   self.handler.on_message(msg)
 def stringReceived(self, data):
   self.successful = True
   #we don't have any errbacks attached yet- an error will just make the client hang indefinately
   try:
     protocol, blob = Basic.read_byte(data)
     if protocol == 1:
       self.hexIdSig, self.username, self.password, self.n = self.unpack(blob)
       d = self.check_for_timeout()
       d.addCallback(self.login_timeout_known)
       d.addErrback(self.err)
     elif protocol == 2:
       ipAddress = self.transport.getPeer().host
       self.currentAction = AccountCreation.AccountCreation(blob, ipAddress, db, self.reply)
     else:
       raise Exception('unknown login protocol: %s' % (protocol))
   except Exception, e:
     self.err(e)
Exemple #27
0
 def update_db(self, blob):
     """utility function that updates verifies the nonce in the msg and then updates the nonce in the db"""
     protocol, blob = Basic.read_byte(blob)
     if protocol is not 1:
         raise Exception('change protocol')
     msgNum, blob = Basic.read_short(blob)
     #the msgNum is a nonce to prevent replay attacks-
     #the client always increases it by one, we just check that it is bigger
     if msgNum > self.previousMsgnum:
         #update the msgnum in the db to be this msgnum of course -
         #not generally threadsafe
         sql = "UPDATE Relays SET Msgnum = %s WHERE tor_id = %s"
         inj = (msgNum, self.hexId)
         d = db.write(sql, inj)
     else:
         raise Exception('replay attack or something')
     return blob
Exemple #28
0
 def update_db(self, blob):
   """utility function that updates verifies the nonce in the msg and then updates the nonce in the db"""
   protocol, blob = Basic.read_byte(blob)
   if protocol is not 1:
     raise Exception('change protocol')
   msgNum, blob = Basic.read_short(blob)
   #the msgNum is a nonce to prevent replay attacks- 
   #the client always increases it by one, we just check that it is bigger
   if msgNum > self.previousMsgnum:
     #update the msgnum in the db to be this msgnum of course - 
     #not generally threadsafe
     sql = "UPDATE Relays SET Msgnum = %s WHERE tor_id = %s"
     inj = (msgNum, self.hexId)
     d = db.write(sql, inj)
   else:
     raise Exception('replay attack or something')
   return blob
Exemple #29
0
 def handle_message(self, msg):
     request_type, msg = Basic.read_byte(msg)
     #attach the correct handler
     if request_type == 1:
         self.handler = ACoinMessages.Request(self.encrypted_reply,
                                              self.owner, self.hexId)
     elif request_type == 2:
         self.handler = ACoinMessages.Deposit(self.encrypted_reply,
                                              self.owner, self.hexId)
     elif request_type == 3:
         self.owner = self.transport.getPeer()
         self.handler = ACoinMessages.Payment(self.reply, self.owner)
     else:
         log_msg('invalid request: %s, %s' % (request_type, msg), 1)
         self.reply('invalid request: %s' % (request_type))
         #self.drop_connection()
         return
     self.handler.on_message(msg)
Exemple #30
0
 def read_payment_tokens(self, msg):
   """Read merchant payment tokens from a message"""
   #read the number of payment requests:
   numTokens, msg = Basic.read_byte(msg)
   #determine the size of the tokens:
   assert len(msg) % numTokens == 0, "bad payment token message"
   tokenSize = len(msg) / numTokens
   #read each of the payment requests:
   while msg:
     token, msg = msg[:tokenSize], msg[tokenSize:]
     requestId, token, tokenSig = struct.unpack("!L%ss%ss" % (Globals.ACOIN_KEY_BYTES, Globals.TOR_ID_KEY_BYTES), token)
     if not self.key.verify(token, tokenSig):
       #END_CIRC_REASON_TORPROTOCOL
       if not self.parClient.circ.is_done():
         log_ex("Signature invalid", "Error unpacking payment tokens")
         self.parClient.circ.close(1)
         return False
     self.paymentTokens[requestId] = token
   return True
Exemple #31
0
 def on_message(self, msg):
   log_msg('PAYMENT', 0)
   current = Globals.CURRENT_ACOIN_INTERVAL[0]
   #read the number of payments:
   numPayments, msg = Basic.read_byte(msg)
   reply = ""
   for i in range(0, numPayments):
     #read the payment:
     result, coin, msg = deposit_acoin(msg, current)
     reply += struct.pack('!s', result)
     token, msg = msg[:Globals.ACOIN_KEY_BYTES], msg[Globals.ACOIN_KEY_BYTES:]
     #if the coin is valid...
     if result == '0':
       sig = Globals.ACOIN_KEY.decrypt(token, False)
       #~ print "token:  " + repr(token)
       #~ print "sig:  " + repr(sig)
       reply += struct.pack('!%ss' % (Globals.ACOIN_KEY_BYTES), sig)
   #and finally, send it back to the client:
   self.send_func(reply)
   #log the event:
   eventLogger.aggregate_event("PAYMENTS", self.address[0], 1)
Exemple #32
0
 def on_message(self, msg):
     log_msg('PAYMENT', 0)
     current = Globals.CURRENT_ACOIN_INTERVAL[0]
     #read the number of payments:
     numPayments, msg = Basic.read_byte(msg)
     reply = ""
     for i in range(0, numPayments):
         #read the payment:
         result, coin, msg = deposit_acoin(msg, current)
         reply += struct.pack('!s', result)
         token, msg = msg[:Globals.ACOIN_KEY_BYTES], msg[Globals.
                                                         ACOIN_KEY_BYTES:]
         #if the coin is valid...
         if result == '0':
             sig = Globals.ACOIN_KEY.decrypt(token, False)
             #~ print "token:  " + repr(token)
             #~ print "sig:  " + repr(sig)
             reply += struct.pack('!%ss' % (Globals.ACOIN_KEY_BYTES), sig)
     #and finally, send it back to the client:
     self.send_func(reply)
     #log the event:
     eventLogger.aggregate_event("PAYMENTS", self.address[0], 1)
Exemple #33
0
    def handle_payment(self, msg):
        """Unpack, process, and respond to a payment message.
    @param msg:  the payment message from the origin.
    @type  msg:  str"""
        #if there are any failures, log them, and close the circuit:
        try:
            #read the PAR protocol version:
            version, msg = Basic.read_byte(msg)
            assert version == 1, "currently only accept PAR version 1"
            readTokens, msg = Basic.read_int(msg)
            writeTokens, msg = Basic.read_int(msg)
            #read their request ID too
            theirId, msg = Basic.read_long(msg)
            #read the number of coins:
            numCoins, msg = Basic.read_byte(msg)
            #read each coin:
            creditsEarned = 0
            requests = []
            for i in range(0, numCoins):
                #what type of coin is this?
                coinType, msg = Basic.read_byte(msg)
                #we only accept acoins for now:
                assert coinType == PaymentStream.COIN_TYPES[
                    'A'], "bad coin type"
                #get the matching request:
                requestId, msg = Basic.read_long(msg)
                requests.append(requestId)
            assert len(msg) % numCoins == 0, "bad payment message length"
            coinLen = len(msg) / numCoins
            for requestId in requests:
                #if this is not true, there wont even be another part to the response
                assert Basic.read_byte(msg)[0] == ord(
                    '0'), "bad leading byte in payment message"
                blob, msg = msg[:coinLen], msg[coinLen:]
                request = self.requests[requestId]
                del self.requests[requestId]
                code, sig = Basic.read_byte(blob)
                #validate the ACoin
                coin = BankMessages.parse_acoin_response(
                    self.bank, sig, request)
                if not coin:
                    raise Exception("Invalid ACoin sent for payment!")
                #success!
                creditsEarned += coin.get_expected_value()
                coin.originCircuit = self
                self.bank.on_earned_coin(coin)
            receiptMessageDeferred = self.send_receipt_message(
                theirId, numCoins)
            if not receiptMessageDeferred:
                return
            #check that they paid enough:
            requestedTokens = readTokens + writeTokens
            paidTokens = creditsEarned * Globals.CELLS_PER_PAYMENT
            if paidTokens < requestedTokens:
                raise Exception("Relays asked for %s, but only paid for %s" %
                                (requestedTokens, paidTokens))
            #inform Tor that we got a payment message:
            addTokensDeferred = self.add_tokens(readTokens, writeTokens)
            if not addTokensDeferred:
                return

            def response(result):
                if result:
                    read, write = result
                    log_msg(
                        "%s paid us %s for exit stream, now %d / %d" %
                        (Basic.clean(self.baseCircuit.prevHexId[:4]),
                         creditsEarned, read, write), 3, "par")

            addTokensDeferred.addCallback(response)
        except Exception, error:
            log_ex(error, "Got bad PAR message")
            self.close()
 def handle_payment(self, msg):
   """Unpack, process, and respond to a payment message.
   @param msg:  the payment message from the origin.
   @type  msg:  str"""
   #if there are any failures, log them, and close the circuit:
   try:
     #read the PAR protocol version:
     version, msg = Basic.read_byte(msg)
     assert version == 1, "currently only accept PAR version 1"
     readTokens, msg = Basic.read_int(msg)
     writeTokens, msg = Basic.read_int(msg)
     #read their request ID too
     theirId, msg = Basic.read_long(msg)
     #read the number of coins:
     numCoins, msg = Basic.read_byte(msg)
     #read each coin:
     creditsEarned = 0
     requests = []
     for i in range(0, numCoins):
       #what type of coin is this?
       coinType, msg = Basic.read_byte(msg)
       #we only accept acoins for now:
       assert coinType == PaymentStream.COIN_TYPES['A'], "bad coin type"
       #get the matching request:
       requestId, msg = Basic.read_long(msg)
       requests.append(requestId)
     assert len(msg) % numCoins == 0, "bad payment message length"
     coinLen = len(msg) / numCoins
     for requestId in requests:
       #if this is not true, there wont even be another part to the response
       assert Basic.read_byte(msg)[0] == ord('0'), "bad leading byte in payment message"
       blob, msg = msg[:coinLen], msg[coinLen:]
       request = self.requests[requestId]
       del self.requests[requestId]
       code, sig = Basic.read_byte(blob)
       #validate the ACoin
       coin = BankMessages.parse_acoin_response(self.bank, sig, request)
       if not coin:
         raise Exception("Invalid ACoin sent for payment!")
       #success!
       creditsEarned += coin.get_expected_value()
       coin.originCircuit = self
       self.bank.on_earned_coin(coin)
     receiptMessageDeferred = self.send_receipt_message(theirId, numCoins)
     if not receiptMessageDeferred:
       return
     #check that they paid enough:
     requestedTokens = readTokens + writeTokens
     paidTokens = creditsEarned * Globals.CELLS_PER_PAYMENT
     if paidTokens < requestedTokens:
       raise Exception("Relays asked for %s, but only paid for %s" % (requestedTokens, paidTokens))
     #inform Tor that we got a payment message:
     addTokensDeferred = self.add_tokens(readTokens, writeTokens)
     if not addTokensDeferred:
       return
     def response(result):
       if result:
         read, write = result
         log_msg("%s paid us %s for exit stream, now %d / %d" % (Basic.clean(self.baseCircuit.prevHexId[:4]), creditsEarned, read, write), 3, "par")
     addTokensDeferred.addCallback(response)
   except Exception, error:
     log_ex(error, "Got bad PAR message")
     self.close()
 def handle_receipt(self, msg):
   """Handle a receipt message from Tor control"""
   version, msg = Basic.read_byte(msg)
   payStream, msg = self.get_payment_stream(msg)
   payStream.handle_receipt(msg)
Exemple #36
0
 def handle_dht_response(self, data):
     log_msg("Got remote DHT response", 4, "dht")
     version, data = Basic.read_byte(data)
     assert version == Node.VERSION
     peerList = {'peers': data}
     self.callback(peerList)
 def handle_receipt(self, msg):
     """Handle a receipt message from Tor control"""
     version, msg = Basic.read_byte(msg)
     payStream, msg = self.get_payment_stream(msg)
     payStream.handle_receipt(msg)
Exemple #38
0
 def handle_dht_response(self, data):
   log_msg("Got remote DHT response", 4, "dht")
   version, data = Basic.read_byte(data)
   assert version == Node.VERSION
   peerList = {'peers': data}
   self.callback(peerList)