extras-buildsys/common SSLConnection.py, NONE, 1.1 AuthedXMLRPCServer.py, 1.1, 1.2 FileDownloader.py, 1.10, 1.11 HTTPSURLopener.py, 1.3, 1.4 HTTPServer.py, 1.1, 1.2 Makefile, 1.4, 1.5 SSLCommon.py, 1.8, 1.9 XMLRPCServerProxy.py, 1.1, 1.2

Daniel Williams (dcbw) fedora-extras-commits at redhat.com
Wed Jul 6 21:20:57 UTC 2005


Author: dcbw

Update of /cvs/fedora/extras-buildsys/common
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv3996/common

Modified Files:
	AuthedXMLRPCServer.py FileDownloader.py HTTPSURLopener.py 
	HTTPServer.py Makefile SSLCommon.py XMLRPCServerProxy.py 
Added Files:
	SSLConnection.py 
Log Message:
2005-07-06  Dan Williams <dcbw at redhat.com>

    * Convert M2Crypto code to pyOpenSSL so that stuff actually works




***** Error reading new file: [Errno 2] No such file or directory: 'SSLConnection.py'

Index: AuthedXMLRPCServer.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/AuthedXMLRPCServer.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AuthedXMLRPCServer.py	5 Jul 2005 21:07:57 -0000	1.1
+++ AuthedXMLRPCServer.py	6 Jul 2005 21:20:55 -0000	1.2
@@ -19,13 +19,18 @@
 import socket
 import time
 import SocketServer
-from M2Crypto import SSL
 import xmlrpclib
 import SimpleXMLRPCServer
 import SSLCommon
 
 
 class AuthedSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
+
+    # For some reason, httplib closes the connection right after headers
+    # have been sent if the connection is _not_ HTTP/1.1, which results in
+    # a "Bad file descriptor" error when the client tries to read from the socket
+    protocol_version = "HTTP/1.1"
+
     def do_POST(self):
         """
         See documentation on SimpleXMLRPCRequestHandler.  Modifications
@@ -88,16 +93,6 @@
         return None
 
     def verify_request(self, request, client_address):
-        """
-        Allow ourselves a chance to verify the client
-        """
-        if self.authinfo_callback:
-            authinfo = self.get_authinfo(request, client_address)
-            if authinfo:
-                return True
-            return False
-
-        # Allow all requests if there's no authinfo_callback
         return True
 
     def _marshaled_dispatch(self, data, authinfo):
@@ -150,7 +145,6 @@
         else:
             raise Exception('method "%s" is not supported' % method)
 
-    # Sigh.  Different versions of M2Crypto have this in different places
     def lcl_resolve_dotted_attribute(self, method):
         pyver = sys.version_info[:3]
         if pyver <= (2, 3, 4):
@@ -160,34 +154,44 @@
             return SimpleXMLRPCServer.resolve_dotted_attribute(
                 self.instance, method, self.allow_dotted_names)
 
-    def serve_forever(self):
-        while True:
-            try:
-                self.handle_request()
-            except KeyboardInterrupt, e:
-                print "Shutting down..."
-                break
-            except socket.error, e:
-                if e[0] == 11:      #Resource temporarily unavailable
-                    try:
-                        time.sleep(0.1)
-                    except KeyboardInterrupt, e:
-                        print "Shutting down..."
-                        break
-
 
-class AuthedSSLXMLRPCServer(BaseAuthedXMLRPCServer, SSLCommon.QuietSSLServer, SimpleXMLRPCServer.SimpleXMLRPCServer):
+class AuthedSSLXMLRPCServer(BaseAuthedXMLRPCServer, SSLCommon.PlgBaseSSLServer, SimpleXMLRPCServer.SimpleXMLRPCServer):
     """ Extension to allow more fine-tuned SSL handling """
 
     def __init__(self, address, authinfo_callback=None, certs=None):
         BaseAuthedXMLRPCServer.__init__(self, address, authinfo_callback)
-        ctx = SSLCommon.getSSLContext(certs)
-        SSLCommon.QuietSSLServer.__init__(self, address, AuthedSimpleXMLRPCRequestHandler, ctx)
+        SSLCommon.PlgBaseSSLServer.__init__(self, address, AuthedSimpleXMLRPCRequestHandler, certs)
 
 
-class AuthedXMLRPCServer(BaseAuthedXMLRPCServer, SocketServer.ThreadingTCPServer, SimpleXMLRPCServer.SimpleXMLRPCServer):
+class AuthedXMLRPCServer(BaseAuthedXMLRPCServer, SSLCommon.PlgBaseServer, SimpleXMLRPCServer.SimpleXMLRPCServer):
 
     def __init__(self, address, authinfo_callback=None):
         BaseAuthedXMLRPCServer.__init__(self, address, authinfo_callback)
-        SocketServer.ThreadingTCPServer.__init__(self, address, AuthedSimpleXMLRPCRequestHandler)
+        SSLCommon.PlgBaseServer.__init__(self, address, AuthedSimpleXMLRPCRequestHandler)
+
+
+###########################################################
+# Testing stuff
+###########################################################
+
+class ReqHandler:
+    def ping(self):
+        return "pong"
+
+
+if __name__ == '__main__':
+    if len(sys.argv) < 4:
+        print "Usage: python AuthdXMLRPCServer.py key_and_cert ca_cert peer_ca_cert"
+        sys.exit(1)
+
+    certs = {}
+    certs['key_and_cert'] = sys.argv[1]
+    certs['ca_cert'] = sys.argv[2]
+    certs['peer_ca_cert'] = sys.argv[3]
+
+    print "Starting the server."
+    server = AuthedSSLXMLRPCServer(('localhost', 8886), None, certs)
+    h = ReqHandler()
+    server.register_instance(h)
+    server.serve_forever()
 


Index: FileDownloader.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/FileDownloader.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- FileDownloader.py	5 Jul 2005 21:07:57 -0000	1.10
+++ FileDownloader.py	6 Jul 2005 21:20:55 -0000	1.11
@@ -1,4 +1,3 @@
-#!/usr/bin/python -t
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
@@ -13,8 +12,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #
-# Copyright 2005 Dan Williams and Red Hat, Inc.
-#
+# Copyright 2005 Dan Williams <dcbw at redhat.com> and Red Hat, Inc.
 
 import threading
 import urllib
@@ -22,7 +20,7 @@
 import os
 import socket
 import HTTPSURLopener
-from M2Crypto import SSL
+import OpenSSL
 import CommonErrors
 
 
@@ -98,10 +96,10 @@
             target_file = os.path.join(self._target_dir, self._filename)
             try:
                 result = self._opener.retrieve(self._url, target_file)
-            except SSL.SSLError, e:
-                # Don't traceback on dropped connections or timeouts
-                if CommonErrors.canIgnoreSSLError(e):
-                    pass
+#            except SSL.SSLError, e:
+#                # Don't traceback on dropped connections or timeouts
+#                if CommonErrors.canIgnoreSSLError(e):
+#                    pass
             except socket.error, e:
                 if CommonErrors.canIgnoreSocketError(e):
                     pass
@@ -121,7 +119,6 @@
 ###########################################################
 
 import sys, time
-from M2Crypto import threading as m2thread
 
 class dlwr:
     def __init__(self, x, t):
@@ -165,7 +162,6 @@
     print "Starting..."
     dlt = dl_tracker()
 
-    m2thread.init()
     x = 0
     while x < 100:
         wr = dlwr(x, dlt)
@@ -183,5 +179,4 @@
             time.sleep(1)
         except KeyboardInterrupt:
             print "Quitting..."
-            m2thread.cleanup()
             os._exit(0)


Index: HTTPSURLopener.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/HTTPSURLopener.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- HTTPSURLopener.py	14 Jun 2005 01:16:30 -0000	1.3
+++ HTTPSURLopener.py	6 Jul 2005 21:20:55 -0000	1.4
@@ -15,43 +15,50 @@
 # Copyright 2005 Dan Williams <dcbw at redhat.com> and Red Hat, Inc.
 
 
-import string, sys, urllib
-import os, sys
-from urllib import *
-
-from M2Crypto import SSL, httpslib
+import string
+import urllib
+import os
+import sys
 import SSLCommon
+from OpenSSL import SSL
+
 
 class HTTPSURLopener(urllib.URLopener):
     def __init__(self, certs):
-        self.ctx = SSLCommon.getSSLContext(certs)
+        self.ctx = SSLCommon.CreateSSLContext(certs)
         urllib.URLopener.__init__(self)
 
     def open_https(self, url, data=None):
         """
-        Inspired by M2Crypto.m2urllib. The problem here with
-        M2Crypto.m2urlllib is that there wasn't a way to get an SSL context
-        into open_https as far as I could tell.
-
+        Need to override this because there was no visible
+        way to get the SSL Context into open_https()
         """
-
         # Attempt to isolate host and request parts from URI
         host = None
         if type(url) is type(""):
-            host, selector = splithost(url)
+            host, selector = urllib.splithost(url)
             if host:
-                user_passwd, host = splituser(host)
-                host = unquote(host)
+                user_passwd, host = urllib.splituser(host)
+                host = urllib.unquote(host)
         if not host:
             raise IOError, ('http error', 'no host given')
 
-        h = httpslib.HTTPSConnection(host=host, ssl_context=self.ctx)
+        h = SSLCommon.PlgHTTPS(host=host, ssl_context=self.ctx)
 
         h.putrequest('GET', selector)
         for args in self.addheaders:
             apply(h.putheader, args)
-        h.endheaders()
 
-        resp = h.getresponse()
-        fp = resp.fp
-        return urllib.addinfourl(fp, {}, "https:" + url)
+        try:
+            h.endheaders()
+        except SSL.Error, e:
+            # Convert the SSL error into an IOError so the call fails
+            raise IOError, e
+
+        errcode, errmsg, headers = h.getreply()
+        fp = h.getfile()
+        if errcode == 200:
+            return urllib.addinfourl(fp, headers, "https:" + url)
+        else:
+            return self.http_error(url, fp, errcode, errmsg, headers)
+


Index: HTTPServer.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/HTTPServer.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- HTTPServer.py	5 Jul 2005 21:07:57 -0000	1.1
+++ HTTPServer.py	6 Jul 2005 21:20:55 -0000	1.2
@@ -17,21 +17,22 @@
 #
 
 import SimpleHTTPServer
-import SocketServer
 import threading
 import urllib
 import posixpath
-import os, sys
-from SimpleHTTPServer import SimpleHTTPRequestHandler
-from M2Crypto import Rand, SSL
-from M2Crypto.SSL.SSLServer import ThreadingSSLServer
+import os
+import sys
 import SSLCommon
-import socket
 import time
-from M2Crypto import threading as m2thread
+from OpenSSL import SSL
 
 
-class HttpRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+class PlgHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+
+    # For some reason, httplib closes the connection right after headers
+    # have been sent if the connection is _not_ HTTP/1.1, which results in
+    # a "Bad file descriptor" error when the client tries to read from the socket
+    protocol_version = "HTTP/1.1"
 
     def __init__(self, request, client_address, server):
         self._server = server
@@ -66,84 +67,33 @@
             path = os.path.join(path, word)
         return path
 
-    def do_GET(self):
-        SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
-#        try:
-#            SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
-#        except Exception, e:
-#            # We get an exception if the client drops the transfer
-#            pass
-
-class ThreadingHTTPSServer(ThreadingSSLServer):
-    """ SSL-enabled variant """
-
-    def __init__(self, server_addr, http_dir, certs):
-        self.allow_reuse_address = 1
-        self.http_dir = http_dir
-
-        self.ctx = SSLCommon.getSSLContext(certs)
-        ThreadingSSLServer.__init__(self, server_addr, HttpRequestHandler, self.ctx)
+    def handle(self):
+        """ Always close the connection when done """
+        self.close_connection = 1
 
-        self.server_name = server_addr[0]
-        self.server_port = server_addr[1]
-
-        # About the last thing we want is a client blocking the server
-        # because it hung or tracebacked
-        timeout = SSL.timeout(10)
-        self.socket.set_socket_read_timeout(timeout)
-        self.socket.set_socket_write_timeout(timeout)
-
-    def finish(self):
-        if self.request:
-            self.request.set_shutdown(SSL.SSL_RECEIVED_SHUTDOWN | SSL.SSL_SENT_SHUTDOWN)
-            self.request.close()
-
-    def serve_forever(self):
-        while True:
-            try:
-                self.handle_request()
-            except KeyboardInterrupt, e:
-                print "Shutting down..."
-                break
-            except socket.error, e:
-                if e[0] == 11:      # Resource temporarily unavailable
-                    try:
-                        time.sleep(0.1)
-                    except KeyboardInterrupt, e:
-                        print "Shutting down..."
-                        break
+        try:
+            self.handle_one_request()
+        except SSL.Error, e:
+            print e[0]
 
-class ThreadingHTTPServer(SocketServer.ThreadingTCPServer):
-    """ Non-SSL variant """
 
-    def __init__(self, certs, server_addr, http_dir):
-        self.allow_reuse_address = 1
+class PlgHTTPSServer(SSLCommon.PlgBaseSSLServer):
+    def __init__(self, server_address, http_dir, certs):
         self.http_dir = http_dir
+        SSLCommon.PlgBaseSSLServer.__init__(self, server_address, PlgHTTPRequestHandler, certs)
 
-        ThreadingTCPServer.__init__(self, server_addr, HttpRequestHandler)
-
-    def serve_forever(self):
-        while True:
-            try:
-                self.handle_request()
-            except KeyboardInterrupt, e:
-                print "Shutting down..."
-                break
-            except socket.error, e:
-                if e[0] == 11:      # Resource temporarily unavailable
-                    try:
-                        time.sleep(0.1)
-                    except KeyboardInterrupt, e:
-                        print "Shutting down..."
-                        break
+class PlgHTTPServer(SSLCommon.PlgBaseServer):
+    def __init__(self, server_address, http_dir):
+        self.http_dir = http_dir
+        SSLCommon.PlgBaseServer.__init__(self, server_address, PlgHTTPRequestHandler)
 
 
-class HTTPServer(threading.Thread):
+class PlgHTTPServer(threading.Thread):
     def __init__(self, addr, http_dir, certs):
         if certs and len(certs) > 0:
-            self._server = ThreadingHTTPSServer(addr, http_dir, certs)
+            self._server = PlgHTTPSServer(addr, http_dir, certs)
         else:
-            self._server = ThreadingHTTPServer(addr, http_dir)
+            self._server = PlgHTTPServer(addr, http_dir)
         self._stop = False
         threading.Thread.__init__(self)
 
@@ -161,7 +111,7 @@
 
 if __name__ == '__main__':
     if len(sys.argv) < 4:
-        print "Usage: python SimpleHTTPSServer.py key_and_cert ca_cert peer_ca_cert"
+        print "Usage: python HTTPServer.py key_and_cert ca_cert peer_ca_cert"
         sys.exit(1)
 
     certs = {}
@@ -183,10 +133,8 @@
         x = x + 1
     f.close()
 
-    m2thread.init()
-
     print "Starting the server."
-    server = SimpleHTTPSServer(certs, ('localhost', 8886), srcdir)
+    server = PlgHTTPServer(('localhost', 8886), srcdir, certs)
     server.start()
 
     while True:
@@ -194,5 +142,4 @@
             time.sleep(1)
         except KeyboardInterrupt:
             print "Quitting..."
-            m2thread.cleanup()
             os._exit(0)


Index: Makefile
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/Makefile,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Makefile	5 Jul 2005 21:07:57 -0000	1.4
+++ Makefile	6 Jul 2005 21:20:55 -0000	1.5
@@ -14,6 +14,7 @@
 	HTTPServer.py \
 	AuthedXMLRPCServer.py \
 	SSLCommon.py \
+    SSLConnection.py \
 	XMLRPCServerProxy.py \
 	lighttpdManager.py \
 	__init__.py


Index: SSLCommon.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/SSLCommon.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- SSLCommon.py	5 Jul 2005 21:07:57 -0000	1.8
+++ SSLCommon.py	6 Jul 2005 21:20:55 -0000	1.9
@@ -14,21 +14,23 @@
 #
 # Copyright 2005 Dan Williams <dcbw at redhat.com> and Red Hat, Inc.
 
-from M2Crypto import SSL
 import os
 import CommonErrors
+from OpenSSL import SSL
+import SSLConnection
+import httplib
+import socket
+import SocketServer
 
+def our_verify(connection, x509, errNum, errDepth, preverifyOK):
+    # print "Verify: errNum = %s, errDepth = %s, preverifyOK = %s" % (errNum, errDepth, preverifyOK)
 
-def quietCallback(self, *args):
-    """
-    This prevents SSL printing out stuff to stderr/stdout.
-    """
-    return
+    # preverifyOK should tell us whether or not the client's certificate
+    # correctly authenticates against the CA chain
+    return preverifyOK
 
-def getSSLContext(certs, session_id='ssl_session'):
-    """
-    Helper method for m2crypto's SSL libraries.
-    """
+
+def CreateSSLContext(certs):
     key_and_cert = certs['key_and_cert']
     ca_cert = certs['ca_cert']
     peer_ca_cert = certs['peer_ca_cert']
@@ -37,53 +39,101 @@
             print "%s does not exist or is not readable." % f
             os._exit(1)
 
-    ctx = SSL.Context('sslv3')   # SSLv3 only
-    ctx.load_cert(key_and_cert)
+    ctx = SSL.Context(SSL.SSLv3_METHOD)   # SSLv3 only
+    ctx.use_certificate_file(key_and_cert)
+    ctx.use_privatekey_file(key_and_cert)
     ctx.load_client_ca(ca_cert)
-    ctx.load_verify_info(peer_ca_cert)
-    ctx.set_allow_unknown_ca(False)
-    verify = SSL.verify_peer | SSL.verify_fail_if_no_peer_cert
-    ctx.set_verify(verify, 10)
-    ctx.set_session_id_ctx(session_id)
-    ctx.set_info_callback(quietCallback)
+    ctx.load_verify_locations(peer_ca_cert)
+    verify = SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT
+    ctx.set_verify(verify, our_verify)
+    ctx.set_verify_depth(10)
+    ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_TLSv1)
     return ctx
-    
 
-class QuietSSLServer(SSL.ThreadingSSLServer):
-    def __init__(self, server_address, RequestHandlerClass, ssl_context):
-        try:
-            SSL.SSLServer.__init__(self, server_address, RequestHandlerClass, ssl_context)
-        except socket.error, e:
-            if e[0] == 49:      # Cannot assign requested address
-                print "Error: requested address '%s' couldn't be used." % server_address
-
-        # About the last thing we want is a client blocking the server
-        # because it hung or tracebacked
-        timeout = SSL.timeout(10)
-        self.socket.set_socket_read_timeout(timeout)
-        self.socket.set_socket_write_timeout(timeout)
-
-    def handle_request(self):
-        request = None
-        client_address = None
-        try:
-            request, client_address = self.get_request()
-            timeout = SSL.timeout(10)
-            request.set_socket_read_timeout(timeout)
-            request.set_socket_write_timeout(timeout)
-            if self.verify_request(request, client_address):
-                self.process_request(request, client_address)
-        except SSL.SSLError, e:
-            if CommonErrors.canIgnoreSSLError(e):
-                pass
-            else:
-                self.handle_error(request, client_address)
-
-    # Override M2Crypto's SSL.SSLServer handle_error, which 
-    # doesn't accept the same arguments as SocketServer
-    def handle_error(self, request, client_address):
-        print '-'*40
-        import traceback
-        traceback.print_exc()
-        print '-'*40
+
+
+class PlgBaseServer(SocketServer.ThreadingTCPServer):
+    allow_reuse_address = 1
+
+    def __init__(self, server_addr, req_handler):
+        self.allow_reuse_address = 1
+        SocketServer.ThreadingTCPServer.__init__(self, server_addr, req_handler)
+
+    def serve_forever(self):
+        while True:
+            try:
+                self.handle_request()
+            except KeyboardInterrupt, e:
+                print "Shutting down..."
+                break
+
+
+class PlgBaseSSLServer(PlgBaseServer):
+    """ SSL-enabled variant """
+
+    def __init__(self, server_address, req_handler, certs):
+        
+        self.ssl_ctx = CreateSSLContext(certs)
+
+        SocketServer.BaseServer.__init__(self, server_address, req_handler)
+
+        sock = socket.socket(self.address_family, self.socket_type)
+        con = SSL.Connection(self.ssl_ctx, sock)
+        self.socket = SSLConnection.SSLConnection(con)
+        self.server_bind()
+        self.server_activate()
+
+        host, port = self.socket.getsockname()[:2]
+        self.server_name = socket.getfqdn(host)
+        self.server_port = port
+
+
+class PlgHTTPSResponse(httplib.HTTPResponse):
+    def __init__(self, sock, debuglevel=0, strict=0, method=None):
+        self.fp = socket._fileobject(sock, "rb", 0)
+        self.debuglevel = debuglevel
+        self.strict = strict
+        self._method = method
+
+        self.msg = None
+
+        # from the Status-Line of the response
+        self.version = httplib._UNKNOWN # HTTP-Version
+        self.status = httplib._UNKNOWN  # Status-Code
+        self.reason = httplib._UNKNOWN  # Reason-Phrase
+
+        self.chunked = httplib._UNKNOWN         # is "chunked" being used?
+        self.chunk_left = httplib._UNKNOWN      # bytes left to read in current chunk
+        self.length = httplib._UNKNOWN          # number of bytes left in response
+        self.will_close = httplib._UNKNOWN      # conn will close at end of response
+
+
+class PlgHTTPSConnection(httplib.HTTPConnection):
+    "This class allows communication via SSL."
+
+    response_class = PlgHTTPSResponse
+
+    def __init__(self, host, port=None, ssl_context=None, strict=None):
+        httplib.HTTPConnection.__init__(self, host, port, strict)
+        self.ssl_ctx = ssl_context
+
+    def connect(self):
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        con = SSL.Connection(self.ssl_ctx, sock)
+        self.sock = SSLConnection.SSLConnection(con)
+        self.sock.connect((self.host, self.port))
+
+
+class PlgHTTPS(httplib.HTTP):
+    """Compatibility with 1.5 httplib interface
+
+    Python 1.5.2 did not have an HTTPS class, but it defined an
+    interface for sending http requests that is also useful for
+    https.
+    """
+
+    _connection_class = PlgHTTPSConnection
+
+    def __init__(self, host='', port=None, ssl_context=None, strict=None):
+        self._setup(self._connection_class(host, port, ssl_context, strict))
 


Index: XMLRPCServerProxy.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/XMLRPCServerProxy.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XMLRPCServerProxy.py	5 Jul 2005 21:07:58 -0000	1.1
+++ XMLRPCServerProxy.py	6 Jul 2005 21:20:55 -0000	1.2
@@ -15,14 +15,84 @@
 # Modified by Dan Williams <dcbw at redhat.com>
 
 import os, sys
-from M2Crypto import SSL
-from M2Crypto.m2xmlrpclib import SSL_Transport, ServerProxy
 import SSLCommon
+import urllib
+import xmlrpclib
 
-class XMLRPCServerProxy(ServerProxy):
+__version__='0.12'
+
+class SSL_Transport(xmlrpclib.Transport):
+
+    user_agent = "pyOpenSSL_XMLRPC/%s - %s" % (__version__, xmlrpclib.Transport.user_agent)
+
+    def __init__(self, ssl_context):
+        self.ssl_ctx=ssl_context
+
+    def request(self, host, handler, request_body, verbose=0):
+        # Handle username and password.
+        user_passwd, host_port = urllib.splituser(host)
+        _host, _port = urllib.splitport(host_port)
+        h = SSLCommon.PlgHTTPS(_host, int(_port), ssl_context=self.ssl_ctx)
+        if verbose:
+            h.set_debuglevel(1)
+
+        # What follows is as in xmlrpclib.Transport. (Except the authz bit.)
+        h.putrequest("POST", handler)
+
+        # required by HTTP/1.1
+        h.putheader("Host", _host)
+
+        # required by XML-RPC
+        h.putheader("User-Agent", self.user_agent)
+        h.putheader("Content-Type", "text/xml")
+        h.putheader("Content-Length", str(len(request_body)))
+
+        # Authorisation.
+        if user_passwd is not None:
+            auth=string.strip(base64.encodestring(user_passwd))
+            h.putheader('Authorization', 'Basic %s' % auth)
+
+        h.endheaders()
+
+        if request_body:
+            h.send(request_body)
+
+        errcode, errmsg, headers = h.getreply()
+
+        if errcode != 200:
+            raise ProtocolError(
+                host + handler,
+                errcode, errmsg,
+                headers
+                )
+
+        self.verbose = verbose
+        return self.parse_response(h.getfile())
+
+
+class XMLRPCServerProxy(xmlrpclib.ServerProxy):
     def __init__(self, uri, certs):
         if certs and len(certs) > 0:
-            self.ctx = SSLCommon.getSSLContext(certs)
-            ServerProxy.__init__(self, uri, SSL_Transport(ssl_context=self.ctx))
+            self.ctx = SSLCommon.CreateSSLContext(certs)
+            xmlrpclib.ServerProxy.__init__(self, uri, SSL_Transport(ssl_context=self.ctx))
         else:
-            ServerProxy.__init__(self, uri)
+            xmlrpclib.ServerProxy.__init__(self, uri)
+
+
+
+###########################################################
+# Testing stuff
+###########################################################
+
+if __name__ == '__main__':
+    if len(sys.argv) < 4:
+        print "Usage: python XMLRPCServerProxy.py key_and_cert ca_cert peer_ca_cert"
+        sys.exit(1)
+
+    certs = {}
+    certs['key_and_cert'] = sys.argv[1]
+    certs['ca_cert'] = sys.argv[2]
+    certs['peer_ca_cert'] = sys.argv[3]
+
+    s = XMLRPCServerProxy("https://127.0.0.1:8886", certs)
+    print s.ping()




More information about the fedora-extras-commits mailing list