Commit 3fd35a04 authored by Philipp Hörist's avatar Philipp Hörist

Remove PGP encryption/decryption from core

parent 5116af03
......@@ -51,14 +51,6 @@
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkCheckMenuItem" id="toggle_gpg_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Toggle Open_PGP Encryption</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkCheckMenuItem" id="toggle_e2e_menuitem">
<property name="visible">True</property>
......
......@@ -90,7 +90,6 @@ def __init__(self, parent_win, contact, acct, session, resource=None):
ChatControlBase.__init__(self, self.TYPE_ID, parent_win,
'chat_control', contact, acct, resource)
self.gpg_is_active = False
self.last_recv_message_id = None
self.last_recv_message_marks = None
self.last_message_timestamp = None
......@@ -282,25 +281,6 @@ def __init__(self, parent_win, contact, acct, session, resource=None):
# Enable encryption if needed
self.no_autonegotiation = False
e2e_is_active = self.session and self.session.enable_encryption
gpg_pref = gajim.config.get_per('contacts', contact.jid, 'gpg_enabled')
# try GPG first
if not e2e_is_active and gpg_pref and \
gajim.config.get_per('accounts', self.account, 'keyid') and \
gajim.connections[self.account].USE_GPG:
self.gpg_is_active = True
gajim.encrypted_chats[self.account].append(contact.jid)
msg = _('OpenPGP encryption enabled')
ChatControlBase.print_conversation_line(self, msg, 'status', '',
None)
if self.session:
self.session.loggable = gajim.config.get_per('accounts',
self.account, 'log_encrypted_sessions')
# GPG is always authenticated as we use GPG's WoT
self._show_lock_image(self.gpg_is_active, 'OpenPGP',
self.gpg_is_active, self.session and self.session.is_loggable(),
True)
self.update_ui()
self.set_lock_image()
......@@ -350,7 +330,8 @@ def _update_toolbar(self):
send_button = self.xml.get_object('send_button')
send_button.set_sensitive(True)
# Formatting
if self.contact.supports(NS_XHTML_IM) and not self.gpg_is_active:
# TODO: find out what encryption allows for xhtml and which not
if self.contact.supports(NS_XHTML_IM):
self._formattings_button.set_sensitive(True)
self._formattings_button.set_tooltip_text(_(
'Show a list of formattings'))
......@@ -862,57 +843,6 @@ def on_audio_button_toggled(self, widget):
def on_video_button_toggled(self, widget):
self.on_jingle_button_toggled(widget, 'video')
def _toggle_gpg(self):
if not self.gpg_is_active and not self.contact.keyID:
dialogs.ErrorDialog(_('No OpenPGP key assigned'),
_('No OpenPGP key is assigned to this contact. So you cannot '
'encrypt messages with OpenPGP.'))
return
ec = gajim.encrypted_chats[self.account]
if self.gpg_is_active:
# Disable encryption
ec.remove(self.contact.jid)
self.gpg_is_active = False
loggable = False
msg = _('OpenPGP encryption disabled')
ChatControlBase.print_conversation_line(self, msg, 'status', '',
None)
if self.session:
self.session.loggable = True
else:
# Enable encryption
ec.append(self.contact.jid)
self.gpg_is_active = True
msg = _('OpenPGP encryption enabled')
ChatControlBase.print_conversation_line(self, msg, 'status', '',
None)
loggable = gajim.config.get_per('accounts', self.account,
'log_encrypted_sessions')
if self.session:
self.session.loggable = loggable
loggable = self.session.is_loggable()
else:
loggable = loggable and gajim.config.should_log(self.account,
self.contact.jid)
if loggable:
msg = _('Session WILL be logged')
else:
msg = _('Session WILL NOT be logged')
ChatControlBase.print_conversation_line(self, msg,
'status', '', None)
gajim.config.set_per('contacts', self.contact.jid,
'gpg_enabled', self.gpg_is_active)
self._show_lock_image(self.gpg_is_active, 'OpenPGP',
self.gpg_is_active, loggable, True)
def set_lock_image(self):
visible = self.encryption != 'disabled'
loggable = self.session and self.session.is_loggable()
......@@ -963,9 +893,7 @@ def _show_lock_image(self, visible, enc_type='', enc_enabled=False,
def _on_authentication_button_clicked(self, widget):
gajim.plugin_manager.gui_extension_point(
'encryption_dialog' + self.encryption, self)
if self.gpg_is_active:
dialogs.GPGInfoWindow(self, self.parent_win.window)
elif self.session and self.session.enable_encryption:
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,
......@@ -989,12 +917,11 @@ def send_message(self, message, keyID='', chatstate=None, xhtml=None,
encrypted = bool(self.session) and self.session.enable_encryption
keyID = ''
if self.gpg_is_active:
keyID = contact.keyID
encrypted = True
if not keyID:
keyID = 'UNKNOWN'
keyID = contact.keyID
encrypted = True
chatstates_on = gajim.config.get('outgoing_chat_state_notifications') != \
'disabled'
chatstate_to_send = None
if contact is not None:
......@@ -1123,20 +1050,6 @@ def print_conversation(self, text, frm='', tim=None, encrypted=False,
msg = _('The following message was NOT encrypted')
ChatControlBase.print_conversation_line(self, msg, 'status',
'', tim)
else:
# GPG encryption
if encrypted and not self.gpg_is_active:
msg = _('The following message was encrypted')
ChatControlBase.print_conversation_line(self, msg, 'status',
'', tim)
# turn on OpenPGP if this was in fact a XEP-0027 encrypted
# message
if encrypted == 'xep27':
self._toggle_gpg()
elif not encrypted and self.gpg_is_active:
msg = _('The following message was NOT encrypted')
ChatControlBase.print_conversation_line(self, msg, 'status',
'', tim)
if not frm:
kind = 'incoming'
name = contact.get_shown_name()
......@@ -1146,7 +1059,7 @@ def print_conversation(self, text, frm='', tim=None, encrypted=False,
else:
kind = 'outgoing'
name = self.get_our_nick()
if not xhtml and not (encrypted and self.gpg_is_active) and \
if not xhtml and not encrypted and \
gajim.config.get('rst_formatting_outgoing_messages'):
from common.rst_xhtml_generator import create_xhtml
xhtml = create_xhtml(text)
......@@ -1223,9 +1136,8 @@ def get_tab_image(self, count_unread=True):
def prepare_context_menu(self, hide_buttonbar_items=False):
"""
Set compact view menuitem active state sets active and sensitivity state
for toggle_gpg_menuitem sets sensitivity for history_menuitem (False for
tranasports) and file_transfer_menuitem and hide()/show() for
add_to_roster_menuitem
for history_menuitem (False for tranasports) and file_transfer_menuitem
and hide()/show() for add_to_roster_menuitem
"""
if gajim.jid_is_transport(self.contact.jid):
menu = gui_menu_builder.get_transport_menu(self.contact,
......@@ -1520,7 +1432,7 @@ def _on_message_tv_buffer_changed(self, textbuffer):
'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 not self.gpg_is_active \
want_e2e = not e2e_is_active and self.encryption == '' \
and e2e_pref
if want_e2e and not self.no_autonegotiation \
......@@ -1717,9 +1629,6 @@ def _on_add_to_roster_menuitem_activate(self, widget):
def _on_contact_information_menuitem_activate(self, widget):
gajim.interface.roster.on_info(widget, self.contact, self.account)
def _on_toggle_gpg_menuitem_activate(self, widget):
self._toggle_gpg()
def _on_convert_to_gc_menuitem_activate(self, widget):
"""
User wants to invite some friends to chat
......
......@@ -179,11 +179,6 @@ class StandardCommonChatCommands(CommandContainer):
def clear(self):
self.conv_textview.clear()
@command
@doc(_("Toggle the OpenPGP encryption"))
def gpg(self):
self._toggle_gpg()
@command
@doc(_("Send a ping to the contact"))
def ping(self):
......
......@@ -480,7 +480,6 @@ class Config:
'state_muc_directed_msg_color': [ opt_color, 'red2' ],
}, {}),
'contacts': ({
'gpg_enabled': [ opt_bool, False, _('Is OpenPGP enabled for this contact?')],
'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')],
......
......@@ -296,65 +296,9 @@ def _prepare_message(self, obj):
if not obj.message and obj.chatstate is None and obj.form_node is None:
return
if obj.keyID and self.USE_GPG:
self._encrypt_message(obj)
return
self._build_message_stanza(obj)
def _encrypt_message(self, obj):
obj.xhtml = None
if obj.keyID == 'UNKNOWN':
error = _('Neither the remote presence is signed, nor a key was '
'assigned.')
elif obj.keyID.endswith('MISMATCH'):
error = _('The contact\'s key (%s) does not match the key assigned '
'in Gajim.' % obj.keyID[:8])
else:
myKeyID = gajim.config.get_per('accounts', self.name, 'keyid')
key_list = [obj.keyID, myKeyID]
def _on_encrypted(output):
msgenc, error = output
if error.startswith('NOT_TRUSTED'):
def _on_always_trust(answer):
if answer:
gajim.thread_interface(
self.gpg.encrypt, [obj.message, key_list, True],
_on_encrypted, [])
else:
self._finished_encrypt(obj, msgenc=msgenc,
error=error)
gajim.nec.push_incoming_event(GPGTrustKeyEvent(None,
conn=self, keyID=error.split(' ')[-1],
callback=_on_always_trust))
else:
self._finished_encrypt(obj, msgenc=msgenc, error=error)
gajim.thread_interface(
self.gpg.encrypt, [obj.message, key_list, False],
_on_encrypted, [])
return
self._finished_encrypt(obj, error=error)
def _finished_encrypt(self, obj, msgenc=None, error=None):
if error:
gajim.nec.push_incoming_event(
MessageNotSentEvent(
None, conn=self, jid=obj.jid, message=obj.message,
error=error, time_=time.time(), session=obj.session))
return
self._build_message_stanza(obj, msgenc)
def _build_message_stanza(self, obj, msgenc=None):
if msgenc:
msgtxt = '[This message is *encrypted* (See :XEP:`27`]'
lang = os.getenv('LANG')
if lang is not None and not lang.startswith('en'):
# we're not english: one in locale and one en
msgtxt = _('[This message is *encrypted* (See :XEP:`27`]') + \
' (' + msgtxt + ')'
else:
msgtxt = obj.message
def _build_message_stanza(self, obj):
if obj.jid == gajim.get_jid_from_account(self.name):
fjid = obj.jid
else:
......@@ -368,17 +312,10 @@ def _build_message_stanza(self, obj, msgenc=None):
namespace=nbxmpp.NS_CORRECT)
id2 = self.connection.getAnID()
obj.correction_msg.setID(id2)
obj.correction_msg.setBody(msgtxt)
obj.correction_msg.setBody(obj.message)
if obj.xhtml:
obj.correction_msg.setXHTML(obj.xhtml)
if msgenc:
encrypted_tag = obj.correction_msg.getTag(
'x', namespace=nbxmpp.NS_ENCRYPTED)
obj.correction_msg.delChild(encrypted_tag)
obj.correction_msg.setTag(
'x', namespace=nbxmpp.NS_ENCRYPTED).setData(msgenc)
if obj.session:
obj.session.last_send = time.time()
......@@ -390,22 +327,19 @@ def _build_message_stanza(self, obj, msgenc=None):
return
if obj.type_ == 'chat':
msg_iq = nbxmpp.Message(body=msgtxt, typ=obj.type_,
msg_iq = nbxmpp.Message(body=obj.message, typ=obj.type_,
xhtml=obj.xhtml)
else:
if obj.subject:
msg_iq = nbxmpp.Message(body=msgtxt, typ='normal',
msg_iq = nbxmpp.Message(body=obj.message, typ='normal',
subject=obj.subject, xhtml=obj.xhtml)
else:
msg_iq = nbxmpp.Message(body=msgtxt, typ='normal',
msg_iq = nbxmpp.Message(body=obj.message, typ='normal',
xhtml=obj.xhtml)
if obj.msg_id:
msg_iq.setID(obj.msg_id)
if msgenc:
msg_iq.setTag('x', namespace=nbxmpp.NS_ENCRYPTED).setData(msgenc)
if obj.form_node:
msg_iq.addChild(node=obj.form_node)
if obj.label:
......@@ -460,7 +394,7 @@ def _build_message_stanza(self, obj, msgenc=None):
if obj.chatstate and contact and contact.supports(nbxmpp.NS_CHATSTATES):
msg_iq.setTag(obj.chatstate, namespace=nbxmpp.NS_CHATSTATES)
only_chatste = False
if not msgtxt:
if not obj.message:
only_chatste = True
if only_chatste and not obj.session.enable_encryption:
msg_iq.setTag('no-store',
......@@ -468,8 +402,9 @@ def _build_message_stanza(self, obj, msgenc=None):
# XEP-0184
if obj.jid != gajim.get_jid_from_account(self.name):
if msgtxt and gajim.config.get_per('accounts', self.name,
'request_receipt'):
request = gajim.config.get_per('accounts', self.name,
'request_receipt')
if obj.message and request:
msg_iq.setTag('request', namespace=nbxmpp.NS_RECEIPTS)
if obj.forward_from:
......
......@@ -897,7 +897,7 @@ def __init__(self):
gajim.ged.register_event_handler('message-received', ged.CORE,
self._nec_message_received)
gajim.ged.register_event_handler('mam-message-received', ged.CORE,
self._nec_mam_message_received)
self._nec_message_received)
gajim.ged.register_event_handler('decrypted-message-received', ged.CORE,
self._nec_decrypted_message_received)
......@@ -911,7 +911,7 @@ def cleanup(self):
gajim.ged.remove_event_handler('message-received', ged.CORE,
self._nec_message_received)
gajim.ged.remove_event_handler('mam-message-received', ged.CORE,
self._nec_mam_message_received)
self._nec_message_received)
gajim.ged.remove_event_handler('decrypted-message-received', ged.CORE,
self._nec_decrypted_message_received)
......@@ -1080,14 +1080,6 @@ def _nec_gc_presence_received(self, obj):
if sess.enable_encryption:
sess.terminate_e2e()
def decrypt_thread(self, encmsg, keyID, obj):
decmsg = self.gpg.decrypt(encmsg, keyID)
decmsg = self.connection.Dispatcher.replace_non_character(decmsg)
# \x00 chars are not allowed in C (so in GTK)
obj.msgtxt = decmsg.replace('\x00', '')
obj.encrypted = 'xep27'
self.gpg_messages_to_decrypt.remove([encmsg, keyID, obj])
def _nec_message_received(self, obj):
if obj.conn.name != self.name:
return
......@@ -1106,59 +1098,6 @@ def _nec_message_received(self, obj):
conn=self, msg_obj=obj))
return
if obj.enc_tag and self.USE_GPG:
encmsg = obj.enc_tag.getData()
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
if keyID:
self.gpg_messages_to_decrypt.append([encmsg, keyID, obj])
if len(self.gpg_messages_to_decrypt) == 1:
gajim.thread_interface(self.decrypt_thread, [encmsg, keyID,
obj], self._on_message_decrypted, [obj])
return
gajim.nec.push_incoming_event(DecryptedMessageReceivedEvent(None,
conn=self, msg_obj=obj))
def _nec_mam_message_received(self, obj):
if obj.conn.name != self.name:
return
if obj.enc_tag and self.USE_GPG:
encmsg = obj.enc_tag.getData()
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
if keyID:
self.gpg_messages_to_decrypt.append([encmsg, keyID, obj])
if len(self.gpg_messages_to_decrypt) == 1:
gajim.thread_interface(self.decrypt_thread, [encmsg, keyID,
obj], self._on_mam_message_decrypted, [obj])
return
gajim.nec.push_incoming_event(MamDecryptedMessageReceivedEvent(None,
conn=self, msg_obj=obj))
def _on_message_decrypted(self, output, obj):
if len(self.gpg_messages_to_decrypt):
encmsg, keyID, obj2 = self.gpg_messages_to_decrypt[0]
if type(obj2) == MessageReceivedEvent:
cb = self._on_message_decrypted
else:
cb = self._on_mam_message_decrypted
gajim.thread_interface(self.decrypt_thread, [encmsg, keyID, obj2],
cb, [obj2])
gajim.nec.push_incoming_event(DecryptedMessageReceivedEvent(None,
conn=self, msg_obj=obj))
def _on_mam_message_decrypted(self, output, obj):
if len(self.gpg_messages_to_decrypt):
encmsg, keyID, obj2 = self.gpg_messages_to_decrypt[0]
if type(obj2) == MessageReceivedEvent:
cb = self._on_message_decrypted
else:
cb = self._on_mam_message_decrypted
gajim.thread_interface(self.decrypt_thread, [encmsg, keyID, obj2],
cb, [obj2])
gajim.nec.push_incoming_event(MamDecryptedMessageReceivedEvent(None,
conn=self, msg_obj=obj))
def _on_message_received(self, obj):
if isinstance(obj, MessageReceivedEvent):
gajim.nec.push_incoming_event(
......
......@@ -1035,6 +1035,7 @@ class MamMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
def init(self):
self.additional_data = {}
self.encrypted = False
def generate(self):
if not self.stanza:
......@@ -1067,7 +1068,6 @@ def generate(self):
self.with_ = to_
self.direction = 'to'
self.resource = gajim.get_resource_from_jid(self.msg_.getAttr('to'))
self.enc_tag = self.msg_.getTag('x', namespace=nbxmpp.NS_ENCRYPTED)
return True
class MamDecryptedMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
......@@ -1216,33 +1216,31 @@ def generate(self):
conn=self.conn, stanza=forwarded))
return
self.enc_tag = self.stanza.getTag('x', namespace=nbxmpp.NS_ENCRYPTED)
if not self.enc_tag:
# Mediated invitation?
muc_user = self.stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER)
if muc_user:
if muc_user.getTag('decline'):
gajim.nec.push_incoming_event(
GcDeclineReceivedEvent(
None, conn=self.conn,
room_jid=self.fjid, stanza=muc_user))
return
if muc_user.getTag('invite'):
gajim.nec.push_incoming_event(
GcInvitationReceivedEvent(
None, conn=self.conn, jid_from=self.fjid,
mediated=True, stanza=muc_user))
return
else:
# Direct invitation?
direct = self.stanza.getTag(
'x', namespace=nbxmpp.NS_CONFERENCE)
if direct:
gajim.nec.push_incoming_event(
GcInvitationReceivedEvent(
None, conn=self.conn, jid_from=self.fjid,
mediated=False, stanza=direct))
return
# Mediated invitation?
muc_user = self.stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER)
if muc_user:
if muc_user.getTag('decline'):
gajim.nec.push_incoming_event(
GcDeclineReceivedEvent(
None, conn=self.conn,
room_jid=self.fjid, stanza=muc_user))
return
if muc_user.getTag('invite'):
gajim.nec.push_incoming_event(
GcInvitationReceivedEvent(
None, conn=self.conn, jid_from=self.fjid,
mediated=True, stanza=muc_user))
return
else:
# Direct invitation?
direct = self.stanza.getTag(
'x', namespace=nbxmpp.NS_CONFERENCE)
if direct:
gajim.nec.push_incoming_event(
GcInvitationReceivedEvent(
None, conn=self.conn, jid_from=self.fjid,
mediated=False, stanza=direct))
return
self.thread_id = self.stanza.getThread()
self.mtype = self.stanza.getType()
......
......@@ -5391,64 +5391,6 @@ def on_no():
YesNoDialog(pritext, sectext, on_response_yes=on_yes,
on_response_no=on_no, transient_for=self.window)
class GPGInfoWindow:
"""
Class for displaying information about a XEP-0116 encrypted session
"""
def __init__(self, control, transient_for=None):
xml = gtkgui_helpers.get_gtk_builder('esession_info_window.ui')
security_image = xml.get_object('security_image')
status_label = xml.get_object('verification_status_label')
info_label = xml.get_object('info_display')
verify_now_button = xml.get_object('verify_now_button')
self.window = xml.get_object('esession_info_window')
account = control.account
keyID = control.contact.keyID
error = None
verify_now_button.set_no_show_all(True)
verify_now_button.hide()
if keyID.endswith('MISMATCH'):
verification_status = _('''Contact's identity NOT verified''')
info = _('The contact\'s key (%s) <b>does not match</b> the key '
'assigned in Gajim.') % keyID[:8]
image = 'security-low'
elif not keyID:
# No key assigned nor a key is used by remote contact
verification_status = _('No OpenPGP key assigned')
info = _('No OpenPGP key is assigned to this contact. So you cannot'
' encrypt messages.')
image = 'security-low'
else:
error = gajim.connections[account].gpg.encrypt('test', [keyID])[1]
if error:
verification_status = _('''Contact's identity NOT verified''')
info = _('OpenPGP key is assigned to this contact, but <b>you '
'do not trust their key</b>, so message <b>cannot</b> be '
'encrypted. Use your OpenPGP client to trust their key.')
image = 'security-low'
else:
verification_status = _('''Contact's identity verified''')
info = _('OpenPGP Key is assigned to this contact, and you '
'trust their key, so messages will be encrypted.')
image = 'security-high'
status_label.set_markup('<b><span size="x-large">%s</span></b>' % \
verification_status)
info_label.set_markup(info)
path = gtkgui_helpers.get_icon_path(image, 32)
security_image.set_from_file(path)
self.window.set_transient_for(transient_for)
xml.connect_signals(self)
self.window.show_all()
def on_close_button_clicked(self, widget):
self.window.destroy()
class ResourceConflictDialog(TimeoutDialog, InputDialog):
def __init__(self, title, text, resource, ok_handler):
......
......@@ -257,9 +257,8 @@ def begin_e2e_negotiation(self):
def prepare_context_menu(self, hide_buttonbar_items=False):
"""
Set compact view menuitem active state sets active and sensitivity state
for toggle_gpg_menuitem sets sensitivity for history_menuitem (False for
tranasports) and file_transfer_menuitem and hide()/show() for
add_to_roster_menuitem
for history_menuitem (False for tranasports) and file_transfer_menuitem