Replacement for xmlrpclib.SafeTransport, which does not validate
authorMark Huang <mlhuang@cs.princeton.edu>
Fri, 15 Dec 2006 18:21:39 +0000 (18:21 +0000)
committerMark Huang <mlhuang@cs.princeton.edu>
Fri, 15 Dec 2006 18:21:39 +0000 (18:21 +0000)
SSL certificates. Requires PyCurl.

PLC/PyCurl.py [new file with mode: 0644]

diff --git a/PLC/PyCurl.py b/PLC/PyCurl.py
new file mode 100644 (file)
index 0000000..8352fd0
--- /dev/null
@@ -0,0 +1,80 @@
+#
+# Replacement for xmlrpclib.SafeTransport, which does not validate
+# SSL certificates. Requires PyCurl.
+#
+# Mark Huang <mlhuang@cs.princeton.edu>
+# Copyright (C) 2006 The Trustees of Princeton University
+#
+# $Id$
+#
+
+import os
+import xmlrpclib
+import pycurl
+from tempfile import NamedTemporaryFile
+
+class PyCurlTransport(xmlrpclib.Transport):
+    def __init__(self, uri, cert = None, timeout = 300):
+        self.curl = pycurl.Curl()
+
+        # Suppress signals
+        self.curl.setopt(pycurl.NOSIGNAL, 1)
+
+        # Follow redirections
+        self.curl.setopt(pycurl.FOLLOWLOCATION, 1)
+
+        # Set URL
+        self.url = uri
+        self.curl.setopt(pycurl.URL, str(uri))
+
+        # Set certificate path
+        if cert is not None:
+            if os.path.exists(cert):
+                cert_path = str(cert)
+            else:
+                # Keep a reference so that it does not get deleted
+                self.cert = NamedTemporaryFile(prefix = "cert")
+                self.cert.write(cert)
+                self.cert.flush()
+                cert_path = self.cert.name
+            self.curl.setopt(pycurl.CAINFO, cert_path)
+            self.curl.setopt(pycurl.SSL_VERIFYPEER, 2)
+
+        # Set connection timeout
+        if timeout:
+            self.curl.setopt(pycurl.CONNECTTIMEOUT, timeout)
+            self.curl.setopt(pycurl.TIMEOUT, timeout)
+
+        # Set request callback
+        self.body = ""
+        def body(buf):
+            self.body += buf
+        self.curl.setopt(pycurl.WRITEFUNCTION, body)        
+
+    def request(self, host, handler, request_body, verbose = 1):
+        # Set verbosity
+        self.curl.setopt(pycurl.VERBOSE, verbose)
+
+        # Post request
+        self.curl.setopt(pycurl.POST, 1)
+        self.curl.setopt(pycurl.POSTFIELDS, request_body)
+
+        try:
+            self.curl.perform()
+            errcode = self.curl.getinfo(pycurl.HTTP_CODE)
+            response = self.body
+            self.body = ""
+        except pycurl.error, err:
+            (errcode, errmsg) = err
+
+        if errcode == 60:
+            raise Exception, "SSL certificate validation failed"
+        elif errcode != 200:
+            raise Exception, "HTTP error %d" % errcode
+
+        # Parse response
+        p, u = self.getparser()
+        p.feed(response)
+        p.close()
+
+        return u.close()