diff --git a/src/chat_control.py b/src/chat_control.py index 6459e4fa1..5d773ca3a 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1050,15 +1050,17 @@ class ChatControl(ChatControlBase): self.on_avatar_eventbox_button_press_event) self.handlers[id] = widget - widget = self.xml.get_widget('gpg_togglebutton') - id = widget.connect('clicked', self.on_toggle_gpg_togglebutton) - self.handlers[id] = widget - - if self.contact.jid in gajim.encrypted_chats[self.account]: - self.xml.get_widget('gpg_togglebutton').set_active(True) - self.set_session(session) + # Enable ecryption if needed + gpg_pref = gajim.config.get_per('contacts', contact.jid, + 'gpg_enabled') + if gpg_pref and gajim.config.get_per('accounts', self.account, 'keyid') and\ + gajim.connections[self.account].USE_GPG: + gajim.encrypted_chats[self.account].append(contact.jid) + msg = _('GPG encryption enabled') + ChatControlBase.print_conversation_line(self, msg, 'status', '', None) + self.status_tooltip = gtk.Tooltips() self.update_ui() # restore previous conversation @@ -1164,8 +1166,6 @@ class ChatControl(ChatControlBase): gtk.gdk.INTERP_BILINEAR) banner_status_img.set_from_pixbuf(scaled_pix) - self._update_gpg() - def draw_banner_text(self): '''Draw the text in the fat line at the top of the window that houses the name, jid. @@ -1254,34 +1254,26 @@ class ChatControl(ChatControlBase): # setup the label that holds name and jid banner_name_label.set_markup(label_text) - def on_toggle_gpg_togglebutton(self, widget): - gajim.config.set_per('contacts', self.contact.jid, 'gpg_enabled', - widget.get_active()) - - def _update_gpg(self): - tb = self.xml.get_widget('gpg_togglebutton') - # we can do gpg - # if self.contact is our own contact info (transports), - # don't enable pgp - if self.contact.keyID and not gajim.jid_is_transport(self.contact.jid): - tb.set_sensitive(True) - tt = _('OpenPGP Encryption') - - # restore gpg pref - gpg_pref = gajim.config.get_per('contacts', self.contact.jid, - 'gpg_enabled') - if gpg_pref == None: - gajim.config.add_per('contacts', self.contact.jid) - gpg_pref = gajim.config.get_per('contacts', self.contact.jid, - 'gpg_enabled') - tb.set_active(gpg_pref) - + def _toggle_gpg(self): + ec = gajim.encrypted_chats[self.account] + if self.contact.jid in ec: + # Disable encryption + ec.remove(self.contact.jid) + gpg_is_active = False + msg = _('GPG encryption disabled') else: - tb.set_sensitive(False) - #we talk about a contact here - tt = _('%s has not broadcast an OpenPGP key, nor has one been assigned') %\ - self.contact.get_shown_name() - gtk.Tooltips().set_tip(self.xml.get_widget('gpg_eventbox'), tt) + # Enable encryption + ec.append(self.contact.jid) + gpg_is_active = True + msg = _('GPG encryption enabled') + + gpg_pref = gajim.config.get_per('contacts', self.contact.jid, + 'gpg_enabled') + if gpg_pref is None: + gajim.config.add_per('contacts', self.contact.jid) + gajim.config.set_per('contacts', self.contact.jid, 'gpg_enabled', + gpg_is_active) + ChatControlBase.print_conversation_line(self, msg, 'status', '', None) def _process_command(self, message): if message[0] != '/': @@ -1369,9 +1361,13 @@ class ChatControl(ChatControlBase): encrypted = bool(self.session) and self.session.enable_encryption keyID = '' - if self.xml.get_widget('gpg_togglebutton').get_active(): + gpg_pref = gajim.config.get_per('contacts', contact.jid, + 'gpg_enabled') + if gpg_pref: keyID = contact.keyID encrypted = True + if keyID == '': + keyID = 'UNKNOWN' chatstates_on = gajim.config.get('outgoing_chat_state_notifications') != \ 'disabled' @@ -1401,7 +1397,7 @@ class ChatControl(ChatControlBase): gobject.source_remove(self.possible_paused_timeout_id) gobject.source_remove(self.possible_inactive_timeout_id) self._schedule_activity_timers() - + if not ChatControlBase.send_message(self, message, keyID, type = 'chat', chatstate = chatstate_to_send, composing_xep = composing_xep, process_command = process_command): @@ -1512,17 +1508,14 @@ class ChatControl(ChatControlBase): # GPG encryption ec = gajim.encrypted_chats[self.account] if encrypted and jid not in ec: - msg = _('OpenPGP Encryption enabled') + msg = _('The following message was encrypted') ChatControlBase.print_conversation_line(self, msg, 'status', '', tim) - ec.append(jid) + self._toggle_gpg() elif not encrypted and jid in ec: - msg = _('OpenPGP Encryption disabled') + msg = _('The following message was NOT encrypted') ChatControlBase.print_conversation_line(self, msg, 'status', '', tim) - ec.remove(jid) - self.xml.get_widget('gpg_togglebutton').set_active(encrypted) - if not frm: kind = 'incoming' name = contact.get_shown_name() @@ -1649,13 +1642,17 @@ class ChatControl(ChatControlBase): contact = self.parent_win.get_active_contact() jid = contact.jid - - # check if gpg capabitlies or else make gpg toggle insensitive - gpg_btn = self.xml.get_widget('gpg_togglebutton') - isactive = gpg_btn.get_active() - is_sensitive = gpg_btn.get_property('sensitive') - toggle_gpg_menuitem.set_active(isactive) - toggle_gpg_menuitem.set_property('sensitive', is_sensitive) + + # check if we support and use gpg + if not gajim.config.get_per('accounts', self.account, 'keyid') or\ + not gajim.connections[self.account].USE_GPG or\ + gajim.jid_is_transport(jid): + toggle_gpg_menuitem.set_sensitive(False) + else: + toggle_gpg_menuitem.set_sensitive(True) + gpg_pref = gajim.config.get_per('contacts', jid, + 'gpg_enabled') + toggle_gpg_menuitem.set_active(bool(gpg_pref)) # TODO: check that the remote client supports e2e if not gajim.HAVE_PYCRYPTO: @@ -1694,14 +1691,15 @@ class ChatControl(ChatControlBase): id = send_file_menuitem.connect('activate', self._on_send_file_menuitem_activate) self.handlers[id] = send_file_menuitem - id = add_to_roster_menuitem.connect('activate', + id = add_to_roster_menuitem.connect('activate', self._on_add_to_roster_menuitem_activate) - self.handlers[id] = add_to_roster_menuitem - id = toggle_gpg_menuitem.connect('activate', + self.handlers[id] = add_to_roster_menuitem + id = toggle_gpg_menuitem.connect('activate', self._on_toggle_gpg_menuitem_activate) + self.handlers[id] = toggle_gpg_menuitem id = toggle_e2e_menuitem.connect('activate', self._on_toggle_e2e_menuitem_activate) - self.handlers[id] = toggle_gpg_menuitem + self.handlers[id] = toggle_e2e_menuitem id = information_menuitem.connect('activate', self._on_contact_information_menuitem_activate) self.handlers[id] = information_menuitem @@ -2154,10 +2152,7 @@ class ChatControl(ChatControlBase): gajim.interface.roster.on_info(widget, self.contact, self.account) def _on_toggle_gpg_menuitem_activate(self, widget): - # update the button - # this is reverse logic, as we are on 'activate' (before change happens) - tb = self.xml.get_widget('gpg_togglebutton') - tb.set_active(not tb.get_active()) + self._toggle_gpg() def _on_convert_to_gc_menuitem_activate(self, widget): '''user want to invite some friends to chat''' diff --git a/src/common/GnuPG.py b/src/common/GnuPG.py index c7603b8b4..4e281c71d 100644 --- a/src/common/GnuPG.py +++ b/src/common/GnuPG.py @@ -45,8 +45,6 @@ if gajim.HAVE_GPG: self.options.armor = 1 self.options.meta_interactive = 0 self.options.extra_args.append('--no-secmem-warning') - # Nolith's patch - prevent crashs on non fully-trusted keys - self.options.extra_args.append('--always-trust') if self.use_agent: self.options.extra_args.append('--use-agent') @@ -173,7 +171,7 @@ if gajim.HAVE_GPG: try: proc.wait() except IOError: pass - + keyid = '' if resp.has_key('GOODSIG'): keyid = resp['GOODSIG'].split()[0] diff --git a/src/common/connection.py b/src/common/connection.py index 0f8441e17..7147f290b 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -961,9 +961,15 @@ class Connection(ConnectionHandlers): fjid += '/' + resource msgtxt = msg msgenc = '' + if keyID and self.USE_GPG: - #encrypt - msgenc, error = self.gpg.encrypt(msg, [keyID]) + if keyID == 'UNKNOWN': + error = _('Neither the remote presence is signed, nor a key was assigned.') + elif keyID[8:] == 'MISMATCH': + error = _('The contact\'s key does not match the key assigned in Gajim.') + else: + #encrypt + msgenc, error = self.gpg.encrypt(msg, [keyID]) if msgenc and not error: msgtxt = '[This message is encrypted]' lang = os.getenv('LANG') diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 33af3e670..375279b51 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -2199,6 +2199,7 @@ returns the session that we last sent a message to.''' self.dispatch('ERROR', (_('OpenPGP passphrase was not given'), #%s is the account name here _('You will be connected to %s without OpenPGP.') % self.name)) + self.USE_GPG = False signed = '' self.connected = STATUS_LIST.index(show) sshow = helpers.get_xmpp_show(show) diff --git a/src/common/helpers.py b/src/common/helpers.py index 7e6d96d9b..3ac741226 100644 --- a/src/common/helpers.py +++ b/src/common/helpers.py @@ -1094,3 +1094,36 @@ def get_transport_path(transport): return os.path.join(gajim.MY_ICONSETS_PATH, 'transports', transport) # No transport folder found, use default jabber one return get_iconset_path(gajim.config.get('iconset')) + +def prepare_and_validate_gpg_keyID(account, jid, keyID): + '''Returns an eight char long keyID that can be used with for GPG encryption with this contact. + If the given keyID is None, return UNKNOWN; if the key does not match the assigned key + XXXXXXXXMISMATCH is returned. If the key is trusted and not yet assigned, assign it''' + if gajim.connections[account].USE_GPG: + if len(keyID) == 16: + keyID = keyID[8:] + + attached_keys = gajim.config.get_per('accounts', account, + 'attached_gpg_keys').split() + + if jid in attached_keys and keyID: + attachedkeyID = attached_keys[attached_keys.index(jid) + 1] + if attachedkeyID != keyID: + # Mismatch! Another gpg key was expected + keyID += 'MISMATCH' + elif jid in attached_keys: + # An unsigned presence, just use the assigned key + keyID = attached_keys[attached_keys.index(jid) + 1] + elif keyID: + public_keys = gajim.connections[account].ask_gpg_keys() + # Assign the corresponding key, if we have it in our keyring + if public_keys.has_key(keyID): + for u in gajim.contacts.get_contacts(account, jid): + u.keyID = keyID + keys_str = gajim.config.get_per('accounts', account, 'attached_gpg_keys') + keys_str += jid + ' ' + keyID + ' ' + gajim.config.set_per('accounts', account, 'attached_gpg_keys', keys_str) + elif keyID is None: + keyID = 'UNKNOWN' + return keyID + diff --git a/src/gajim.py b/src/gajim.py index b6cb3b6ab..dd5f4f347 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -579,10 +579,11 @@ class Interface: jid = array[0].split('/')[0] keyID = array[5] contact_nickname = array[7] - attached_keys = gajim.config.get_per('accounts', account, - 'attached_gpg_keys').split() - if jid in attached_keys: - keyID = attached_keys[attached_keys.index(jid) + 1] + + # Get the proper keyID + keyID = helpers.prepare_and_validate_gpg_keyID(account, + jid, keyID) + resource = array[3] if not resource: resource = '' diff --git a/src/roster_window.py b/src/roster_window.py index 7058022a9..98d0693a5 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1912,12 +1912,11 @@ class RosterWindow: if keyID[0] == _('None'): if contact.jid in keys: del keys[contact.jid] - for u in gajim.contacts.get_contacts(account, contact.jid): - u.keyID = '' + keyID = '' else: - keys[contact.jid] = keyID[0] - for u in gajim.contacts.get_contacts(account, contact.jid): - u.keyID = keyID[0] + keyID = keyID[0] + keys[contact.jid] = keyID + if gajim.interface.msg_win_mgr.has_window(contact.jid, account): ctrl = gajim.interface.msg_win_mgr.get_control(contact.jid, account) ctrl.update_ui() @@ -1925,6 +1924,9 @@ class RosterWindow: for jid in keys: keys_str += jid + ' ' + keys[jid] + ' ' gajim.config.set_per('accounts', account, 'attached_gpg_keys', keys_str) + for u in gajim.contacts.get_contacts(account, contact.jid): + u.keyID = helpers.prepare_and_validate_gpg_keyID(account, + contact.jid, keyID) def update_avatar_in_gui(self, jid, account): # Update roster