Пример #1
0
    def update_user(username, data):
        """
        Method to update a user from the database

        :param username: Username that targets the user to be updated
        :param data: Data to be saved
        """

        hashed_username = base64.b64encode(
            Cryptography.hash(username).digest()).decode()

        with open(getcwd() + Database.__DB_FILENAME) as file_input,\
                open(getcwd() + Database.__DB_FILENAME + '.temp', 'w') as file_output:
            for entry in file_input:
                new_entry = entry
                if entry.split(':')[0] == hashed_username:
                    iv, ciphered_data = Cryptography.cipher(
                        Cryptography.get_passphrase(), data)
                    new_entry = hashed_username + ':' + ciphered_data.hex(
                    ) + '.' + iv.hex() + '\n'
                file_output.write(new_entry)
            if os.path.exists(getcwd() + Database.__DB_FILENAME):
                os.remove(getcwd() + Database.__DB_FILENAME)
                os.rename(getcwd() + Database.__DB_FILENAME + '.temp',
                          getcwd() + Database.__DB_FILENAME)
Пример #2
0
    def update_client(username, hostname, port, cert):
        """
        Method to update a client from the database

        :param username: Username that targets the client to be updated
        :param hostname: Hostname to be updated
        :param port: Port to be updated
        :param cert: Certificate to be updated
        """

        hashed_username = base64.b64encode(
            Cryptography.hash(username).digest()).decode()
        data = f'{hostname}:{port}:{cert}'
        with open(getcwd() + ClientsStore.__DB_FILENAME) as file_input, \
                open(getcwd() + ClientsStore.__DB_FILENAME + '.temp', 'w') as file_output:
            for entry in file_input:
                new_entry = entry
                if entry.split(':')[0] == hashed_username:
                    iv, ciphered_data = Cryptography.cipher(
                        Cryptography.get_passphrase(), data)
                    new_entry = hashed_username + ':' + ciphered_data.hex(
                    ) + '.' + iv.hex() + '\n'
                file_output.write(new_entry)
            if path.exists(getcwd() + ClientsStore.__DB_FILENAME):
                remove(getcwd() + ClientsStore.__DB_FILENAME)
                rename(getcwd() + ClientsStore.__DB_FILENAME + '.temp',
                       getcwd() + ClientsStore.__DB_FILENAME)
Пример #3
0
    def get_client(username):
        """
        Method to fetch a User's Client

        :param username: User whose Client will be fetch
        :return: Client's data
        """

        data = None
        hashed_username = base64.b64encode(
            Cryptography.hash(username).digest()).decode()
        with open(getcwd() + ClientsStore.__DB_FILENAME, 'r') as f:
            for entry in f:
                parts = entry.split(':')
                if parts[0] == hashed_username:
                    material = parts[1].split('.')
                    ciphertext = bytearray.fromhex(material[0])
                    iv = bytearray.fromhex(material[1])
                    data = Cryptography.decipher(Cryptography.get_passphrase(),
                                                 ciphertext, iv).decode()
        client_info = data.split(':')

        return {
            'hostname': client_info[0],
            'port': client_info[1],
            'cert': client_info[2]
        }
Пример #4
0
    def register_user(client_socket, parts):
        """
        Method to register users and their clients

        :param client_socket: Socket where a connection with a client is happening
        :param parts: Parts of the message that was sent by the client
        """

        username = parts[1]
        one_time_id = parts[2]
        signature = base64.b64decode(parts[3])
        hostname = parts[4]
        port = parts[5]
        client_cert = parts[6]

        valid_signature = Cryptography.verify_signature(
            base64.b64decode(client_cert).decode(), one_time_id, signature)

        if valid_signature and User.login(username, one_time_id):
            ClientsStore.save_client(username, hostname, port, client_cert)
            ClientsStore.set_online(username, hostname, port)
            Administration.__socket_map[client_socket] = username
            client_socket.send('OK'.encode())
        else:
            client_socket.send('NOTOK'.encode())
Пример #5
0
    def register_client(client, server):
        """
        Method to login a user in the server

        :param client: Client instance, whose properties can be fetched
        :param server: Server connection
        """

        username = input('Please insert the username:\n> ')
        one_time_id = input('Please insert the One Time ID:\n> ')

        signed_one_time_id = base64.b64encode(
            Cryptography.sign(Connection.get_key(), one_time_id)).decode()

        server.send(
            f'LOGIN:{username}:{one_time_id}:{signed_one_time_id}:{client.get_hostname()}'
            f':{str(client.get_port())}:{Connection.get_cert()}'.encode())
        response = server.recv(100000).decode()
        if response == 'OK':
            pin = input('Please insert your PIN:\n> ')
            client.save_pin(username, pin)
            client.set_username(username)
            print('Login successful and PIN set')
            return True
        else:
            print('Login was not successful, failed on the server')
            return False
Пример #6
0
    def list_users(client, server):
        """
        Method that accepts list requests

        :param client: Client instance, whose properties can be fetched
        :param server: Server connection
        """

        signed_username = base64.b64encode(
            Cryptography.sign(Connection.get_key(),
                              client.get_username())).decode()
        server.send(f'LIST:{client.get_username()}:{signed_username}'.encode())
        response = server.recv(100000000)
        if response[0] != 0x80:
            if response.decode() == 'UNAUTHORIZED':
                print("You don't have permissions to perform this operation!")
                return None

        user_list = pickle.loads(response)
        if len(user_list) > 0:
            print('Online users are:')
            for user in user_list:
                print('> ' + user['username'])
                client.add_user(user['username'], user['hostname'],
                                user['port'], user['cert'])
        else:
            print('No users online!')
Пример #7
0
    def perform_root(client, server, number, n):
        """
        Method to ask the server to calculate a root of a number

        :param client: Client instance, whose properties can be fetched
        :param server: Server connection that will be used to ask for the operation
        :param number: Server number on which the root will be calculated
        :param n: N of the root that needs to be computed
        :return: Result of the number's N root
        """

        signed_username = base64.b64encode(
            Cryptography.sign(Connection.get_key(),
                              client.get_username())).decode()
        server.send(
            f'OP:{client.get_username()}:{signed_username}:{n}:{number}'.
            encode())
        response = server.recv(100000).decode()
        if response == 'UNAUTHORIZED':
            print("You don't have permissions to perform this operation!")
            return None
        if response == 'INVALID':
            print("The values you inserted are not valid!")
            return None
        return float(response)
Пример #8
0
    def create():
        """
        Static method to create a new user. This method asks the system administrator for the relevant information

        :return: User's username, User's one time id
        """

        full_name = input('Please insert the User\'s full name: ')
        email = input('Please insert the User\'s email: ')
        username = ''
        username_exists = True
        # Username needs to have 12 characters at most
        while len(username) > 12 or username_exists:
            username = input(
                'Please insert the User\'s username(max of 12 characters): ')
            username_exists = Database.username_exists(username)
            if username_exists:
                print('Username already exists! Please choose another.')
        clearance_level = 0
        # clearance level must be between 1 and 3
        while 1 > clearance_level or clearance_level > 3:
            clearance_level = int(
                input('Please insert the User\'s clearance level[1-3]: '))

        one_time_id = generate_one_time_id()

        # Creates a new user with all the information
        user = User(full_name, email, username, clearance_level,
                    Cryptography.hash_data(one_time_id))
        # Saves user to the database
        user_data = json.dumps(user.to_dictionary())
        Database.save_user(user.username, user_data)

        return username, one_time_id
Пример #9
0
    def save_user(username, data):
        """
        Method to save a user into the database

        :param username: Username used as the index
        :param data: Data to be saved
        """

        hashed_username = base64.b64encode(
            Cryptography.hash(username).digest()).decode()

        file = open(getcwd() + Database.__DB_FILENAME, 'a')
        iv, ciphered_data = Cryptography.cipher(Cryptography.get_passphrase(),
                                                data)
        file.write(hashed_username + ':' + ciphered_data.hex() + '.' +
                   iv.hex() + '\n')
        file.flush()
        file.close()
Пример #10
0
    def save_client(username, hostname, port, cert):
        """
        Method to save a new client that is currently online

        :param username: Username of the user that is using the client
        :param hostname: Client's hostname
        :param port: Client's port
        :param cert: Client's certificate
        """

        data = f'{hostname}:{port}:{cert}'
        hashed_username = base64.b64encode(
            Cryptography.hash(username).digest()).decode()
        file = open(getcwd() + ClientsStore.__DB_FILENAME, 'a')
        iv, ciphered_data = Cryptography.cipher(Cryptography.get_passphrase(),
                                                data)
        file.write(hashed_username + ':' + ciphered_data.hex() + '.' +
                   iv.hex() + '\n')
        file.flush()
        file.close()
Пример #11
0
    def verify_pin(username, pin):
        """
        Method to verify the PIN inserted

        :return: True if it is the same as the one saved, false otherwise
        """

        with open(Client._LOCAL_DATA_FILE, 'r') as f:
            pin_hash = f.readline().strip()
        f.close()

        return Cryptography.verify_hash(f'{username}:{pin}', pin_hash)
Пример #12
0
    def load_user(username):
        """
        Method to load a user information given a username

        :param username: User's username to be be loaded
        :return: User's information
        """

        hashed_username = base64.b64encode(
            Cryptography.hash(username).digest()).decode()

        with open(getcwd() + Database.__DB_FILENAME, 'r') as f:
            for entry in f:
                parts = entry.split(':')
                if parts[0] == hashed_username:
                    material = parts[1].split('.')
                    ciphertext = bytearray.fromhex(material[0])
                    iv = bytearray.fromhex(material[1])
                    return Cryptography.decipher(Cryptography.get_passphrase(),
                                                 ciphertext, iv)
        f.close()
        return None
Пример #13
0
    def save_message(message):
        """
        Method to persist a message

        :param message: Message to be saved
        """

        file = open(Client._LOCAL_DATA_FILE, 'a')
        iv, ciphered_data = Cryptography.cipher(f'{Client.get_pin(): <32}',
                                                message)
        file.write(ciphered_data.hex() + '.' + iv.hex() + '\n')
        file.flush()
        file.close()
Пример #14
0
    def save_pin(username, pin):
        """
        Method to persist the user's PIN

        :param username: Username to be saved into the filesystem
        :param pin: PIN to be saved into the filesystem
        """

        hashed_pin = Cryptography.hash_data(f'{username}:{pin}')
        with open(Client._LOCAL_DATA_FILE, 'w') as f:
            f.write(hashed_pin.hex() + '\n')
        f.close()
        Client.set_pin(pin)
Пример #15
0
    def run_administration(server):
        """
        Method that runs the administration panel

        :param server: Server instance, whose properties can be fetched
        """

        if Cryptography.get_passphrase() == "":
            while len(Cryptography.get_passphrase()) != 32:
                passphrase = input(
                    "Please insert the server's passphrase (32 characters): ")
                Cryptography.set_passphrase(passphrase)
        """
        Method to start the menu used by the administrator
        """

        banner = """What do you want to do?
    1 - Create user
    2 - Quit
    > """
        print('Welcome to the administration panel!')
        while True:
            option = int(input(banner))
            if option == 1:
                username, one_time_id = User.create()
                print(
                    f'\nUser created with success!\n\tUsername: {username}\n\tOne Time ID: {one_time_id}\n\n'
                )
            elif option == 2:
                print('Quitting server...')
                logging.info('Quitting server...')
                Administration.RUNNING = False
                socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(
                    (server.get_hostname(), server.get_port()))
                _thread.interrupt_main()
                quit(0)
            else:
                print('Option not valid! Try again.')
Пример #16
0
    def list_users(client_socket, parts):
        username = parts[1]
        signature = base64.b64decode(parts[2])

        user = User.load_user(username)
        client = ClientsStore.get_client(username)

        valid_signature = Cryptography.verify_signature(
            base64.b64decode(client['cert']).decode(), username, signature)

        if valid_signature:
            user_list = ClientsStore.list_users(username,
                                                user.get_clearance_level())
            encoded_list = pickle.dumps(user_list)
            client_socket.send(encoded_list)

        else:
            client_socket.send('UNAUTHORIZED'.encode())
Пример #17
0
    def client_exists(username):
        """
        Method to check if a given user is online (has a registered client online)

        :param username: Username whose connection will be check
        :return: True if the user has a client stored, False if it doesn't
        """

        hashed_username = base64.b64encode(
            Cryptography.hash(username).digest()).decode()

        if path.exists(getcwd() + ClientsStore.__DB_FILENAME):
            with open(getcwd() + ClientsStore.__DB_FILENAME, 'r') as f:
                for entry in f:
                    parts = entry.split(':')
                    if parts[0] == hashed_username:
                        return True
                return False
        else:
            return False
Пример #18
0
    def username_exists(username):
        """
        Method to check if a user exists in the database

        :param username: Username whose existence will be check
        :return: True if the user with that username exists, False otherwise
        """

        hashed_username = base64.b64encode(
            Cryptography.hash(username).digest()).decode()

        if os.path.exists(getcwd() + Database.__DB_FILENAME):
            with open(getcwd() + Database.__DB_FILENAME, 'r') as f:
                for entry in f:
                    parts = entry.split(':')
                    if parts[0] == hashed_username:
                        return True
                return False
        else:
            return False
Пример #19
0
    def perform_operations(client_socket, parts):
        """
        Method to execute the privileged operations

        :param client_socket: Socket where a connection with a client is happening
        :param parts: Parts of the message that was sent by the client
        """

        username = parts[1]
        signature = base64.b64decode(parts[2])
        n = int(parts[3])
        number = int(parts[4])
        user = User.load_user(username)
        client = ClientsStore.get_client(username)

        valid_signature = Cryptography.verify_signature(
            base64.b64decode(client['cert']).decode(), username, signature)
        if n <= 0.0:
            client_socket.send('INVALID'.encode())
            return

        if valid_signature:
            clearance = user.get_clearance_level()
            if clearance == 1 and n > 2:
                client_socket.send('UNAUTHORIZED'.encode())
                return
            if clearance == 2 and n > 3:
                client_socket.send('UNAUTHORIZED'.encode())
                return
            if n == 2:
                result = Functions.square_root(number)
            elif n == 3:
                result = Functions.cubic_root(number)
            else:
                result = Functions.n_root(number, n)

            client_socket.send(str(result).encode())
        else:
            client_socket.send('UNAUTHORIZED'.encode())
Пример #20
0
    def login(username, one_time_id):
        """
        Method to perform a login of a user

        :param username: User that we want to perform the challenge on
        :param one_time_id: One Time ID passed to perform the login
        :return: True if the username and one time id combination match, false otherwise
        """

        user = User.load_user(username)
        # Checks if a user was found (and hence, is not None), the one time id passed matches with the one stored and
        # did not yet performed any other login with this one time id
        if user is not None and Cryptography.verify_hash(
                one_time_id, user.one_time_id_hash) and not user.login_done:
            user.login_done = True
            # Save change to the database
            user_data = json.dumps(user.to_dictionary())
            Database.update_user(user.username, user_data)
            return True

        if user is not None and user.login_done:
            logging.debug(f'Login retry on {username}')
        return False