summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2011-11-12 02:48:13 +0100
committerFlorent Le Coz <louiz@louiz.org>2011-11-12 02:48:13 +0100
commit6b9d166e1cfe6c71a1f55d86e144a17fc3e73581 (patch)
tree093dec7d6a704ec7f7b3a0acf061726d0e02d14e
parent3dda32ea5b2e5329e035f2b3f8ee49271e1512b3 (diff)
downloadpoezio-6b9d166e1cfe6c71a1f55d86e144a17fc3e73581.tar.gz
poezio-6b9d166e1cfe6c71a1f55d86e144a17fc3e73581.tar.bz2
poezio-6b9d166e1cfe6c71a1f55d86e144a17fc3e73581.tar.xz
poezio-6b9d166e1cfe6c71a1f55d86e144a17fc3e73581.zip
Gpg module: send signed presences, and verify the signature in received presences.
-rw-r--r--plugins/gpg/__init__.py70
1 files changed, 69 insertions, 1 deletions
diff --git a/plugins/gpg/__init__.py b/plugins/gpg/__init__.py
index 88259acf..2c6d9981 100644
--- a/plugins/gpg/__init__.py
+++ b/plugins/gpg/__init__.py
@@ -1,8 +1,76 @@
from gpg import gnupg
+from xml.etree import cElementTree as ET
+import xml.sax.saxutils
from plugin import BasePlugin
+import logging
+log = logging.getLogger(__name__)
+
+NS_SIGNED = "jabber:x:signed"
+NS_ENCRYPTED = "jabber:x:encrypted"
+
class Plugin(BasePlugin):
def init(self):
- pass
+ self.contacts = {}
+ # a dict of {full-JID: 'signed'/'valid'/'invalid'}
+ # Whenever we receive a signed presence from a JID, we add it to this
+ # dict, this way we know if we can encrypt the messages we will send to
+ # this JID.
+ # If that resource sends a non-signed presence, then we remove it
+ # from that dict and stop encrypting our messages.
+ self.gpg = gnupg.GPG()
+ self.keyid = self.config.get('keyid', '') or None
+ self.passphrase = self.config.get('passphrase', '') or None
+ if not self.keyid:
+ self.core.information('No GPG keyid provided in the configuration', 'Warning')
+
+ self.add_event_handler('send_normal_presence', self.sign_presence)
+ self.add_event_handler('normal_presence', self.on_normal_presence)
+
+ def cleanup(self):
+ self.send_unsigned_presence()
+
+ def sign_presence(self, presence):
+ """
+ Sign every normal presence we send
+ """
+ signed_element = ET.Element('{%s}x' % (NS_SIGNED))
+ t = self.gpg.sign(presence['status'], keyid=self.keyid, passphrase=self.passphrase)
+ if not t:
+ self.core.information('Could not sign presence. Disabling GPG module', 'Info')
+ self.core.plugin_manager.unload('gpg')
+ return
+ signed_element.text = xml.sax.saxutils.escape(str(t))
+ presence.append(signed_element)
+
+ def send_unsigned_presence(self):
+ """
+ Send our current presence, to everyone, but unsigned, to indicate
+ that we cannot/do not want to encrypt/unencrypt messages.
+ """
+ current_presence = self.core.get_status()
+ self.core.command_status('%s %s' % (current_presence.show or 'available', current_presence.message,))
+ def on_normal_presence(self, presence, resource):
+ """
+ Check if it’s signed, if it is and we can verify the signature,
+ add 'valid' or 'invalid' into the dict. If it cannot be verified, just add
+ 'signed'. Otherwise, do nothing.
+ """
+ signed = presence.find('{%s}x' % (NS_SIGNED,))
+ bare = presence['from'].bare
+ full = presence['from'].full
+ if signed is None:
+ log.debug('Not signed')
+ if bare in self.contacts.keys():
+ del self.contacts[bare]
+ return
+ if self.config.has_section('keys') and bare in self.config.options('keys'):
+ verify = self.gpg.verify(signed.text)
+ if verify:
+ self.contacts[full] = 'valid'
+ else:
+ self.contacts[full] = 'invalid'
+ else:
+ self.contacts[full] = 'signed'