Beispiel #1
0
def password_reset(payload=None):
    client=currentSession()
    form = PasswordForm(request.form)
        
    if request.method == 'POST':
        decrypted = ""
        reset_id = form["reset_id"].data

        if not form.validate():
            return render_template('passwordreset.html', form=form, client=client, msg=None, decrypted=decrypted)
        else:
            # update password
            if reset_id:
                client.user = client.getUserById(reset_id)
                client.user.set_password(form.password.data)
                database.db_session.add(client.user)
                database.db_session.commit()
                client.saveSession()
                msg = "password has been changed. please login again."
            else:
                msg = "user not found."
            return render_template('passwordreset.html', form=form, client=client, msg=msg, decrypted=decrypted)
    else:
        msg = None
        e = Crypto()
        decrypted = e.decrypt(payload, True)
        if utilities.validate_uuid4(decrypted) == False:
            # timestamp has expired.
            msg = decrypted
        return render_template('passwordreset.html', form=form, client=client, msg=msg, decrypted=decrypted)
Beispiel #2
0
    def __init__(self,
                 connectionManager,
                 remoteNick,
                 sendMessageCallback,
                 recvMessageCallback,
                 handshakeDoneCallback,
                 smpRequestCallback,
                 errorCallback,
                 initiateHandkshakeOnStart=False):
        Thread.__init__(self)
        self.daemon = True

        self.connectionManager = connectionManager
        self.remoteNick = remoteNick
        self.sendMessageCallback = sendMessageCallback
        self.recvMessageCallback = recvMessageCallback
        self.handshakeDoneCallback = handshakeDoneCallback
        self.smpRequestCallback = smpRequestCallback
        self.errorCallback = errorCallback
        self.initiateHandkshakeOnStart = initiateHandkshakeOnStart

        self.incomingMessageNum = 0
        self.outgoingMessageNum = 0
        self.isEncrypted = False
        self.wasHandshakeDone = False
        self.messageQueue = queue.Queue()

        self.crypto = Crypto()
        self.crypto.generateDHKey()
        self.smp = None
Beispiel #3
0
def forgot():
    client=currentSession()
    form = ForgotForm(request.form)
    if request.method == 'POST':
        if not form.validate():
            return render_template('forgot.html', form=form, client=client)
        else:
            user = client.getUserByEmail(form.email.data)
            m = Mail()
            e = Crypto()
            # get encrypted link
            encrypted = e.encrypt(user.id, True)
            # email link
            result = m.send_forgot_password(user.email, encrypted)
            form.email.errors.append(result)
            return render_template('forgot.html', form=form, client=client)
    else:
        return render_template('forgot.html', form=form, client=client)
Beispiel #4
0
class CryptoTest(unittest.TestCase):
    def setUp(self):
        self.crypto = Crypto()

    def test_decrypt_a(self):
        self.assertMessageIs('a', '!')

    def test_decrypt_b(self):
        self.assertMessageIs('b', ')')

    def test_decrypt_foo(self):
        self.assertMessageIs('foo', '*dd')

    def assertMessageIs(self, exptected_message, encrypted_message):
        message = self.crypto.decrypt(encrypted_message)
        self.assertEqual(exptected_message, message)
Beispiel #5
0
    def __init__(self, connectionManager, remoteNick, sendMessageCallback, recvMessageCallback, handshakeDoneCallback, errorCallback, initiateHandkshakeOnStart=False):
        Thread.__init__(self)
        self.daemon = True

        self.connectionManager = connectionManager
        self.remoteNick = remoteNick
        self.sendMessageCallback = sendMessageCallback
        self.recvMessageCallback = recvMessageCallback
        self.handshakeDoneCallback = handshakeDoneCallback
        self.errorCallback = errorCallback
        self.initiateHandkshakeOnStart = initiateHandkshakeOnStart

        self.incomingMessageNum = 0
        self.outgoingMessageNum = 0
        self.isEncrypted = False
        self.wasHandshakeDone = False
        self.messageQueue = Queue.Queue()

        self.crypto = Crypto()
        self.crypto.generateDHKey()
Beispiel #6
0
 def setUp(self):
     self.crypto = Crypto()
Beispiel #7
0
class Client(Thread):
    def __init__(self,
                 connectionManager,
                 remoteNick,
                 sendMessageCallback,
                 recvMessageCallback,
                 handshakeDoneCallback,
                 smpRequestCallback,
                 errorCallback,
                 initiateHandkshakeOnStart=False):
        Thread.__init__(self)
        self.daemon = True

        self.connectionManager = connectionManager
        self.remoteNick = remoteNick
        self.sendMessageCallback = sendMessageCallback
        self.recvMessageCallback = recvMessageCallback
        self.handshakeDoneCallback = handshakeDoneCallback
        self.smpRequestCallback = smpRequestCallback
        self.errorCallback = errorCallback
        self.initiateHandkshakeOnStart = initiateHandkshakeOnStart

        self.incomingMessageNum = 0
        self.outgoingMessageNum = 0
        self.isEncrypted = False
        self.wasHandshakeDone = False
        self.messageQueue = queue.Queue()

        self.crypto = Crypto()
        self.crypto.generateDHKey()
        self.smp = None

    def sendChatMessage(self, text):
        self.sendMessage(constants.COMMAND_MSG, text)

    def sendTypingMessage(self, status):
        self.sendMessage(constants.COMMAND_TYPING, str(status))

    def sendMessage(self, command, payload=None):
        message = Message(clientCommand=command, destNick=self.remoteNick)

        # Encrypt all outgoing data
        if payload is not None and self.isEncrypted:
            payload = self.crypto.aesEncrypt(payload)
            message.setEncryptedPayload(payload)

            # Generate and set the HMAC for the message
            message.setBinaryHmac(self.crypto.generateHmac(payload))

            # Encrypt the message number of the message
            message.setBinaryMessageNum(
                self.crypto.aesEncrypt(str(self.outgoingMessageNum)))
            self.outgoingMessageNum += 1
        else:
            message.payload = payload

        self.sendMessageCallback(message)

    def postMessage(self, message):
        self.messageQueue.put(message)

    def initiateSMP(self, question, answer):
        self.sendMessage(constants.COMMAND_SMP_0, question)

        self.smp = SMP(answer)
        buffer = self.smp.step1()
        self.sendMessage(constants.COMMAND_SMP_1, buffer)

    def respondSMP(self, answer):
        self.smp = SMP(answer)
        self.__doSMPStep1(self.smpStep1)

    def run(self):
        if self.initiateHandkshakeOnStart:
            self.__initiateHandshake()
        else:
            self.__doHandshake()

        if not self.wasHandshakeDone:
            return

        while True:
            message = self.messageQueue.get()

            command = message.clientCommand
            payload = message.payload

            # Check if the client requested to end the connection
            if command == constants.COMMAND_END:
                self.connectionManager.destroyClient(self.remoteNick)
                self.errorCallback(self.remoteNick,
                                   errors.ERR_CONNECTION_ENDED)
                return
            # Ensure we got a valid command
            elif self.wasHandshakeDone and command not in constants.LOOP_COMMANDS:
                self.connectionManager.destroyClient(self.remoteNick)
                self.errorCallback(self.remoteNick, errors.ERR_INVALID_COMMAND)
                return

            # Decrypt the incoming data
            payload = self.__getDecryptedPayload(message)

            self.messageQueue.task_done()

            # Handle SMP commands specially
            if command in constants.SMP_COMMANDS:
                self.__handleSMPCommand(command, payload)
            else:
                self.recvMessageCallback(command, message.sourceNick, payload)

    def connect(self):
        self.__initiateHandshake()

    def disconnect(self):
        try:
            self.sendMessage(constants.COMMAND_END)
        except:
            pass

    def __doHandshake(self):
        try:
            # The caller of this function (should) checks for the initial HELO command

            # Send the ready command
            self.sendMessage(constants.COMMAND_REDY)

            # Receive the client's public key
            clientPublicKey = self.__getHandshakeMessagePayload(
                constants.COMMAND_PUBLIC_KEY)
            self.crypto.computeDHSecret(int(base64.b64decode(clientPublicKey)))

            # Send our public key
            publicKey = base64.b64encode(str(self.crypto.getDHPubKey()))
            self.sendMessage(constants.COMMAND_PUBLIC_KEY, publicKey)

            # Switch to AES encryption for the remainder of the connection
            self.isEncrypted = True

            self.wasHandshakeDone = True
            self.handshakeDoneCallback(self.remoteNick)
        except exceptions.ProtocolEnd:
            self.disconnect()
            self.connectionManager.destroyClient(self.remoteNick)
        except (exceptions.ProtocolError, exceptions.CryptoError) as e:
            self.__handleHandshakeError(e)

    def __initiateHandshake(self):
        try:
            # Send the hello command
            self.sendMessage(constants.COMMAND_HELO)

            # Receive the redy command
            self.__getHandshakeMessagePayload(constants.COMMAND_REDY)

            # Send our public key
            publicKey = base64.b64encode(str(self.crypto.getDHPubKey()))
            self.sendMessage(constants.COMMAND_PUBLIC_KEY, publicKey)

            # Receive the client's public key
            clientPublicKey = self.__getHandshakeMessagePayload(
                constants.COMMAND_PUBLIC_KEY)
            self.crypto.computeDHSecret(int(base64.b64decode(clientPublicKey)))

            # Switch to AES encryption for the remainder of the connection
            self.isEncrypted = True

            self.wasHandshakeDone = True
            self.handshakeDoneCallback(self.remoteNick)
        except exceptions.ProtocolEnd:
            self.disconnect()
            self.connectionManager.destroyClient(self.remoteNick)
        except (exceptions.ProtocolError, exceptions.CryptoError) as e:
            self.__handleHandshakeError(e)

    def __getHandshakeMessagePayload(self, expectedCommand):
        message = self.messageQueue.get()

        if message.clientCommand != expectedCommand:
            if message.clientCommand == constants.COMMAND_END:
                raise exceptions.ProtocolEnd
            elif message.clientCommand == constants.COMMAND_REJECT:
                raise exceptions.ProtocolError(
                    errno=errors.ERR_CONNECTION_REJECTED)
            else:
                raise exceptions.ProtocolError(errno=errors.ERR_BAD_HANDSHAKE)

        payload = self.__getDecryptedPayload(message)
        self.messageQueue.task_done()

        return payload

    def __getDecryptedPayload(self, message):
        if self.isEncrypted:
            payload = message.getEncryptedPayloadAsBinaryString()
            encryptedMessageNumber = message.getMessageNumAsBinaryString()

            # Check the HMAC
            if not self.__verifyHmac(message.hmac, payload):
                self.errorCallback(message.sourceNick, errors.ERR_BAD_HMAC)
                raise exceptions.CryptoError(errno=errors.BAD_HMAC)

            try:
                # Check the message number
                messageNumber = int(
                    self.crypto.aesDecrypt(encryptedMessageNumber))

                # If the message number is less than what we're expecting, the message is being replayed
                if self.incomingMessageNum > messageNumber:
                    raise exceptions.ProtocolError(
                        errno=errors.ERR_MESSAGE_REPLAY)
                # If the message number is greater than what we're expecting, messages are being deleted
                elif self.incomingMessageNum < messageNumber:
                    raise exceptions.ProtocolError(
                        errno=errors.ERR_MESSAGE_DELETION)
                self.incomingMessageNum += 1

                # Decrypt the payload
                payload = self.crypto.aesDecrypt(payload)
            except exceptions.CryptoError as ce:
                self.errorCallback(message.sourceNick, errors.ERR_BAD_DECRYPT)
                raise ce
        else:
            payload = message.payload

        return payload

    def __verifyHmac(self, givenHmac, payload):
        generatedHmac = self.crypto.generateHmac(payload)
        return utils.secureStrcmp(generatedHmac, base64.b64decode(givenHmac))

    def __handleSMPCommand(self, command, payload):
        try:
            if command == constants.COMMAND_SMP_0:
                # Fire the SMP request callback with the given question
                self.smpRequestCallback(constants.SMP_CALLBACK_REQUEST,
                                        self.remoteNick, payload)
            elif command == constants.COMMAND_SMP_1:
                # If there's already an smp object, go ahead to step 1.
                # Otherwise, save the payload until we have an answer from the user to respond with
                if self.smp:
                    self.__doSMPStep1(payload)
                else:
                    self.smpStep1 = payload
            elif command == constants.COMMAND_SMP_2:
                self.__doSMPStep2(payload)
            elif command == constants.COMMAND_SMP_3:
                self.__doSMPStep3(payload)
            elif command == constants.COMMAND_SMP_4:
                self.__doSMPStep4(payload)
            else:
                # This shouldn't happen
                raise exceptions.CryptoError(errno=errors.ERR_SMP_CHECK_FAILED)
        except exceptions.CryptoError as ce:
            self.smpRequestCallback(constants.SMP_CALLBACK_ERROR,
                                    self.remoteNick, '', ce.errno)

    def __doSMPStep1(self, payload):
        buffer = self.smp.step2(payload)
        self.sendMessage(constants.COMMAND_SMP_2, buffer)

    def __doSMPStep2(self, payload):
        buffer = self.smp.step3(payload)
        self.sendMessage(constants.COMMAND_SMP_3, buffer)

    def __doSMPStep3(self, payload):
        buffer = self.smp.step4(payload)
        self.sendMessage(constants.COMMAND_SMP_4, buffer)

        # Destroy the SMP object now that we're done
        self.smp = None

    def __doSMPStep4(self, payload):
        self.smp.step5(payload)

        if self.__checkSMP():
            self.smpRequestCallback(constants.SMP_CALLBACK_COMPLETE,
                                    self.remoteNick)

        # Destroy the SMP object now that we're done
        self.smp = None

    def __checkSMP(self):
        if not self.smp.match:
            raise exceptions.CryptoError(errno=errors.ERR_SMP_MATCH_FAILED)
        return True

    def __handleHandshakeError(self, exception):
        self.errorCallback(self.remoteNick, exception.errno)

        # For all errors except the connection being rejected, tell the client there was an error
        if exception.errno != errors.ERR_CONNECTION_REJECTED:
            self.sendMessage(constants.COMMAND_ERR)
        else:
            self.connectionManager.destroyClient(self.remoteNick)
Beispiel #8
0
class Client(Thread):
    def __init__(self, connectionManager, remoteNick, sendMessageCallback, recvMessageCallback, handshakeDoneCallback, smpRequestCallback, errorCallback, initiateHandkshakeOnStart=False):
        Thread.__init__(self)
        self.daemon = True

        self.connectionManager = connectionManager
        self.remoteNick = remoteNick
        self.sendMessageCallback = sendMessageCallback
        self.recvMessageCallback = recvMessageCallback
        self.handshakeDoneCallback = handshakeDoneCallback
        self.smpRequestCallback = smpRequestCallback
        self.errorCallback = errorCallback
        self.initiateHandkshakeOnStart = initiateHandkshakeOnStart

        self.incomingMessageNum = 0
        self.outgoingMessageNum = 0
        self.isEncrypted = False
        self.wasHandshakeDone = False
        self.messageQueue = Queue.Queue()

        self.crypto = Crypto()
        self.crypto.generateDHKey()
        self.smp = None


    def sendChatMessage(self, text):
        self.sendMessage(constants.COMMAND_MSG, text)


    def sendTypingMessage(self, status):
        self.sendMessage(constants.COMMAND_TYPING, str(status))


    def sendMessage(self, command, payload=None):
        message = Message(clientCommand=command, destNick=self.remoteNick)

        # Encrypt all outgoing data
        if payload is not None and self.isEncrypted:
            payload = self.crypto.aesEncrypt(payload)
            message.setEncryptedPayload(payload)

            # Generate and set the HMAC for the message
            message.setBinaryHmac(self.crypto.generateHmac(payload))

            # Encrypt the message number of the message
            message.setBinaryMessageNum(self.crypto.aesEncrypt(str(self.outgoingMessageNum)))
            self.outgoingMessageNum += 1
        else:
            message.payload = payload

        self.sendMessageCallback(message)


    def postMessage(self, message):
        self.messageQueue.put(message)


    def initiateSMP(self, question, answer):
        self.sendMessage(constants.COMMAND_SMP_0, question)

        self.smp = SMP(answer)
        buffer = self.smp.step1()
        self.sendMessage(constants.COMMAND_SMP_1, buffer)


    def respondSMP(self, answer):
        self.smp = SMP(answer)
        self.__doSMPStep1(self.smpStep1)


    def run(self):
        if self.initiateHandkshakeOnStart:
            self.__initiateHandshake()
        else:
            self.__doHandshake()

        if not self.wasHandshakeDone:
            return

        while True:
            message = self.messageQueue.get()

            command = message.clientCommand
            payload = message.payload

            # Check if the client requested to end the connection
            if command == constants.COMMAND_END:
                self.connectionManager.destroyClient(self.remoteNick)
                self.errorCallback(self.remoteNick, errors.ERR_CONNECTION_ENDED)
                return
            # Ensure we got a valid command
            elif self.wasHandshakeDone and command not in constants.LOOP_COMMANDS:
                self.connectionManager.destroyClient(self.remoteNick)
                self.errorCallback(self.remoteNick, errors.ERR_INVALID_COMMAND)
                return

            # Decrypt the incoming data
            payload = self.__getDecryptedPayload(message)

            self.messageQueue.task_done()

            # Handle SMP commands specially
            if command in constants.SMP_COMMANDS:
               self.__handleSMPCommand(command, payload)
            else:
                self.recvMessageCallback(command, message.sourceNick, payload)


    def connect(self):
        self.__initiateHandshake()


    def disconnect(self):
        try:
            self.sendMessage(constants.COMMAND_END)
        except:
            pass


    def __doHandshake(self):
        try:
            # The caller of this function (should) checks for the initial HELO command

            # Send the ready command
            self.sendMessage(constants.COMMAND_REDY)

            # Receive the client's public key
            clientPublicKey = self.__getHandshakeMessagePayload(constants.COMMAND_PUBLIC_KEY)
            self.crypto.computeDHSecret(long(base64.b64decode(clientPublicKey)))

            # Send our public key
            publicKey = base64.b64encode(str(self.crypto.getDHPubKey()))
            self.sendMessage(constants.COMMAND_PUBLIC_KEY, publicKey)

            # Switch to AES encryption for the remainder of the connection
            self.isEncrypted = True

            self.wasHandshakeDone = True
            self.handshakeDoneCallback(self.remoteNick)
        except exceptions.ProtocolEnd:
            self.disconnect()
            self.connectionManager.destroyClient(self.remoteNick)
        except (exceptions.ProtocolError, exceptions.CryptoError) as e:
            self.__handleHandshakeError(e)


    def __initiateHandshake(self):
        try:
            # Send the hello command
            self.sendMessage(constants.COMMAND_HELO)

            # Receive the redy command
            self.__getHandshakeMessagePayload(constants.COMMAND_REDY)

            # Send our public key
            publicKey = base64.b64encode(str(self.crypto.getDHPubKey()))
            self.sendMessage(constants.COMMAND_PUBLIC_KEY, publicKey)

            # Receive the client's public key
            clientPublicKey = self.__getHandshakeMessagePayload(constants.COMMAND_PUBLIC_KEY)
            self.crypto.computeDHSecret(long(base64.b64decode(clientPublicKey)))

            # Switch to AES encryption for the remainder of the connection
            self.isEncrypted = True

            self.wasHandshakeDone = True
            self.handshakeDoneCallback(self.remoteNick)
        except exceptions.ProtocolEnd:
            self.disconnect()
            self.connectionManager.destroyClient(self.remoteNick)
        except (exceptions.ProtocolError, exceptions.CryptoError) as e:
            self.__handleHandshakeError(e)


    def __getHandshakeMessagePayload(self, expectedCommand):
        message = self.messageQueue.get()

        if message.clientCommand != expectedCommand:
            if message.clientCommand == constants.COMMAND_END:
                raise exceptions.ProtocolEnd
            elif message.clientCommand == constants.COMMAND_REJECT:
                raise exceptions.ProtocolError(errno=errors.ERR_CONNECTION_REJECTED)
            else:
                raise exceptions.ProtocolError(errno=errors.ERR_BAD_HANDSHAKE)

        payload = self.__getDecryptedPayload(message)
        self.messageQueue.task_done()

        return payload


    def __getDecryptedPayload(self, message):
        if self.isEncrypted:
            payload = message.getEncryptedPayloadAsBinaryString()
            encryptedMessageNumber = message.getMessageNumAsBinaryString()

            # Check the HMAC
            if not self.__verifyHmac(message.hmac, payload):
                self.errorCallback(message.sourceNick, errors.ERR_BAD_HMAC)
                raise exceptions.CryptoError(errno=errors.BAD_HMAC)

            try:
                # Check the message number
                messageNumber = int(self.crypto.aesDecrypt(encryptedMessageNumber))

                # If the message number is less than what we're expecting, the message is being replayed
                if self.incomingMessageNum > messageNumber:
                    raise exceptions.ProtocolError(errno=errors.ERR_MESSAGE_REPLAY)
                # If the message number is greater than what we're expecting, messages are being deleted
                elif self.incomingMessageNum < messageNumber:
                    raise exceptions.ProtocolError(errno=errors.ERR_MESSAGE_DELETION)
                self.incomingMessageNum += 1

                # Decrypt the payload
                payload = self.crypto.aesDecrypt(payload)
            except exceptions.CryptoError as ce:
                self.errorCallback(message.sourceNick, errors.ERR_BAD_DECRYPT)
                raise ce
        else:
            payload = message.payload

        return payload


    def __verifyHmac(self, givenHmac, payload):
        generatedHmac = self.crypto.generateHmac(payload)
        return utils.secureStrcmp(generatedHmac, base64.b64decode(givenHmac))


    def __handleSMPCommand(self, command, payload):
        try:
            if command == constants.COMMAND_SMP_0:
                # Fire the SMP request callback with the given question
                self.smpRequestCallback(constants.SMP_CALLBACK_REQUEST, self.remoteNick, payload)
            elif command == constants.COMMAND_SMP_1:
                # If there's already an smp object, go ahead to step 1.
                # Otherwise, save the payload until we have an answer from the user to respond with
                if self.smp:
                    self.__doSMPStep1(payload)
                else:
                    self.smpStep1 = payload
            elif command == constants.COMMAND_SMP_2:
                self.__doSMPStep2(payload)
            elif command == constants.COMMAND_SMP_3:
                self.__doSMPStep3(payload)
            elif command == constants.COMMAND_SMP_4:
                self.__doSMPStep4(payload)
            else:
                # This shouldn't happen
                raise exceptions.CryptoError(errno=errors.ERR_SMP_CHECK_FAILED)
        except exceptions.CryptoError as ce:
            self.smpRequestCallback(constants.SMP_CALLBACK_ERROR, self.remoteNick, '', ce.errno)


    def __doSMPStep1(self, payload):
        buffer = self.smp.step2(payload)
        self.sendMessage(constants.COMMAND_SMP_2, buffer)


    def __doSMPStep2(self, payload):
        buffer = self.smp.step3(payload)
        self.sendMessage(constants.COMMAND_SMP_3, buffer)


    def __doSMPStep3(self, payload):
        buffer = self.smp.step4(payload)
        self.sendMessage(constants.COMMAND_SMP_4, buffer)

        # Destroy the SMP object now that we're done
        self.smp = None


    def __doSMPStep4(self, payload):
        self.smp.step5(payload)

        if self.__checkSMP():
            self.smpRequestCallback(constants.SMP_CALLBACK_COMPLETE, self.remoteNick)

        # Destroy the SMP object now that we're done
        self.smp = None


    def __checkSMP(self):
        if not self.smp.match:
            raise exceptions.CryptoError(errno=errors.ERR_SMP_MATCH_FAILED)
        return True


    def __handleHandshakeError(self, exception):
        self.errorCallback(self.remoteNick, exception.errno)

        # For all errors except the connection being rejected, tell the client there was an error
        if exception.errno != errors.ERR_CONNECTION_REJECTED:
            self.sendMessage(constants.COMMAND_ERR)
        else:
            self.connectionManager.destroyClient(self.remoteNick)
Beispiel #9
0
    def __init__(self, server):
        Thread.__init__(self)
        self.daemon = True

        self.server = server
        self.crypto = Crypto(generateKeys=True)