diff --git a/src/common/GnuPG.py b/src/common/GnuPG.py index 715ac7bf8..d5278508d 100644 --- a/src/common/GnuPG.py +++ b/src/common/GnuPG.py @@ -35,6 +35,7 @@ if gajim.HAVE_GPG: GnuPGInterface.GnuPG.__init__(self) self.use_agent = use_agent self._setup_my_options() + self.always_trust = False def _setup_my_options(self): self.options.armor = 1 @@ -71,10 +72,13 @@ if gajim.HAVE_GPG: resp[ keyword ] = "" return resp - def encrypt(self, str_, recipients): + def encrypt(self, str_, recipients, always_trust=False): self.options.recipients = recipients # a list! - proc = self.run(['--encrypt'], create_fhs=['stdin', 'stdout', 'status', + opt = ['--encrypt'] + if always_trust or self.always_trust: + opt.append('--always-trust') + proc = self.run(opt, create_fhs=['stdin', 'stdout', 'status', 'stderr']) proc.handles['stdin'].write(str_) try: @@ -100,6 +104,9 @@ if gajim.HAVE_GPG: try: proc.wait() except IOError: pass + if 'INV_RECP' in resp and resp['INV_RECP'].split()[0] == '10': + # unusable recipient "Key not trusted" + return '', 'NOT_TRUSTED' if 'BEGIN_ENCRYPTION' in resp and 'END_ENCRYPTION' in resp: # Encryption succeeded, even if there is output on stderr. Maybe # verbose is on diff --git a/src/common/connection.py b/src/common/connection.py index e1a4a2a08..2d20dcf62 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -1180,17 +1180,33 @@ class Connection(ConnectionHandlers): elif keyID.endswith('MISMATCH'): error = _('The contact\'s key (%s) does not match the key assigned in Gajim.' % keyID[:8]) else: - def encrypt_thread(msg, keyID): + def encrypt_thread(msg, keyID, always_trust=False): # encrypt message. This function returns (msgenc, error) - return self.gpg.encrypt(msg, [keyID]) - gajim.thread_interface(encrypt_thread, [msg, keyID], - self._on_message_encrypted, [type_, msg, msgtxt, - original_message, fjid, resource, jid, xhtml, subject, - chatstate, composing_xep, forward_from, delayed, session, - form_node, user_nick, keyID, callback, callback_args]) + return self.gpg.encrypt(msg, [keyID], always_trust) + def _on_encrypted(output): + msgenc, error = output + if error == 'NOT_TRUSTED': + def _on_always_trust(answer): + if answer: + gajim.thread_interface(encrypt_thread, [msg, keyID, + True], _on_encrypted, []) + else: + self._on_message_encrypted(output, type_, msg, msgtxt, + original_message, fjid, resource, jid, xhtml, + subject, chatstate, composing_xep, forward_from, + delayed, session, form_node, user_nick, keyID, + callback, callback_args) + self.dispatch('GPG_ALWAYS_TRUST', _on_always_trust) + else: + self._on_message_encrypted(output, type_, msg, msgtxt, + original_message, fjid, resource, jid, xhtml, subject, + chatstate, composing_xep, forward_from, delayed, session, + form_node, user_nick, keyID, callback, callback_args) + gajim.thread_interface(encrypt_thread, [msg, keyID, False], + _on_encrypted, []) return - self._on_message_encrypted(self, ('', error), type_, msg, msgtxt, + self._on_message_encrypted(('', error), type_, msg, msgtxt, original_message, fjid, resource, jid, xhtml, subject, chatstate, composing_xep, forward_from, delayed, session, form_node, user_nick, keyID, callback, callback_args) diff --git a/src/gajim.py b/src/gajim.py index 86ae2d8b2..07f28c2f2 100644 --- a/src/gajim.py +++ b/src/gajim.py @@ -1532,6 +1532,21 @@ class Interface: self.gpg_passphrase[keyid] = request request.add_callback(account, callback) + def handle_event_gpg_always_trust(self, account, callback): + #('GPG_ALWAYS_TRUST', account, callback) + def on_yes(checked): + if checked: + gajim.connections[account].gpg.always_trust = True + callback(True) + + def on_no(): + callback(False) + + dialogs.YesNoDialog(_('GPG key not trusted'), _('The GPG key used to ' + 'encrypt this chat is not trusted. Do you really want to encrypt this ' + 'message?'), checktext=_('Do _not ask me again'), + on_response_yes=on_yes, on_response_no=on_no) + def handle_event_password_required(self, account, array): #('PASSWORD_REQUIRED', account, None) text = _('Enter your password for account %s') % account @@ -2295,6 +2310,7 @@ class Interface: self.handle_event_unique_room_id_unsupported, 'UNIQUE_ROOM_ID_SUPPORTED': self.handle_event_unique_room_id_supported, 'GPG_PASSWORD_REQUIRED': self.handle_event_gpg_password_required, + 'GPG_ALWAYS_TRUST': self.handle_event_gpg_always_trust, 'PASSWORD_REQUIRED': self.handle_event_password_required, 'SSL_ERROR': self.handle_event_ssl_error, 'FINGERPRINT_ERROR': self.handle_event_fingerprint_error,