Esempio n. 1
0
def _start_omemo_session(jid):
    # should be started before the first message is sent.

    # we store the jid in ProfActiveOmemoChats as the user at least intends to
    # use OMEMO encryption. The respecting methods should then not ignore
    # sending OMEMO messages and fail if no session was created then.
    if not ProfActiveOmemoChats.account_is_registered(jid):
        ProfActiveOmemoChats.add(jid)
    else:
        ProfActiveOmemoChats.activate(jid)

    # ensure we have no running OTR session
    prof.encryption_reset(jid)

    # Visualize that OMEMO is now running
    prof.chat_set_titlebar_enctext(jid, 'OMEMO')

    message_char = _get_omemo_message_char()
    prof.chat_set_outgoing_char(jid, message_char)

    show_chat_info(jid, 'OMEMO Session started.')
    _show_no_trust_mgmt_header(jid)

    log.info('Query Devicelist for {0}'.format(jid))
    _query_device_list(jid)

    prof.settings_string_list_add(SETTINGS_GROUP, 'omemo_sessions', jid)
def _start_omemo_session(jid):
    # should be started before the first message is sent.

    # we store the jid in ProfActiveOmemoChats as the user at least intends to
    # use OMEMO encryption. The respecting methods should then not ignore
    # sending OMEMO messages and fail if no session was created then.
    if not ProfActiveOmemoChats.account_is_registered(jid):
        ProfActiveOmemoChats.add(jid)
    else:
        ProfActiveOmemoChats.activate(jid)

    # ensure we have no running OTR session
    prof.encryption_reset(jid)

    # Visualize that OMEMO is now running
    prof.chat_set_titlebar_enctext(jid, 'OMEMO')

    message_char = _get_omemo_message_char()
    prof.chat_set_outgoing_char(jid, message_char)

    show_chat_info(jid, 'OMEMO Session started.')
    _show_no_trust_mgmt_header(jid)

    log.info('Query Devicelist for {0}'.format(jid))
    _query_device_list(jid)

    prof.settings_string_list_add(SETTINGS_GROUP, 'omemo_sessions', jid)
    def test_omemo_chat_remove_account(self):
        account = '*****@*****.**'
        assert len(ProfActiveOmemoChats._active) == 0

        ProfActiveOmemoChats.add(account)
        assert len(ProfActiveOmemoChats._active) == 1

        ProfActiveOmemoChats.remove(account)
        assert len(ProfActiveOmemoChats._active) == 0
    def test_omemo_acitve_chat_is_singleton(self):
        account = '*****@*****.**'

        active_chats_instance = ProfActiveOmemoChats
        ProfActiveOmemoChats.add(account)

        new_active_chats_instance = ProfActiveOmemoChats

        assert active_chats_instance._active == new_active_chats_instance._active
    def test_omemo_chat_adds_accounts_uniquely(self):
        account = '*****@*****.**'
        assert len(ProfActiveOmemoChats._active) == 0

        ProfActiveOmemoChats.add(account)
        assert len(ProfActiveOmemoChats._active) == 1

        ProfActiveOmemoChats.add(account)
        assert len(ProfActiveOmemoChats._active) == 1
    def test_has_session_decorator_returns_default_on_error(self):
        @plugin.require_sessions_for_all_devices('not_valid_attrib')
        def func(x):
            return x

        recipient = '*****@*****.**'
        ProfActiveOmemoChats.add(recipient)

        stanza = '<message to="{}"></message>'.format(recipient)

        assert func(stanza) is None
    def test_has_session_decorator_returns_default_on_error(self):
        @plugin.require_sessions_for_all_devices('not_valid_attrib')
        def func(x):
            return x

        recipient = '*****@*****.**'
        ProfActiveOmemoChats.add(recipient)

        stanza = '<message to="{}"></message>'.format(recipient)

        assert func(stanza) is None
Esempio n. 8
0
def _end_omemo_session(jid):
    ProfActiveOmemoChats.deactivate(jid)

    # Release OMEMO from titlebar
    prof.chat_unset_titlebar_enctext(jid)

    prof.chat_unset_incoming_char(jid)
    prof.chat_unset_outgoing_char(jid)

    prof.settings_string_list_remove(SETTINGS_GROUP, 'omemo_sessions', jid)

    show_chat_info(jid, 'OMEMO Session ended.')
def _end_omemo_session(jid):
    ProfActiveOmemoChats.deactivate(jid)

    # Release OMEMO from titlebar
    prof.chat_unset_titlebar_enctext(jid)

    prof.chat_unset_incoming_char(jid)
    prof.chat_unset_outgoing_char(jid)

    prof.settings_string_list_remove(SETTINGS_GROUP, 'omemo_sessions', jid)

    show_chat_info(jid, 'OMEMO Session ended.')
    def test_stacked_decorators(self, settings_boolean_get):
        @plugin.omemo_enabled(else_return='enabled_first')
        @plugin.require_sessions_for_all_devices('to', else_return='session_second')
        def func(x):
            return x

        settings_boolean_get.return_value = True
        recipient = '*****@*****.**'
        ProfActiveOmemoChats.add(recipient)

        stanza = '<message to="{}"></message>'.format(recipient)

        assert func(stanza) == stanza
    def test_stacked_decorators(self, settings_boolean_get):
        @plugin.omemo_enabled(else_return='enabled_first')
        @plugin.require_sessions_for_all_devices('to',
                                                 else_return='session_second')
        def func(x):
            return x

        settings_boolean_get.return_value = True
        recipient = '*****@*****.**'
        ProfActiveOmemoChats.add(recipient)

        stanza = '<message to="{}"></message>'.format(recipient)

        assert func(stanza) == stanza
    def test_has_session_decorator_returns_func_result_on_none_session(self, devices_mock):
        devices_mock.return_value = []

        @plugin.require_sessions_for_all_devices('to')
        def func(x):
            return x

        recipient = '*****@*****.**'

        ProfActiveOmemoChats.add(recipient)

        stanza = '<message to="{}"></message>'.format(recipient)

        assert func(stanza) == stanza
    def test_has_session_decorator_returns_func_result_on_none_session(
            self, devices_mock):
        devices_mock.return_value = []

        @plugin.require_sessions_for_all_devices('to')
        def func(x):
            return x

        recipient = '*****@*****.**'

        ProfActiveOmemoChats.add(recipient)

        stanza = '<message to="{}"></message>'.format(recipient)

        assert func(stanza) == stanza
Esempio n. 14
0
def prof_on_chat_win_focus(barejid):
    if not ProfActiveOmemoChats.account_is_registered(barejid):
        # get remembered user sessions
        u_sess = prof.settings_string_list_get(SETTINGS_GROUP,
                                               'omemo_sessions')
        if u_sess and barejid in u_sess:
            _start_omemo_session(barejid)
Esempio n. 15
0
def prof_on_message_stanza_send(stanza):
    stanza = ensure_unicode_stanza(stanza)

    contact_jid = xmpp.get_recipient(stanza)
    if not ProfActiveOmemoChats.account_is_active(contact_jid):
        log.debug('Chat not activated for {0}'.format(contact_jid))
        return None

    try:
        if xmpp.is_xmpp_plaintext_message(stanza):
            encrypted_stanza = xmpp.encrypt_stanza(stanza)
            if xmpp.stanza_is_valid_xml(encrypted_stanza):
                return encrypted_stanza
    except Exception as e:
        log.exception('Could not encrypt message')

    show_chat_critical(contact_jid, 'Last message was sent unencrypted.')
    return None
def prof_on_message_stanza_send(stanza):
    stanza = ensure_unicode_stanza(stanza)

    contact_jid = xmpp.get_recipient(stanza)
    if not ProfActiveOmemoChats.account_is_active(contact_jid):
        log.debug('Chat not activated for {0}'.format(contact_jid))
        return None

    try:
        if xmpp.is_xmpp_plaintext_message(stanza):
            encrypted_stanza = xmpp.encrypt_stanza(stanza)
            if xmpp.stanza_is_valid_xml(encrypted_stanza):
                return encrypted_stanza
    except Exception as e:
        log.exception('Could not encrypt message')

    show_chat_critical(contact_jid, 'Last message was sent unencrypted.')
    return None
Esempio n. 17
0
def prof_pre_chat_message_send(barejid, message):
    """ Called before a chat message is sent

    :returns: the new message to send, returning None stops the message
              from being sent
    """

    plugin_enabled = _get_omemo_enabled_setting()
    if not plugin_enabled:
        return message

    if not ProfActiveOmemoChats.account_is_active(barejid):
        log.info('Chat not activated for {0}'.format(barejid))
        return message

    omemo_state = ProfOmemoState()
    uninitialzed_devices = omemo_state.devices_without_sessions(barejid)

    if uninitialzed_devices:
        d_str = ', '.join([str(d) for d in uninitialzed_devices])
        msg = 'Requesting bundles for missing devices {0}'.format(d_str)

        log.info(msg)
        prof.notify(msg, 5000, 'Profanity Omemo Plugin')

        for device in uninitialzed_devices:
            _query_bundle_info_for(barejid, device)

    own_jid = ProfOmemoUser.account
    own_uninitialized = omemo_state.devices_without_sessions(own_jid)

    if own_uninitialized:
        d_str = ', '.join([str(d) for d in own_uninitialized])
        msg = 'Requesting own bundles for missing devices {0}'.format(d_str)

        log.info(msg)
        prof.notify(msg, 5000, 'Profanity Omemo Plugin')

        for device in own_uninitialized:
            _query_bundle_info_for(own_jid, device)

    return message
def prof_pre_chat_message_send(barejid, message):
    """ Called before a chat message is sent

    :returns: the new message to send, returning None stops the message
              from being sent
    """

    plugin_enabled = _get_omemo_enabled_setting()
    if not plugin_enabled:
        return message

    if not ProfActiveOmemoChats.account_is_active(barejid):
        log.info('Chat not activated for {0}'.format(barejid))
        return message

    omemo_state = ProfOmemoState()
    uninitialzed_devices = omemo_state.devices_without_sessions(barejid)

    if uninitialzed_devices:
        d_str = ', '.join([str(d) for d in uninitialzed_devices])
        msg = 'Requesting bundles for missing devices {0}'.format(d_str)

        log.info(msg)
        prof.notify(msg, 5000, 'Profanity Omemo Plugin')

        for device in uninitialzed_devices:
            _query_bundle_info_for(barejid, device)

    own_jid = ProfOmemoUser.account
    own_uninitialized = omemo_state.devices_without_sessions(own_jid)

    if own_uninitialized:
        d_str = ', '.join([str(d) for d in own_uninitialized])
        msg = 'Requesting own bundles for missing devices {0}'.format(d_str)

        log.info(msg)
        prof.notify(msg, 5000, 'Profanity Omemo Plugin')

        for device in own_uninitialized:
            _query_bundle_info_for(own_jid, device)

    return message
def prof_on_message_stanza_receive(stanza):
    stanza = ensure_unicode_stanza(stanza)

    log.info('Received Message: {0}'.format(stanza))
    if xmpp.is_devicelist_update(stanza):
        log.info('Device List update detected.')
        try:
            _handle_devicelist_update(stanza)
        except:
            log.exception('Failed to handle devicelist update.')

        return False

    if xmpp.is_encrypted_message(stanza):
        log.info('Received OMEMO encrypted message.')
        omemo_state = ProfOmemoState()

        try:
            msg_dict = xmpp.unpack_encrypted_stanza(stanza)
            sender = msg_dict['sender_jid']
            resource = msg_dict['sender_resource']
            sender_fulljid = sender + '/' + resource

            if sender_fulljid == ProfOmemoUser().fulljid:
                log.debug('Skipping own Message.')
                return False

            try:
                plain_msg = omemo_state.decrypt_msg(msg_dict)
            except Exception:
                log.exception('Could not decrypt Message.')
                return False

            if plain_msg is None:
                log.error('Could not decrypt Message')
                return True

            if plain_msg:
                # only mark the message if it was an OMEMO encrypted message
                try:
                    message_char = _get_omemo_message_char()
                    log.debug('Set incoming Message Character: {0}'.format(message_char))
                    prof.chat_set_incoming_char(sender, message_char)
                    prof.incoming_message(sender, resource, plain_msg)
                finally:
                    prof.chat_unset_incoming_char(sender)

                # if this was the first OMEMO encrypted message received by
                # the sender (a.k.a. whenever profanity opens a new chat window
                # for a recipient), we automatically respond with OMEMO encrypted
                # messages. If encryption is turned off later by the user,
                # we respect that.
                if not ProfActiveOmemoChats.account_is_active(sender):
                    if not ProfActiveOmemoChats.account_is_deactivated(sender):
                        _start_omemo_session(sender)

            return False

        except Exception:
            # maybe not OMEMO encrypted, profanity will take care then
            log.exception('Could not handle encrypted message.')

    return True
 def teardown_method(self, test_method):
     ProfActiveOmemoChats.reset()
     ProfOmemoUser.reset()
    def test_prof_active_chats_finds_active_chats(self):
        account = '*****@*****.**'
        account2 = '*****@*****.**'

        ProfActiveOmemoChats.add(account)
        ProfActiveOmemoChats.add(account2)

        assert ProfActiveOmemoChats.account_is_active(account) is True
        assert ProfActiveOmemoChats.account_is_active(account2) is True

        ProfActiveOmemoChats.remove(account)
        assert ProfActiveOmemoChats.account_is_active(account) is False

        ProfActiveOmemoChats.remove(account2)
        assert ProfActiveOmemoChats.account_is_active(account2) is False
 def teardown_method(self, test_method):
     ProfOmemoUser.reset()
     ProfActiveOmemoChats.reset()
Esempio n. 23
0
def prof_on_message_stanza_receive(stanza):
    stanza = ensure_unicode_stanza(stanza)

    log.info('Received Message: {0}'.format(stanza))
    if xmpp.is_devicelist_update(stanza):
        log.info('Device List update detected.')
        try:
            _handle_devicelist_update(stanza)
        except:
            log.exception('Failed to handle devicelist update.')

        return False

    if xmpp.is_encrypted_message(stanza):
        log.info('Received OMEMO encrypted message.')
        omemo_state = ProfOmemoState()

        try:
            msg_dict = xmpp.unpack_encrypted_stanza(stanza)
            sender = msg_dict['sender_jid']
            resource = msg_dict['sender_resource']
            sender_fulljid = sender + '/' + resource

            if sender_fulljid == ProfOmemoUser().fulljid:
                log.debug('Skipping own Message.')
                return False

            try:
                plain_msg = omemo_state.decrypt_msg(msg_dict)
            except Exception:
                log.exception('Could not decrypt Message.')
                return False

            if plain_msg is None:
                log.error('Could not decrypt Message')
                return True

            if plain_msg:
                # only mark the message if it was an OMEMO encrypted message
                try:
                    message_char = _get_omemo_message_char()
                    log.debug('Set incoming Message Character: {0}'.format(
                        message_char))
                    prof.chat_set_incoming_char(sender, message_char)
                    prof.incoming_message(sender, resource, plain_msg)
                finally:
                    prof.chat_unset_incoming_char(sender)

                # if this was the first OMEMO encrypted message received by
                # the sender (a.k.a. whenever profanity opens a new chat window
                # for a recipient), we automatically respond with OMEMO encrypted
                # messages. If encryption is turned off later by the user,
                # we respect that.
                if not ProfActiveOmemoChats.account_is_active(sender):
                    if not ProfActiveOmemoChats.account_is_deactivated(sender):
                        _start_omemo_session(sender)

            return False

        except Exception:
            # maybe not OMEMO encrypted, profanity will take care then
            log.exception('Could not handle encrypted message.')

    return True
def prof_on_chat_win_focus(barejid):
    if not ProfActiveOmemoChats.account_is_registered(barejid):
        # get remembered user sessions
        u_sess = prof.settings_string_list_get(SETTINGS_GROUP, 'omemo_sessions')
        if u_sess and barejid in u_sess:
            _start_omemo_session(barejid)