Ejemplo n.º 1
0
    def authenticate_as_client(self, session_socket):
        # authenticates an external server connected via session_socket

        iv = self.receive_iv(session_socket)
        master_encrypter = Encrypter(self.master_key, iv)
        m = Messenger(session_socket, master_encrypter, self.continueHandler)

        client_challenge = genStr(CHALLENGE_LENGTH)
        client_challenge_hash = str(create_key(client_challenge))
        hash_len = len(client_challenge_hash)
        secretA = generateAorB()
        publicA = pow(g, secretA, p)
        m.send(client_challenge + str(publicA))

        response = m.recv()
        while not response:
            response = m.recv()

        if response[:hash_len] != client_challenge_hash:
            m.close()
            raise Exception('client could not authenticate')

        server_challenge_hash = str(create_key(response[hash_len:hash_len + CHALLENGE_LENGTH]))
        m.send(server_challenge_hash)
        public_b = int(response[hash_len + CHALLENGE_LENGTH:])
        self.log.info('g^b mod p is {}'.format(public_b))
        session_key = create_key(str(pow(public_b, secretA, p)))
        self.log.info('Session key generated by the client is {}'.format(session_key))

        session_encrypter = Encrypter(session_key, iv)
        session_m = Messenger(session_socket, session_encrypter, self.continueHandler)

        self._messenger = session_m
Ejemplo n.º 2
0
def _test_chain_execution(session):
    def job1(outbox, params):
        print 'did 1'
        outbox.send('do_2')

    def job2(outbox, params):
        print 'did 1'
        outbox.send('do_3')

    def job3(outbox, params):
        print 'did 1'
        outbox.send('done')

    disp = Dispatcher()
    disp.register('do_1', job1)
    disp.register('do_2', job2)
    disp.register('do_3', job3)
    disp.start()
    try:
        messenger = Messenger(session)  # db.get_session())
        assert not messenger.recv()
        messenger.send('do_1')
        messenger.subscribe('done')
        import time
        time.sleep(1)
        assert messenger.recv()
    finally:
        disp.stop()
Ejemplo n.º 3
0
    def _run(self):
        messenger = Messenger(db.get_session())
        running_jobs = set()

        for dest in self._mapping:
            messenger.subscribe(dest)

        counter = 0
        while self._running:
            print 'counter = ', counter
            counter += 1
            messages = messenger.recv()
            for msg in messages:
                running_jobs.add((msg, self._dispatch_job(msg)))

            gevent.sleep(0.01)
            done = gevent.joinall(
                [j[1] for j in running_jobs],
                timeout=0,
            )

            for j in done:
                for msg, job in running_jobs:
                    if j == job:
                        running_jobs.remove((msg, job))
                        messenger.retire(msg.id)
                        break

            while self._outgoing_messages:
                to, params = self._outgoing_messages.pop()
                messenger.send(to, **params)
Ejemplo n.º 4
0
def test_recv_twice(session):
    m = Messenger(session)
    m.send('test_recv_twice', a='a', b=1)
    m.subscribe('test_recv_twice')

    assert len(m.recv()) == 1
    assert len(m.recv()) == 0
Ejemplo n.º 5
0
def test_retire(session):
    m = Messenger(session)
    sent_id = m.send('test_retire', a='a', b=1)
    m.subscribe('test_retire')
    m.retire(sent_id)

    assert not m.recv()
Ejemplo n.º 6
0
	def handleConnection(self, client_sock):
		while True:
			req = Messenger.recv(client_sock)
			if req is None:
				break
			t = threading.Thread(target=self.handleReq, args=(req,))
			t.start()
Ejemplo n.º 7
0
 def handleConnection(self, client_sock):
     while True:
         req = Messenger.recv(client_sock)
         if req is None:
             raise ConnectionError(
                 'Something went wrong with the connection')
         t = threading.Thread(target=self.handleReq, args=(req, ))
         t.start()
Ejemplo n.º 8
0
def test_recv(session):
    m = Messenger(session)
    sent_id = m.send('test_recv', a='a', b=1)
    m.subscribe('test_recv')
    incoming = m.recv()

    assert len(incoming) == 1
    mm = incoming.pop()
    assert mm.id == sent_id
    assert mm.destination == 'test_recv'
    assert len(mm.params) == 2
    assert mm.params.a == 'a'
    assert mm.params.b == 1
Ejemplo n.º 9
0
 def handleConnection(self, req_sock):
     while True:
         req = Messenger.recv(req_sock)
         if req == None:
             break
         if verbose:
             print("Recv msg {0}\n".format(req))
         body = req['body']
         if req['msg_type'] == MSG.DECISION:
             if self.cntr < self.global_config['client']['num_txns']:
                 self.recvDecision(body['final_decision'])
             else:
                 self.logResults()
                 break
Ejemplo n.º 10
0
    def authenticate_as_server(self, session_socket):
        # authenticates an external client connected via session_socket

        iv = self.generate_and_send_iv(session_socket) # the server should generate a random iv

        master_encrypter = Encrypter(self.master_key, iv)
        m_messenger = Messenger(session_socket, master_encrypter, self.continueHandler)

        secret_b = generateAorB()
        public_b = str(pow(g, secret_b, p))
        server_challenge = genStr(CHALLENGE_LENGTH)
        server_challenge_hash = str(create_key(server_challenge))

        response = m_messenger.recv()
        while not response:
            response = m_messenger.recv()

        client_challenge = response[:CHALLENGE_LENGTH]
        client_challenge_hash = str(create_key(client_challenge))
        public_a = response[CHALLENGE_LENGTH:]
        self.log.info('publicA is {}'.format(public_a))
        m_messenger.send(client_challenge_hash + server_challenge + public_b)
        session_key = create_key(str(pow(int(public_a), secret_b, p)))
        self.log.info('session key is {}'.format(session_key))

        response = m_messenger.recv()
        while not response:
            response = m_messenger.recv()

        if response != server_challenge_hash:
            self.log.warn('Client could not be authenticated. Session will be terminated!')
            m_messenger.close()
        else:
            print('Server Authentication Successful!!!')

        session_encrypter = Encrypter(session_key, iv)
        self._messenger = Messenger(session_socket, session_encrypter, self.continueHandler)
Ejemplo n.º 11
0
def thread_client(conn, addr, db_conn, active_clients):
    """
    Checks and verifies password/username, and handles adding new
    users to the database.

    Main client loop Accepts messages from client socket then
    broadcasts message to all clients. If the connection is broken
    the loop will break, database will be updated(active state).

    :param conn: socket objected connected with remote client
    :param addr: tuple of the remote clients address and port
    :param db_conn: connection to the sqlite3 database containing user-info
    """

    length_struct = struct.Struct("!I")
    local_messenger = Messenger(conn, length_struct)
    lock = _thread.allocate_lock()
    verified = False  # used to control looping

    while not verified:  # handle client login/signup credentials
        try:
            """
            first message received will be a login or sign up attempt
            message_type will be "LOGIN" or "SIGNUP"
            """
            message = local_messenger.recv()
            message_type, username, password = message.split("`", 2)
        except ValueError or ConnectionResetError:
            print("bad connection at {}".format(addr))
            break

        # retrieve user info from database. username_check() returns two boolean values
        lock.acquire()
        username_exists, correct_password = username_check(db_conn, username, password)
        lock.release()

        # add new users to database
        if message_type == "SIGNUP":
            if username_exists:  # username already taken
                local_messenger.send("UNAVAILABLE")
            else:
                # acquire lock and add user to database and active_clients
                lock.acquire()
                new_user(db_conn, username, password)
                active_clients[username] = conn
                lock.release()

                local_messenger.send("OK")
                verified = True

        # login existing users
        elif message_type == "LOGIN":
            if username_exists and correct_password:
                if username not in active_clients:  # username is not already signed in
                    # acquire lock and add username to active_clients
                    lock.acquire()
                    active_clients[username] = conn
                    lock.release()

                    local_messenger.send("OK")
                    verified = True
                else:
                    local_messenger.send("USER_ACTIVE")  # user is already active
            else:
                local_messenger.send("BAD")  # wrong password or username

    while verified:
        """
        client will only be verified when an existing username and password have been
        submitted, or a new username and password has been created.

        verified loop will handle all incoming messages, errors, socket closures
        """
        try:
            message = local_messenger.recv()
        except socket.error or struct.error:
            print("bad connection at {}".format(addr))
            break

        if message:
            lock.acquire()
            local_messenger.broadcast(active_clients, message)
            lock.release()
        else:
            # empty string signaling connection closed
            lock.acquire()
            del active_clients[username]
            lock.release()
            conn.close()
            break

    # clean up after client disconnects or the connection is broken
    if username in active_clients:
        lock.acquire()
        del active_clients[username]
        lock.release()
    conn.close()
    print("{} DISCONNECTED".format(addr))
Ejemplo n.º 12
0
class App(tkinter.Tk):
    def __init__(self):
        super().__init__()
        self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.protocol("WM_DELETE_WINDOW", lambda: destroy_all(self.connection, self))
        self.title("Chat Client")

        self.length_struct = struct.Struct("!I")
        self.messenger = Messenger(self.connection, self.length_struct)

        self.username = ""
        self.password = ""

        self.connect = ConnectScreen(self, self.connect_to_server)
        self.login = LoginScreen(self, self.check_data)
        self.chat = ChatScreen(self, self.handle_out_going)

        self.connect.pack()
        self.connect.pack_children()

    def connect_to_server(self):
        """
        Callback for self.connect. Retrieves the user submitted address
        and port. Attempts to make connection. If any errors are caught the
        connect_message widget will be updated with information about the error.
        """
        host_address = self.connect.ip_entry.get()
        host_port = self.connect.port_entry.get()

        try:
            host_port = int(host_port)
            self.connection.connect((host_address, host_port))
            self.connect.pack_forget()
            self.login.pack()
            self.login.pack_children()
        except ValueError:
            self.connect.connect_message.config(text="Invalid Entry For Port\nMust Be an Integer", fg="red")
        except ConnectionRefusedError:
            self.connect.connect_message.config(text="Server Refused Connection", fg="red")
        except socket.gaierror:
            self.connect.connect_message.config(text="Invalid Address", fg="red")

    def check_data(self, message_type):
        """
        Communicates with chat server to verify login information. If the
        login or sign up attempt fails a message is displayed on the login
        screen.

        :param message_type: tells the server whether it is a login attempt
        or signup request
        """
        self.username = self.login.name_entry.get()
        self.password = self.login.pass_entry.get()

        # restrict user names to alpha numeric values
        if not self.username.isalnum():
            self.login.display_message.config(text="Username can only be numbers and letters", fg="red")
            return

        # format message to be sent
        message = "{}`{}`{}".format(message_type, self.username, self.password)
        reply = ""

        # try communicating with server
        try:
            self.messenger.send(message)
            reply = self.messenger.recv()
        except ConnectionResetError or ValueError:
            self.login.display_message.config(text="Connection with server lost...restarting", fg="red")
            self.login.pack_forget()
            self.connection.detach()
            self.connect.pack()

        # check for all possible server responses
        if reply == "OK":
            self.login.pack_forget()
            self.title(self.username)
            self.chat.pack()
            self.chat.pack_children()
            self.connection.settimeout(.10)  # prevents blocking calls of handle_incoming()
            self.handle_incoming()
        elif reply == "UNAVAILABLE":
            self.login.display_message.config(text="Username Unavailable", fg="red")
        elif reply == "BAD":
            self.login.display_message.config(text="Incorrect user Info", fg="red")
        elif reply == "USER ACTIVE":
            self.login.display_message.config(text="Username is currently already logged in", fg="red")
        else:
            self.login.display_message.config(text="Unexpected Server Response")

    def handle_out_going(self, event=None):
        """
        reads from the chat_entry and sends it to the server.

        :param event: is used as a place holder for the event
        information sent by self.chat_entry.bind(<RETURN>) it is not
        used.
        """
        text = self.chat.chat_entry.get()

        if text:  # prevent empty messages from being sent
            try:
                message = "{}: {}".format(self.username, text)  # This should be handled by server
                self.messenger.send(message)
                self.chat.chat_entry.delete(0, "end")
            except ConnectionResetError:
                self.chat.pack_forget()
                self.login.pack()
                self.login.display_message.config(text="Connection with server lost")

    def handle_incoming(self):
        """
        called every 500 milliseconds from within the
        tkinter mainloop. Will check for incoming socket
        data, but will pass if socket timeout limit is
        reached.
        """
        try:
            message = self.messenger.recv()
            self.chat.add_message(message)
        except socket.timeout:
            pass
        except ConnectionResetError or struct.error:
            self.chat.pack_forget()
            self.login.pack()
            self.login.display_message.config(text="Connection with server lost")
            return
        finally:
            self.after(500, self.handle_incoming)
Ejemplo n.º 13
0
class SessionManager:
    def __init__(self, port, ip_address, secret_value, continueHandler):
        # can be either a server or client. if ip_address=None, be a server on port. Otherwise, try to connect to
        # ip_address:port

        self.port = port
        self.ip_address = ip_address
        self.master_key = create_key(secret_value)
        self.log = logging.getLogger(__name__)
        self.continueHandler = continueHandler

        self._messenger = None
        self.reset_messenger()

    def generate_and_send_iv(self, session_socket):
        iv = urandom(16)

        self.continueHandler(iv)
        # send iv over socket first!
        sent_len = 0
        while sent_len < len(iv):
            sent = session_socket.send(iv[sent_len:])
            if sent == 0:
                raise RuntimeError("socket send connection issue")
            sent_len += sent  # how much of the message we have sent
        logging.getLogger(__name__).info("sent iv: " + str(iv))
        return iv

    def receive_iv(self, session_socket):
        iv = b''
        while len(iv) < IV_LENGTH:
            chunk = session_socket.recv(IV_LENGTH - len(iv))
            if chunk == b'':
                session_socket.close()
                raise RuntimeError("socket closed")
            iv += chunk
        logging.getLogger(__name__).info('received iv: {}'.format(str(iv)))
        return iv

    def authenticate_as_server(self, session_socket):
        # authenticates an external client connected via session_socket

        iv = self.generate_and_send_iv(session_socket) # the server should generate a random iv

        master_encrypter = Encrypter(self.master_key, iv)
        m_messenger = Messenger(session_socket, master_encrypter, self.continueHandler)

        secret_b = generateAorB()
        public_b = str(pow(g, secret_b, p))
        server_challenge = genStr(CHALLENGE_LENGTH)
        server_challenge_hash = str(create_key(server_challenge))

        response = m_messenger.recv()
        while not response:
            response = m_messenger.recv()

        client_challenge = response[:CHALLENGE_LENGTH]
        client_challenge_hash = str(create_key(client_challenge))
        public_a = response[CHALLENGE_LENGTH:]
        self.log.info('publicA is {}'.format(public_a))
        m_messenger.send(client_challenge_hash + server_challenge + public_b)
        session_key = create_key(str(pow(int(public_a), secret_b, p)))
        self.log.info('session key is {}'.format(session_key))

        response = m_messenger.recv()
        while not response:
            response = m_messenger.recv()

        if response != server_challenge_hash:
            self.log.warn('Client could not be authenticated. Session will be terminated!')
            m_messenger.close()
        else:
            print('Server Authentication Successful!!!')

        session_encrypter = Encrypter(session_key, iv)
        self._messenger = Messenger(session_socket, session_encrypter, self.continueHandler)

    def authenticate_as_client(self, session_socket):
        # authenticates an external server connected via session_socket

        iv = self.receive_iv(session_socket)
        master_encrypter = Encrypter(self.master_key, iv)
        m = Messenger(session_socket, master_encrypter, self.continueHandler)

        client_challenge = genStr(CHALLENGE_LENGTH)
        client_challenge_hash = str(create_key(client_challenge))
        hash_len = len(client_challenge_hash)
        secretA = generateAorB()
        publicA = pow(g, secretA, p)
        m.send(client_challenge + str(publicA))

        response = m.recv()
        while not response:
            response = m.recv()

        if response[:hash_len] != client_challenge_hash:
            m.close()
            raise Exception('client could not authenticate')

        server_challenge_hash = str(create_key(response[hash_len:hash_len + CHALLENGE_LENGTH]))
        m.send(server_challenge_hash)
        public_b = int(response[hash_len + CHALLENGE_LENGTH:])
        self.log.info('g^b mod p is {}'.format(public_b))
        session_key = create_key(str(pow(public_b, secretA, p)))
        self.log.info('Session key generated by the client is {}'.format(session_key))

        session_encrypter = Encrypter(session_key, iv)
        session_m = Messenger(session_socket, session_encrypter, self.continueHandler)

        self._messenger = session_m

    def reset_messenger(self):
        if self._messenger is not None:
            self._messenger.close()
            self._messenger = None

        # AF_INET = ipv4, SOCK_STREAM = tcp
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # assuming we can use the same "client socket" for both reading and writing
        if self.ip_address is None:  # server init
            s.bind(('', self.port))
            self.log.info("Listening for connection on port {}".format(self.port))
            s.listen(1) # listen for only one connection

            session_socket, addr = s.accept()
            self.log.info("Accepted connection from {}".format(addr))

            self.authenticate_as_server(session_socket)
            s.close()
        else:
            # client init: specify ip address and port to try to ping
            self.log.info("Trying to connect to {}:{}".format(self.ip_address, self.port))
            s.connect((self.ip_address, self.port))

            self.authenticate_as_client(s)


    def checkReceivedMessages(self):
        try:
            nextReceivedMessage = self.recv()
            # Get and Send Messages
            return nextReceivedMessage
        except Exception as e:
            self.log.warning("Session closed: {}".format(e))
            self.reset_messenger()
            # Return 0 as default
            return 0  
               

    def send(self, msg):
        self._messenger.send(msg)

    def recv(self):
        data_in = self._messenger.recv()
        if len(data_in) > 0:
            self.log.info('received data: ' + data_in)
        return data_in

    def close(self):
        self._messenger.close()
Ejemplo n.º 14
0
def test_empty_recv(session):
    m = Messenger(session)
    assert not m.recv()
Ejemplo n.º 15
0
class App(tkinter.Tk):
    def __init__(self):
        super().__init__()
        self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.protocol("WM_DELETE_WINDOW",
                      lambda: destroy_all(self.connection, self))
        self.title("Chat Client")

        self.length_struct = struct.Struct("!I")
        self.messenger = Messenger(self.connection, self.length_struct)

        self.username = ""
        self.password = ""

        self.connect = ConnectScreen(self, self.connect_to_server)
        self.login = LoginScreen(self, self.check_data)
        self.chat = ChatScreen(self, self.handle_out_going)

        self.connect.pack()
        self.connect.pack_children()

    def connect_to_server(self):
        """
        Callback for self.connect. Retrieves the user submitted address
        and port. Attempts to make connection. If any errors are caught the
        connect_message widget will be updated with information about the error.
        """
        host_address = self.connect.ip_entry.get()
        host_port = self.connect.port_entry.get()

        try:
            host_port = int(host_port)
            self.connection.connect((host_address, host_port))
            self.connect.pack_forget()
            self.login.pack()
            self.login.pack_children()
        except ValueError:
            self.connect.connect_message.config(
                text="Invalid Entry For Port\nMust Be an Integer", fg="red")
        except ConnectionRefusedError:
            self.connect.connect_message.config(
                text="Server Refused Connection", fg="red")
        except socket.gaierror:
            self.connect.connect_message.config(text="Invalid Address",
                                                fg="red")

    def check_data(self, message_type):
        """
        Communicates with chat server to verify login information. If the
        login or sign up attempt fails a message is displayed on the login
        screen.

        :param message_type: tells the server whether it is a login attempt
        or signup request
        """
        self.username = self.login.name_entry.get()
        self.password = self.login.pass_entry.get()

        # restrict user names to alpha numeric values
        if not self.username.isalnum():
            self.login.display_message.config(
                text="Username can only be numbers and letters", fg="red")
            return

        # format message to be sent
        message = "{}`{}`{}".format(message_type, self.username, self.password)
        reply = ""

        # try communicating with server
        try:
            self.messenger.send(message)
            reply = self.messenger.recv()
        except ConnectionResetError or ValueError:
            self.login.display_message.config(
                text="Connection with server lost...restarting", fg="red")
            self.login.pack_forget()
            self.connection.detach()
            self.connect.pack()

        # check for all possible server responses
        if reply == "OK":
            self.login.pack_forget()
            self.title(self.username)
            self.chat.pack()
            self.chat.pack_children()
            self.connection.settimeout(
                .10)  # prevents blocking calls of handle_incoming()
            self.handle_incoming()
        elif reply == "UNAVAILABLE":
            self.login.display_message.config(text="Username Unavailable",
                                              fg="red")
        elif reply == "BAD":
            self.login.display_message.config(text="Incorrect user Info",
                                              fg="red")
        elif reply == "USER ACTIVE":
            self.login.display_message.config(
                text="Username is currently already logged in", fg="red")
        else:
            self.login.display_message.config(
                text="Unexpected Server Response")

    def handle_out_going(self, event=None):
        """
        reads from the chat_entry and sends it to the server.

        :param event: is used as a place holder for the event
        information sent by self.chat_entry.bind(<RETURN>) it is not
        used.
        """
        text = self.chat.chat_entry.get()

        if text:  # prevent empty messages from being sent
            try:
                message = "{}: {}".format(
                    self.username, text)  # This should be handled by server
                self.messenger.send(message)
                self.chat.chat_entry.delete(0, "end")
            except ConnectionResetError:
                self.chat.pack_forget()
                self.login.pack()
                self.login.display_message.config(
                    text="Connection with server lost")

    def handle_incoming(self):
        """
        called every 500 milliseconds from within the
        tkinter mainloop. Will check for incoming socket
        data, but will pass if socket timeout limit is
        reached.
        """
        try:
            message = self.messenger.recv()
            self.chat.add_message(message)
        except socket.timeout:
            pass
        except ConnectionResetError or struct.error:
            self.chat.pack_forget()
            self.login.pack()
            self.login.display_message.config(
                text="Connection with server lost")
            return
        finally:
            self.after(500, self.handle_incoming)