reguire gnupg1 on f>=31; sense the system to use gpg1 when installed
[nodemanager.git] / ticket.py
index 3389027..a52be17 100644 (file)
--- a/ticket.py
+++ b/ticket.py
@@ -1,55 +1,43 @@
-import SocketServer
-import os
-import subprocess
-
-from config import KEY_FILE, TICKET_SERVER_PORT
-import tools
-
-
-class TicketServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
-    allow_reuse_address = True
-
-
-class TicketRequestHandler(SocketServer.StreamRequestHandler):
-    def handle(self):
-        data = self.rfile.read()
-        filename = tools.write_temp_file(lambda thefile:
-                                         thefile.write(TEMPLATE % data))
-        result = subprocess.Popen([XMLSEC1, '--sign',
-                                   '--privkey-pem', KEY_FILE, filename],
-                                  stdout=subprocess.PIPE).stdout
-        self.wfile.write(result.read())
-        result.close()
-#         os.unlink(filename)
-
-
-def start():
-    tools.as_daemon_thread(TicketServer(('', TICKET_SERVER_PORT),
-                                        TicketRequestHandler).serve_forever)
-
-
-XMLSEC1 = '/usr/bin/xmlsec1'
-
-TEMPLATE = '''<?xml version="1.0" encoding="UTF-8"?>
-<Envelope xmlns="urn:envelope">
-  <Data>%s</Data>
-  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
-    <SignedInfo>
-      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
-      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
-      <Reference URI="">
-        <Transforms>
-          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
-        </Transforms>
-        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
-        <DigestValue></DigestValue>
-      </Reference>
-    </SignedInfo>
-    <SignatureValue/>
-    <KeyInfo>
-       <KeyName/>
-    </KeyInfo>
-  </Signature>
-</Envelope>
-'''
-
+"""An extremely simple interface to the signing/verifying capabilities
+of gnupg.
+
+You must already have the key in the keyring.
+"""
+
+from subprocess import PIPE, Popen
+from xmlrpc.client import dumps, loads
+
+# see also myplc/plc.d/gpg
+import os.path
+GPG = '/usr/bin/gpg1' if os.path.exists("/usr/bin/gpg1") else "/usr/bin/gpg"
+
+def _popen_gpg(*args):
+    """Return a Popen object to GPG."""
+    return Popen((GPG, '--batch', '--no-tty') + args,
+                 stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+
+def sign(data):
+    """Return <data> signed with the default GPG key."""
+    msg = dumps((data,), methodresponse = True)
+    p = _popen_gpg('--armor', '--sign', '--keyring', '/etc/planetlab/secring.gpg', '--no-default-keyring')
+    p.stdin.write(msg)
+    p.stdin.close()
+    signed_msg = p.stdout.read()
+    p.stdout.close()
+    p.stderr.close()
+    p.wait()
+    return signed_msg
+
+def verify(signed_msg):
+    """If <signed_msg> is a valid signed document, return its contents.  Otherwise, return None."""
+    p = _popen_gpg('--decrypt', '--keyring', '/usr/boot/pubring.gpg', '--no-default-keyring')
+    p.stdin.write(signed_msg)
+    p.stdin.close()
+    msg = p.stdout.read()
+    p.stdout.close()
+    p.stderr.close()
+    if p.wait():
+        return None  # verification failed
+    else:
+        data, = loads(msg)[0]
+        return data