Skip to content
Snippets Groups Projects
Commit 8b85e8a0 authored by Philipp Hörist's avatar Philipp Hörist
Browse files

Merge branch 'omemo' into 'gtk3'

omemo version 2.3.0

See merge request !38
parents de369fc6 ddf3f86b
No related branches found
No related tags found
2 merge requests!41Improved error messages,!38omemo version 2.3.0
2.3.0 / 2017-05-07
- Make plugin compatible with Gajims encryption API
2.2.1 / 2017-04-15
- Recognize aesgcm uri scheme
......
[info]
name: OMEMO
short_name: omemo
version: 2.2.1
version: 2.3.0
description: OMEMO is an XMPP Extension Protocol (XEP) for secure multi-client end-to-end encryption based on Axolotl and PEP. You need to install some dependencys, you can find install instructions for your system in the Github Wiki.
authors: Bahtiar `kalkin-` Gadimov <bahtiar@gadimov.de>
Daniel Gultsch <daniel@gultsch.de>
......
This diff is collapsed.
# -*- coding: utf-8 -*-
#
# Copyright 2015 Bahtiar `kalkin-` Gadimov <bahtiar@gadimov.de>
# Copyright 2015 Daniel Gultsch <daniel@cgultsch.de>
#
# This file is part of Gajim-OMEMO plugin.
#
# The Gajim-OMEMO plugin is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Gajim-OMEMO is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# the Gajim-OMEMO plugin. If not, see <http://www.gnu.org/licenses/>.
#
'''
Copyright 2015 Bahtiar `kalkin-` Gadimov <bahtiar@gadimov.de>
Copyright 2015 Daniel Gultsch <daniel@cgultsch.de>
Copyright 2016 Philipp Hörist <philipp@hoerist.com>
This file is part of Gajim-OMEMO plugin.
The Gajim-OMEMO plugin is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
Gajim-OMEMO is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
the Gajim-OMEMO plugin. If not, see <http://www.gnu.org/licenses/>.
'''
import binascii
import logging
import os
import message_control
from gi.repository import GObject, Gtk, GdkPixbuf, Gdk
from enum import IntEnum, unique
# pylint: disable=import-error
import gtkgui_helpers
from common import gajim
from dialogs import YesNoDialog
from plugins.gui import GajimPluginConfigDialog
from gi.repository import Gtk, GdkPixbuf, Gdk
from axolotl.state.sessionrecord import SessionRecord
from common import configpaths
log = logging.getLogger('gajim.plugin_system.omemo')
......@@ -43,285 +38,17 @@ except Exception as e:
log.exception('Error:')
log.error('python-qrcode or dependencies of it, are not available')
# pylint: enable=import-error
UNDECIDED = 2
TRUSTED = 1
UNTRUSTED = 0
class OmemoButton(Gtk.Button):
def __init__(self, plugin, chat_control, ui, enabled):
super(OmemoButton, self).__init__(label=None, stock=None)
self.chat_control = chat_control
self.set_property('relief', Gtk.ReliefStyle.NONE)
self.set_property('can-focus', False)
self.set_sensitive(True)
icon = Gtk.Image.new_from_file(
plugin.local_file_path('omemo16x16.png'))
self.set_image(icon)
self.set_tooltip_text('OMEMO Encryption')
self.connect('clicked', self.on_click)
self.menu = OmemoMenu(ui, enabled)
def on_click(self, widget):
"""
Popup omemo menu
"""
gtkgui_helpers.popup_emoticons_under_button(
self.menu, widget, self.chat_control.parent_win)
def set_omemo_state(self, state):
self.menu.set_omemo_state(state)
class OmemoMenu(Gtk.Menu):
def __init__(self, ui, enabled):
super(OmemoMenu, self).__init__()
self.ui = ui
self.item_omemo_state = Gtk.CheckMenuItem('Activate OMEMO')
self.item_omemo_state.set_active(enabled)
self.item_omemo_state.connect('activate', self.on_toggle_omemo)
self.append(self.item_omemo_state)
item = Gtk.ImageMenuItem('Fingerprints')
icon = Gtk.Image.new_from_stock(Gtk.STOCK_DIALOG_AUTHENTICATION,
Gtk.IconSize.MENU)
item.set_image(icon)
item.connect('activate', self.on_open_fingerprint_window)
self.append(item)
self.show_all()
def on_toggle_omemo(self, widget):
self.ui.set_omemo_state(widget.get_active())
def on_open_fingerprint_window(self, widget):
self.ui.show_fingerprint_window()
def set_omemo_state(self, state):
self.item_omemo_state.handler_block_by_func(self.on_toggle_omemo)
self.item_omemo_state.set_active(state)
self.item_omemo_state.handler_unblock_by_func(self.on_toggle_omemo)
class Ui(object):
def __init__(self, plugin, chat_control, enabled, state):
self.contact = chat_control.contact
self.chat_control = chat_control
self.plugin = plugin
self.state = state
self.account = self.contact.account.name
self.windowinstances = {}
self.groupchat = False
if chat_control.type_id == message_control.TYPE_GC:
self.groupchat = True
self.omemo_capable = False
self.room = self.chat_control.room_jid
self.display_omemo_state()
self.refresh_auth_lock_icon()
self.omemobutton = OmemoButton(plugin, chat_control, self, enabled)
self.actions_hbox = chat_control.xml.get_object('actions_hbox')
send_button = chat_control.xml.get_object('send_button')
send_button_pos = self.actions_hbox.child_get_property(send_button,
'position')
self.actions_hbox.add(self.omemobutton)
self.actions_hbox.reorder_child(self.omemobutton, send_button_pos - 1)
self.omemobutton.show_all()
# add a OMEMO entry to the context/advanced menu
self.chat_control.omemo_orig_prepare_context_menu = \
self.chat_control.prepare_context_menu
def omemo_prepare_context_menu(hide_buttonbar_items=False):
menu = self.chat_control. \
omemo_orig_prepare_context_menu(hide_buttonbar_items)
submenu = OmemoMenu(self, self.encryption_active())
item = Gtk.ImageMenuItem('OMEMO Encryption')
icon_path = plugin.local_file_path('omemo16x16.png')
item.set_image(Gtk.Image.new_from_file(icon_path))
item.set_submenu(submenu)
if self.groupchat:
item.set_sensitive(self.omemo_capable)
# at index 8 is the separator after the esession encryption entry
menu.insert(item, 8)
return menu
self.chat_control.prepare_context_menu = omemo_prepare_context_menu
# Hook into Send Button so we can check Stuff before sending
self.chat_control.orig_send_message = \
self.chat_control.send_message
def omemo_send_message(message, keyID='', chatstate=None, xhtml=None,
process_commands=True, attention=False):
self.new_fingerprints_available()
if self.encryption_active() and \
self.plugin.are_keys_missing(self.account,
self.contact.jid):
log.debug(self.account + ' => No Trusted Fingerprints for ' +
self.contact.jid)
self.no_trusted_fingerprints_warning()
else:
self.chat_control.orig_send_message(message, keyID, chatstate,
xhtml, process_commands,
attention)
log.debug(self.account + ' => Sending Message to ' +
self.contact.jid)
def omemo_send_gc_message(message, xhtml=None, process_commands=True):
self.new_fingerprints_available()
if self.encryption_active():
missing = True
own_jid = gajim.get_jid_from_account(self.account)
for nick in self.plugin.groupchat[self.room]:
real_jid = self.plugin.groupchat[self.room][nick]
if real_jid == own_jid:
continue
if not self.plugin.are_keys_missing(self.account,
real_jid):
missing = False
if missing:
log.debug(self.account +
' => No Trusted Fingerprints for ' +
self.room)
self.no_trusted_fingerprints_warning()
else:
self.chat_control.orig_send_message(message, xhtml,
process_commands)
log.debug(self.account + ' => Sending Message to ' +
self.room)
else:
self.chat_control.orig_send_message(message, xhtml,
process_commands)
log.debug(self.account + ' => Sending Message to ' +
self.room)
if self.groupchat:
self.chat_control.send_message = omemo_send_gc_message
else:
self.chat_control.send_message = omemo_send_message
def set_omemo_state(self, enabled):
"""
Enable or disable OMEMO for this window's contact and update the
window ui accordingly
"""
if enabled:
log.debug(self.contact.account.name + ' => Enable OMEMO for ' +
self.contact.jid)
self.plugin.omemo_enable_for(self.contact.jid,
self.contact.account.name)
self.refresh_auth_lock_icon()
else:
log.debug(self.contact.account.name + ' => Disable OMEMO for ' +
self.contact.jid)
self.plugin.omemo_disable_for(self.contact.jid,
self.contact.account.name)
self.refresh_auth_lock_icon()
self.omemobutton.set_omemo_state(enabled)
self.display_omemo_state()
def sensitive(self, value):
self.omemobutton.set_sensitive(value)
self.omemo_capable = value
if value:
self.chat_control.prepare_context_menu
def encryption_active(self):
return self.state.encryption.is_active(self.contact.jid)
def activate_omemo(self):
if not self.encryption_active():
self.set_omemo_state(True)
def new_fingerprints_available(self):
jid = self.contact.jid
if self.groupchat and self.room in self.plugin.groupchat:
for nick in self.plugin.groupchat[self.room]:
real_jid = self.plugin.groupchat[self.room][nick]
fingerprints = self.state.store. \
getNewFingerprints(real_jid)
if fingerprints:
self.show_fingerprint_window(fingerprints)
elif not self.groupchat:
fingerprints = self.state.store.getNewFingerprints(jid)
if fingerprints:
self.show_fingerprint_window(fingerprints)
def show_fingerprint_window(self, fingerprints=None):
if 'dialog' not in self.windowinstances:
if self.groupchat:
self.windowinstances['dialog'] = \
FingerprintWindow(self.plugin, self.contact,
self.chat_control.parent_win.window,
self.windowinstances, groupchat=True)
else:
self.windowinstances['dialog'] = \
FingerprintWindow(self.plugin, self.contact,
self.chat_control.parent_win.window,
self.windowinstances)
self.windowinstances['dialog'].show_all()
if fingerprints:
log.debug(self.account +
' => Showing Fingerprint Prompt for ' +
self.contact.jid)
self.state.store.setShownFingerprints(fingerprints)
else:
self.windowinstances['dialog'].update_context_list()
if fingerprints:
self.state.store.setShownFingerprints(fingerprints)
def plain_warning(self):
self.chat_control.print_conversation_line(
'Received plaintext message! ' +
'Your next message will still be encrypted!', 'status', '', None)
def display_omemo_state(self):
if self.encryption_active():
msg = u'OMEMO encryption enabled'
else:
msg = u'OMEMO encryption disabled'
self.chat_control.print_conversation_line(msg, 'status', '', None)
def no_trusted_fingerprints_warning(self):
msg = "To send an encrypted message, you have to " \
"first trust the fingerprint of your contact!"
self.chat_control.print_conversation_line(msg, 'status', '', None)
from common import gajim
from common import configpaths
from dialogs import YesNoDialog
from plugins.gui import GajimPluginConfigDialog
def refresh_auth_lock_icon(self):
if self.groupchat:
return
if self.encryption_active():
if self.state.getUndecidedFingerprints(self.contact.jid):
self.chat_control._show_lock_image(True, 'OMEMO', True, True,
False)
else:
self.chat_control._show_lock_image(True, 'OMEMO', True, True,
True)
else:
self.chat_control._show_lock_image(False, 'OMEMO', False, True,
False)
def removeUi(self):
self.actions_hbox.remove(self.omemobutton)
self.chat_control._show_lock_image(False, 'OMEMO', False, True,
False)
self.chat_control.prepare_context_menu = \
self.chat_control.omemo_orig_prepare_context_menu
self.chat_control.send_message = self.chat_control.orig_send_message
@unique
class State(IntEnum):
UNTRUSTED = 0
TRUSTED = 1
UNDECIDED = 2
class OMEMOConfigDialog(GajimPluginConfigDialog):
......@@ -480,7 +207,7 @@ class OMEMOConfigDialog(GajimPluginConfigDialog):
mod, paths = self.fpr_view.get_selection().get_selected_rows()
def on_yes(checked, identity_key):
state.store.setTrust(identity_key, TRUSTED)
state.store.setTrust(identity_key, State.TRUSTED)
try:
if self.plugin.ui_list[account]:
self.plugin.ui_list[account][jid]. \
......@@ -490,7 +217,7 @@ class OMEMOConfigDialog(GajimPluginConfigDialog):
self.update_context_list()
def on_no(identity_key):
state.store.setTrust(identity_key, UNTRUSTED)
state.store.setTrust(identity_key, State.UNTRUSTED)
try:
if jid in self.plugin.ui_list[account]:
self.plugin.ui_list[account][jid]. \
......@@ -700,17 +427,11 @@ class FingerprintWindow(Gtk.Dialog):
mod, paths = self.fpr_view.get_selection().get_selected_rows()
def on_yes(checked, identity_key):
state.store.setTrust(identity_key, TRUSTED)
if not self.groupchat:
self.plugin.ui_list[self.account][self.contact.jid]. \
refresh_auth_lock_icon()
state.store.setTrust(identity_key, State.TRUSTED)
self.update_context_list()
def on_no(identity_key):
state.store.setTrust(identity_key, UNTRUSTED)
if not self.groupchat:
self.plugin.ui_list[self.account][self.contact.jid]. \
refresh_auth_lock_icon()
state.store.setTrust(identity_key, State.UNTRUSTED)
self.update_context_list()
for path in paths:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment