From cf07022cbd6057b5c5c75048e2102dc0db138659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Mon, 17 Apr 2017 19:58:41 +0200 Subject: [PATCH] Remove ESessions encryption/decryption from core --- data/gui/contact_context_menu.ui | 14 ----- src/chat_control.py | 52 ++++++---------- src/chat_control_base.py | 2 + src/common/config.py | 1 - src/common/connection.py | 18 ------ src/common/connection_handlers.py | 9 --- src/common/connection_handlers_events.py | 45 +------------- src/dialogs.py | 76 ------------------------ src/gui_menu_builder.py | 17 ------ 9 files changed, 20 insertions(+), 214 deletions(-) diff --git a/data/gui/contact_context_menu.ui b/data/gui/contact_context_menu.ui index 0ef415bea..98d846d40 100644 --- a/data/gui/contact_context_menu.ui +++ b/data/gui/contact_context_menu.ui @@ -45,20 +45,6 @@ True - - - True - False - - - - - True - False - Toggle End to End Encryption - True - - True diff --git a/src/chat_control.py b/src/chat_control.py index 07ff8adba..b1beb22f7 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -280,7 +280,6 @@ class ChatControl(ChatControlBase): # Enable encryption if needed self.no_autonegotiation = False - e2e_is_active = self.session and self.session.enable_encryption self.update_ui() self.set_lock_image() @@ -893,8 +892,6 @@ class ChatControl(ChatControlBase): def _on_authentication_button_clicked(self, widget): gajim.plugin_manager.gui_extension_point( 'encryption_dialog' + self.encryption, self) - if self.session and self.session.enable_encryption: - dialogs.ESessionInfoWindow(self.session, self.parent_win.window) def send_message(self, message, keyID='', chatstate=None, xhtml=None, process_commands=True, attention=False): @@ -914,11 +911,7 @@ class ChatControl(ChatControlBase): return None contact = self.contact - - encrypted = bool(self.session) and self.session.enable_encryption - keyID = contact.keyID - encrypted = True chatstates_on = gajim.config.get('outgoing_chat_state_notifications') != \ 'disabled' @@ -957,7 +950,7 @@ class ChatControl(ChatControlBase): ChatControlBase.send_message(self, message, keyID, type_='chat', chatstate=chatstate_to_send, xhtml=xhtml, callback=_on_sent, - callback_args=[message, encrypted, xhtml, self.get_seclabel()], + callback_args=[message, self.encryption, xhtml, self.get_seclabel()], process_commands=process_commands, attention=attention) @@ -1426,19 +1419,7 @@ class ChatControl(ChatControlBase): if textbuffer.get_char_count(): gajim.plugin_manager.gui_extension_point( 'typing' + self.encryption, self) - e2e_is_active = self.session and \ - self.session.enable_encryption - e2e_pref = gajim.config.get_per('accounts', self.account, - 'enable_esessions') and gajim.config.get_per('accounts', - self.account, 'autonegotiate_esessions') and gajim.config.get_per( - 'contacts', self.contact.jid, 'autonegotiate_esessions') - want_e2e = not e2e_is_active and self.encryption == '' \ - and e2e_pref - - if want_e2e and not self.no_autonegotiation \ - and gajim.HAVE_PYCRYPTO and self.contact.supports(NS_ESESSION): - self.begin_e2e_negotiation() - elif (not self.session or not self.session.status) and \ + if (not self.session or not self.session.status) and \ gajim.connections[self.account].archiving_136_supported: self.begin_archiving_negotiation() @@ -1635,22 +1616,23 @@ class ChatControl(ChatControlBase): """ dialogs.TransformChatToMUC(self.account, [self.contact.jid]) - def _on_toggle_e2e_menuitem_activate(self, widget): - if self.session and self.session.enable_encryption: - # e2e was enabled, disable it - jid = str(self.session.jid) - thread_id = self.session.thread_id - - self.session.terminate_e2e() - - gajim.connections[self.account].delete_session(jid, thread_id) - - # presumably the user had a good reason to shut it off, so - # disable autonegotiation too - self.no_autonegotiation = True - else: + def activate_esessions(self): + if not (self.session and self.session.enable_encryption): self.begin_e2e_negotiation() + def terminate_esessions(self): + # e2e was enabled, disable it + jid = str(self.session.jid) + thread_id = self.session.thread_id + + self.session.terminate_e2e() + + gajim.connections[self.account].delete_session(jid, thread_id) + + # presumably the user had a good reason to shut it off, so + # disable autonegotiation too + self.no_autonegotiation = True + def begin_negotiation(self): self.no_autonegotiation = True diff --git a/src/chat_control_base.py b/src/chat_control_base.py index 248d4990f..3b6cde993 100644 --- a/src/chat_control_base.py +++ b/src/chat_control_base.py @@ -434,6 +434,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): plugin = gajim.plugin_manager.encryption_plugins[encryption] if not plugin.activate_encryption(self): return + else: + self.terminate_esessions() action.set_state(param) gajim.config.set_per( 'contacts', self.contact.jid, 'encryption', encryption) diff --git a/src/common/config.py b/src/common/config.py index b1c096d8a..9c8585fed 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -481,7 +481,6 @@ class Config: }, {}), 'contacts': ({ 'encryption': [ opt_str, '', _('Encryption used for this contact.')], - 'autonegotiate_esessions': [opt_bool, False, _('Should Gajim automatically start an encrypted session with this contact when possible?')], 'speller_language': [ opt_str, '', _('Language for which we want to check misspelled words')], }, {}), 'rooms': ({ diff --git a/src/common/connection.py b/src/common/connection.py index e9f1ab2bb..baf18bc45 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -319,10 +319,6 @@ class CommonConnection: if obj.session: obj.session.last_send = time.time() - # XEP-0200 - if obj.session.enable_encryption: - obj.correction_msg = obj.session.encrypt_stanza(obj.correction_msg) - self._push_stanza_message_outgoing(obj, obj.correction_msg) return @@ -418,20 +414,6 @@ class CommonConnection: obj.session.last_send = time.time() msg_iq.setThread(obj.session.thread_id) - # XEP-0200 - if obj.session.enable_encryption: - msg_iq = obj.session.encrypt_stanza(msg_iq) - if self.carbons_enabled: - msg_iq.addChild(name='private', - namespace=nbxmpp.NS_CARBONS) - msg_iq.addChild(name='no-permanent-store', - namespace=nbxmpp.NS_MSG_HINTS) - msg_iq.addChild(name='no-copy', - namespace=nbxmpp.NS_MSG_HINTS) - if only_chatste: - msg_iq.addChild(name='no-store', - namespace=nbxmpp.NS_MSG_HINTS) - self._push_stanza_message_outgoing(obj, msg_iq) def _push_stanza_message_outgoing(self, obj, msg_iq): diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index ec25feaf9..80f4cf19d 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -1089,15 +1089,6 @@ class ConnectionHandlersBase: if not obj.encrypted: self._on_message_received(obj) - if obj.encrypted == 'xep200': - try: - obj.stanza = obj.session.decrypt_stanza(obj.stanza) - obj.msgtxt = obj.stanza.getBody() - except Exception: - gajim.nec.push_incoming_event(FailedDecryptEvent(None, - conn=self, msg_obj=obj)) - return - def _on_message_received(self, obj): if isinstance(obj, MessageReceivedEvent): gajim.nec.push_incoming_event( diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index c30823ccc..ed2a9dd41 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -1122,6 +1122,7 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.get_id() self.forwarded = False self.sent = False + self.encrypted = False account = self.conn.name our_full_jid = gajim.get_jid_from_account(account, full=True) @@ -1281,52 +1282,8 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.session.last_receive = time_time() - # check if the message is a XEP-0020 feature negotiation request - if not self.forwarded and self.stanza.getTag('feature', - namespace=nbxmpp.NS_FEATURE): - if gajim.HAVE_PYCRYPTO: - feature = self.stanza.getTag(name='feature', - namespace=nbxmpp.NS_FEATURE) - form = nbxmpp.DataForm(node=feature.getTag('x')) - if not form: - return - - if not form.getField('FORM_TYPE'): - return - - if form['FORM_TYPE'] == 'urn:xmpp:ssn': - self.session.handle_negotiation(form) - else: - reply = self.stanza.buildReply() - reply.setType('error') - reply.addChild(feature) - err = nbxmpp.ErrorNode('service-unavailable', typ='cancel') - reply.addChild(node=err) - self.conn.connection.send(reply) - return - - if not self.forwarded and self.stanza.getTag('init', - namespace=nbxmpp.NS_ESESSION_INIT): - init = self.stanza.getTag(name='init', - namespace=nbxmpp.NS_ESESSION_INIT) - form = nbxmpp.DataForm(node=init.getTag('x')) - - self.session.handle_negotiation(form) - - return - self._generate_timestamp(self.stanza.getTimestamp()) - - self.encrypted = False - xep_200_encrypted = self.stanza.getTag('c', - namespace=nbxmpp.NS_STANZA_CRYPTO) - if xep_200_encrypted: - if self.forwarded: - # Ignore E2E forwarded encrypted messages - return False - self.encrypted = 'xep200' - return True class ZeroconfMessageReceivedEvent(MessageReceivedEvent): diff --git a/src/dialogs.py b/src/dialogs.py index bfe84ba30..48203b566 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -5315,82 +5315,6 @@ class DataFormWindow(Dialog): self.df_response_ok(form) self.destroy() -class ESessionInfoWindow: - """ - Class for displaying information about a XEP-0116 encrypted session - """ - def __init__(self, session, transient_for=None): - self.session = session - - self.xml = gtkgui_helpers.get_gtk_builder('esession_info_window.ui') - self.xml.connect_signals(self) - - self.security_image = self.xml.get_object('security_image') - self.verify_now_button = self.xml.get_object('verify_now_button') - self.button_label = self.xml.get_object('verification_status_label') - self.window = self.xml.get_object('esession_info_window') - self.update_info() - self.window.set_transient_for(transient_for) - - self.window.show_all() - - def update_info(self): - labeltext = _('''Your chat session with %(jid)s is encrypted.\n\nThis session's Short Authentication String is %(sas)s.''') % {'jid': self.session.jid, 'sas': self.session.sas} - - if self.session.verified_identity: - labeltext += '\n\n' + _('''You have already verified this contact's identity.''') - security_image = 'security-high' - if self.session.control: - self.session.control._show_lock_image(True, 'E2E', True, - self.session.is_loggable(), True) - - verification_status = _('''Contact's identity verified''') - self.window.set_title(verification_status) - self.xml.get_object('verification_status_label').set_markup( - '%s' % verification_status) - - self.xml.get_object('dialog-action_area1').set_no_show_all(True) - self.button_label.set_text(_('Verify again…')) - else: - if self.session.control: - self.session.control._show_lock_image(True, 'E2E', True, - self.session.is_loggable(), False) - labeltext += '\n\n' + _('''To be certain that only the expected person can read your messages or send you messages, you need to verify their identity by clicking the button below.''') - security_image = 'security-low' - - verification_status = _('''Contact's identity NOT verified''') - self.window.set_title(verification_status) - self.xml.get_object('verification_status_label').set_markup( - '%s' % verification_status) - - self.button_label.set_text(_('Verify…')) - - path = gtkgui_helpers.get_icon_path(security_image, 32) - self.security_image.set_from_file(path) - - self.xml.get_object('info_display').set_markup(labeltext) - - def on_close_button_clicked(self, widget): - self.window.destroy() - - def on_verify_now_button_clicked(self, widget): - pritext = _('''Have you verified the contact's identity?''') - sectext = _('''To prevent talking to an unknown person, you should speak to %(jid)s directly (in person or on the phone) and verify that they see the same Short Authentication String (SAS) as you.\n\nThis session's Short Authentication String is %(sas)s.''') % {'jid': self.session.jid, 'sas': self.session.sas} - sectext += '\n\n' + _('Did you talk to the remote contact and verify the SAS?') - - def on_yes(checked): - self.session._verified_srs_cb() - self.session.verified_identity = True - self.update_info() - - def on_no(): - self.session._unverified_srs_cb() - self.session.verified_identity = False - self.update_info() - - YesNoDialog(pritext, sectext, on_response_yes=on_yes, - on_response_no=on_no, transient_for=self.window) - class ResourceConflictDialog(TimeoutDialog, InputDialog): def __init__(self, title, text, resource, ok_handler): diff --git a/src/gui_menu_builder.py b/src/gui_menu_builder.py index f61ae68bd..f03d61a87 100644 --- a/src/gui_menu_builder.py +++ b/src/gui_menu_builder.py @@ -245,8 +245,6 @@ control=None, gc_contact=None, is_anonymous=True): 'remove_from_roster_menuitem') manage_contact_menuitem = xml.get_object('manage_contact') convert_to_gc_menuitem = xml.get_object('convert_to_groupchat_menuitem') - encryption_separator = xml.get_object('encryption_separator') - toggle_e2e_menuitem = xml.get_object('toggle_e2e_menuitem') last_separator = xml.get_object('last_separator') items_to_hide = [] @@ -321,21 +319,6 @@ control=None, gc_contact=None, is_anonymous=True): if not show_start_chat: items_to_hide.append(start_chat_menuitem) - if not show_encryption or not control: - items_to_hide += [encryption_separator, toggle_e2e_menuitem] - else: - e2e_is_active = control.session is not None and \ - control.session.enable_encryption - - # disable esessions if we or the other client don't support them - if not gajim.HAVE_PYCRYPTO or not contact.supports(NS_ESESSION) or \ - not gajim.config.get_per('accounts', account, 'enable_esessions'): - toggle_e2e_menuitem.set_sensitive(False) - else: - toggle_e2e_menuitem.set_active(e2e_is_active) - toggle_e2e_menuitem.connect('activate', - control._on_toggle_e2e_menuitem_activate) - if not show_buttonbar_items: items_to_hide += [history_menuitem, send_file_menuitem, information_menuitem, convert_to_gc_menuitem, last_separator]