Exemple #1
0
def log_command(user_input: 'UserInput', window: 'TxWindow',
                contact_list: 'ContactList', group_list: 'GroupList',
                settings: 'Settings', c_queue: 'Queue',
                master_key: 'MasterKey') -> None:
    """Display message logs or export them to plaintext file on TxM/RxM.

    TxM processes sent messages, RxM processes sent and
    received messages for all participants in active window.
    """
    cmd = user_input.plaintext.split()[0]

    export, header = dict(export=(True, LOG_EXPORT_HEADER),
                          history=(False, LOG_DISPLAY_HEADER))[cmd]

    try:
        msg_to_load = int(user_input.plaintext.split()[1])
    except ValueError:
        raise FunctionReturn("Error: Invalid number of messages.")
    except IndexError:
        msg_to_load = 0

    if export and not yes(
            f"Export logs for '{window.name}' in plaintext?", head=1, tail=1):
        raise FunctionReturn("Logfile export aborted.")

    try:
        command = header + window.uid.encode() + US_BYTE + int_to_bytes(
            msg_to_load)
    except struct.error:
        raise FunctionReturn("Error: Invalid number of messages.")

    queue_command(command, settings, c_queue)

    access_logs(window, contact_list, group_list, settings, master_key,
                msg_to_load, export)
Exemple #2
0
def log_command(cmd_data: bytes, ts: 'datetime', window_list: 'WindowList',
                contact_list: 'ContactList', group_list: 'GroupList',
                settings: 'Settings', master_key: 'MasterKey') -> None:
    """Display or export log file for the active window.

    Having the capability to export the log file from the encrypted
    database is a bad idea, but as it's required by the GDPR
    (https://gdpr-info.eu/art-20-gdpr/), it should be done as securely
    as possible.

    Therefore, before allowing export, TFC will ask for the master
    password to ensure no unauthorized user who gains momentary
    access to the system can the export logs from the database.
    """
    export = ts is not None
    ser_no_msg, uid = separate_header(cmd_data, ENCODED_INTEGER_LENGTH)
    no_messages = bytes_to_int(ser_no_msg)
    window = window_list.get_window(uid)

    access_logs(window,
                contact_list,
                group_list,
                settings,
                master_key,
                msg_to_load=no_messages,
                export=export)

    if export:
        local_win = window_list.get_local_window()
        local_win.add_new(
            ts,
            f"Exported log file of {window.type} '{window.name}'.",
            output=True)
Exemple #3
0
def log_command(user_input: 'UserInput', window: 'TxWindow',
                contact_list: 'ContactList', group_list: 'GroupList',
                settings: 'Settings', queues: 'QueueDict',
                master_key: 'MasterKey') -> None:
    """Display message logs or export them to plaintext file on TCBs.

    Transmitter Program processes sent, Receiver Program sent and
    received, messages of all participants in the active window.

    Having the capability to export the log file from the encrypted
    database is a bad idea, but as it's required by the GDPR
    (https://gdpr-info.eu/art-20-gdpr/), it should be done as securely
    as possible.

    Therefore, before allowing export, TFC will ask for the master
    password to ensure no unauthorized user who gains momentary
    access to the system can the export logs from the database.
    """
    cmd = user_input.plaintext.split()[0]
    export, header = dict(export=(True, LOG_EXPORT),
                          history=(False, LOG_DISPLAY))[cmd]

    try:
        msg_to_load = int(user_input.plaintext.split()[1])
    except ValueError:
        raise SoftError("Error: Invalid number of messages.", head_clear=True)
    except IndexError:
        msg_to_load = 0

    try:
        command = header + int_to_bytes(msg_to_load) + window.uid
    except struct.error:
        raise SoftError("Error: Invalid number of messages.", head_clear=True)

    if export and not yes(f"Export logs for '{window.name}' in plaintext?",
                          abort=False):
        raise SoftError("Log file export aborted.",
                        tail_clear=True,
                        head=0,
                        delay=1)

    authenticated = master_key.authenticate_action(
    ) if settings.ask_password_for_log_access else True

    if authenticated:
        queue_command(command, settings, queues)
        access_logs(window,
                    contact_list,
                    group_list,
                    settings,
                    master_key,
                    msg_to_load,
                    export=export)

        if export:
            raise SoftError(
                f"Exported log file of {window.type} '{window.name}'.",
                head_clear=True)
Exemple #4
0
    def test_export_short_private_message(self, _):
        # Setup
        # Test title displayed by the Receiver program.
        self.settings.software_operation = RX

        # Add a message from contact Alice to user (Bob).
        for p in assembly_packet_creator(MESSAGE, 'Hi Bob'):
            write_log_entry(p,
                            nick_to_pub_key('Alice'),
                            self.settings,
                            self.master_key,
                            origin=ORIGIN_CONTACT_HEADER)

        # Add a message from user (Bob) to Alice.
        for p in assembly_packet_creator(MESSAGE, 'Hi Alice'):
            write_log_entry(p, nick_to_pub_key('Alice'), self.settings,
                            self.master_key)

        # Test
        self.assertIsNone(access_logs(*self.args, export=True))

        with open("Receiver - Plaintext log (Alice)") as f:
            self.assertEqual(
                f.read(), f"""\
Log file of message(s) to/from contact Alice
════════════════════════════════════════════════════════════════════════════════
{self.time} Alice: Hi Bob
{self.time}    Me: Hi Alice
<End of log file>

""")
Exemple #5
0
def log_command(cmd_data: bytes, ts: 'datetime', window_list: 'WindowList',
                contact_list: 'ContactList', group_list: 'GroupList',
                settings: 'Settings', master_key: 'MasterKey') -> None:
    """Display or export logfile for active window."""
    export = ts is not None
    win_uid, no_msg_bytes = cmd_data.split(US_BYTE)
    no_messages = bytes_to_int(no_msg_bytes)
    window = window_list.get_window(win_uid.decode())
    access_logs(window,
                contact_list,
                group_list,
                settings,
                master_key,
                msg_to_load=no_messages,
                export=export)

    if export:
        local_win = window_list.get_window(LOCAL_ID)
        local_win.add_new(
            ts,
            f"Exported logfile of {window.type_print} {window.name}.",
            output=True)
Exemple #6
0
def log_command(cmd_data: bytes, ts: 'datetime', window_list: 'WindowList',
                contact_list: 'ContactList', group_list: 'GroupList',
                settings: 'Settings', master_key: 'MasterKey') -> None:
    """Display or export log file for the active window."""
    export = ts is not None
    ser_no_msg, uid = separate_header(cmd_data, ENCODED_INTEGER_LENGTH)
    no_messages = bytes_to_int(ser_no_msg)
    window = window_list.get_window(uid)
    access_logs(window,
                contact_list,
                group_list,
                settings,
                master_key,
                msg_to_load=no_messages,
                export=export)

    if export:
        local_win = window_list.get_local_window()
        local_win.add_new(
            ts,
            f"Exported log file of {window.type} '{window.name}'.",
            output=True)
Exemple #7
0
def log_command(user_input:   'UserInput',
                window:       'TxWindow',
                contact_list: 'ContactList',
                group_list:   'GroupList',
                settings:     'Settings',
                queues:       'QueueDict',
                master_key:   'MasterKey'
                ) -> None:
    """Display message logs or export them to plaintext file on TCBs.

    Transmitter Program processes sent, Receiver Program sent and
    received, messages of all participants in the active window.
    """
    cmd            = user_input.plaintext.split()[0]
    export, header = dict(export =(True,  LOG_EXPORT),
                          history=(False, LOG_DISPLAY))[cmd]

    try:
        msg_to_load = int(user_input.plaintext.split()[1])
    except ValueError:
        raise FunctionReturn("Error: Invalid number of messages.", head_clear=True)
    except IndexError:
        msg_to_load = 0

    try:
        command = header + int_to_bytes(msg_to_load) + window.uid
    except struct.error:
        raise FunctionReturn("Error: Invalid number of messages.", head_clear=True)

    if export:
        if not yes(f"Export logs for '{window.name}' in plaintext?", abort=False):
            raise FunctionReturn("Log file export aborted.", tail_clear=True, head=0, delay=1)

    queue_command(command, settings, queues)

    access_logs(window, contact_list, group_list, settings, master_key, msg_to_load, export)

    if export:
        raise FunctionReturn(f"Exported log file of {window.type} '{window.name}'.", head_clear=True)
Exemple #8
0
    def test_export_short_private_message(self):
        # Setup
        for p in assembly_packet_creator(MESSAGE, b'Hi Bob'):
            write_log_entry(p, '*****@*****.**', self.settings, self.masterkey, origin=ORIGIN_CONTACT_HEADER)
        for p in assembly_packet_creator(MESSAGE, b'Hi Alice'):
            write_log_entry(p, '*****@*****.**', self.settings, self.masterkey)

        # Test
        self.assertIsNone(access_logs(self.window, self.contact_list, self.group_list, self.settings, self.masterkey, export=True))

        with open("UtM - Plaintext log (Alice)") as f:
            exported_log = f.read()
        self.assertEqual(exported_log, f"""\
Logfile of messages to/from Alice
════════════════════════════════════════════════════════════════════════════════
{self.time} Alice: Hi Bob
{self.time}    Me: Hi Alice
<End of logfile>

""")
Exemple #9
0
    def test_long_group_message(self):
        # Setup
        self.window = RxWindow(type=WIN_TYPE_GROUP, uid='test_group', name='test_group')

        # Add an assembly packet sequence for contact containing cancel packet that the function should skip
        packets = assembly_packet_creator(MESSAGE, self.msg)
        packets = packets[2:] + [M_C_HEADER + bytes(PADDING_LEN)]
        for p in packets:
            write_log_entry(p, '*****@*****.**', self.settings, self.masterkey)

        # Add an orphaned 'append' assembly packet that the function should skip
        write_log_entry(M_A_HEADER + bytes(PADDING_LEN), '*****@*****.**', self.settings, self.masterkey)

        # Add a private message that the function should skip
        for p in assembly_packet_creator(MESSAGE, b'This is a short message'):
            write_log_entry(p, '*****@*****.**', self.settings, self.masterkey)

        # Add a group management message that the function should skip
        message = US_BYTE.join([b'test_group', b'*****@*****.**'])
        for p in assembly_packet_creator(MESSAGE, message, header=GROUP_MSG_INVITEJOIN_HEADER):
            write_log_entry(p, '*****@*****.**', self.settings, self.masterkey)

        # Add a group message that the function should skip
        for p in assembly_packet_creator(MESSAGE, b'This is a short message', group_name='different_group'):
            write_log_entry(p, '*****@*****.**', self.settings, self.masterkey)

        for p in assembly_packet_creator(MESSAGE, self.msg, group_name='test_group'):
            write_log_entry(p, '*****@*****.**',   self.settings, self.masterkey)
            write_log_entry(p, '*****@*****.**',   self.settings, self.masterkey, origin=ORIGIN_CONTACT_HEADER)
            write_log_entry(p, '*****@*****.**', self.settings, self.masterkey)
            write_log_entry(p, '*****@*****.**', self.settings, self.masterkey, origin=ORIGIN_CONTACT_HEADER)

        # Test
        access_logs(self.window, self.contact_list, self.group_list, self.settings, self.masterkey)
        self.assertPrints((CLEAR_ENTIRE_SCREEN + CURSOR_LEFT_UP_CORNER + f"""\
Logfile of messages to/from test_group
════════════════════════════════════════════════════════════════════════════════
{self.time}      Me: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean
               condimentum consectetur purus quis dapibus. Fusce venenatis lacus
               ut rhoncus faucibus. Cras sollicitudin commodo sapien, sed
               bibendum velit maximus in. Aliquam ac metus risus. Sed cursus
               ornare luctus. Integer aliquet lectus id massa blandit imperdiet.
               Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl.
               Sed ut elit iaculis, faucibus lacus eget, sodales magna. Nunc sed
               commodo arcu. In hac habitasse platea dictumst. Integer luctus
               aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est
               eget odio rutrum, vel malesuada lorem rhoncus. Cras finibus in
               neque eu euismod. Nulla facilisi. Nunc nec aliquam quam, quis
               ullamcorper leo. Nunc egestas lectus eget est porttitor, in
               iaculis felis scelerisque. In sem elit, fringilla id viverra
               commodo, sagittis varius purus. Pellentesque rutrum lobortis
               neque a facilisis. Mauris id tortor placerat, aliquam dolor ac,
               venenatis arcu.
{self.time}   Alice: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean
               condimentum consectetur purus quis dapibus. Fusce venenatis lacus
               ut rhoncus faucibus. Cras sollicitudin commodo sapien, sed
               bibendum velit maximus in. Aliquam ac metus risus. Sed cursus
               ornare luctus. Integer aliquet lectus id massa blandit imperdiet.
               Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl.
               Sed ut elit iaculis, faucibus lacus eget, sodales magna. Nunc sed
               commodo arcu. In hac habitasse platea dictumst. Integer luctus
               aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est
               eget odio rutrum, vel malesuada lorem rhoncus. Cras finibus in
               neque eu euismod. Nulla facilisi. Nunc nec aliquam quam, quis
               ullamcorper leo. Nunc egestas lectus eget est porttitor, in
               iaculis felis scelerisque. In sem elit, fringilla id viverra
               commodo, sagittis varius purus. Pellentesque rutrum lobortis
               neque a facilisis. Mauris id tortor placerat, aliquam dolor ac,
               venenatis arcu.
{self.time} Charlie: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean
               condimentum consectetur purus quis dapibus. Fusce venenatis lacus
               ut rhoncus faucibus. Cras sollicitudin commodo sapien, sed
               bibendum velit maximus in. Aliquam ac metus risus. Sed cursus
               ornare luctus. Integer aliquet lectus id massa blandit imperdiet.
               Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl.
               Sed ut elit iaculis, faucibus lacus eget, sodales magna. Nunc sed
               commodo arcu. In hac habitasse platea dictumst. Integer luctus
               aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est
               eget odio rutrum, vel malesuada lorem rhoncus. Cras finibus in
               neque eu euismod. Nulla facilisi. Nunc nec aliquam quam, quis
               ullamcorper leo. Nunc egestas lectus eget est porttitor, in
               iaculis felis scelerisque. In sem elit, fringilla id viverra
               commodo, sagittis varius purus. Pellentesque rutrum lobortis
               neque a facilisis. Mauris id tortor placerat, aliquam dolor ac,
               venenatis arcu.
<End of logfile>

"""), access_logs, self.window, self.contact_list, self.group_list, self.settings, self.masterkey)