Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 920fa0f0e28c0a57d683a2dc3f252bab > files > 9

m2crypto-0.16-9.el5.src.rpm

diff -urN m2crypto/M2Crypto/__init__.py m2crypto-0.16/M2Crypto/__init__.py
--- m2crypto/M2Crypto/__init__.py	2006-06-12 19:36:19.000000000 +0200
+++ m2crypto-0.16/M2Crypto/__init__.py	2006-10-20 16:04:57.000000000 +0200
@@ -33,6 +33,7 @@
 import m2urllib
 # Backwards compatibility.
 urllib2 = m2urllib
+import m2urllib2
 import ftpslib
 import httpslib
 import m2xmlrpclib
diff -urN m2crypto/M2Crypto/m2urllib2.py m2crypto-0.16/M2Crypto/m2urllib2.py
--- m2crypto/M2Crypto/m2urllib2.py	1970-01-01 01:00:00.000000000 +0100
+++ m2crypto-0.16/M2Crypto/m2urllib2.py	2006-10-20 16:04:57.000000000 +0200
@@ -0,0 +1,123 @@
+"""
+M2Crypto enhancement to Python's urllib2 for handling 
+'https' url's.
+
+Code from urllib2 is Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006
+Python Software Foundation; All Rights Reserved
+
+Summary of changes:
+ * Add the SSL context to the https connection when performing https_open.
+ * Add the M2Crypto HTTPSHandler when building a default opener.
+"""
+
+from urllib2 import *
+
+import SSL
+import httpslib
+
+class HTTPSHandler(AbstractHTTPHandler):
+    def __init__(self, ssl_context = None):
+        AbstractHTTPHandler.__init__(self)
+
+        if ssl_context is not None:
+            self.ctx = ssl_context
+        else:
+            self.ctx = SSL.Context()
+
+    # Copied from urllib2, so we can set the ssl context.
+    def https_open(self, req):
+        """Return an addinfourl object for the request, using http_class.
+
+        http_class must implement the HTTPConnection API from httplib.
+        The addinfourl return value is a file-like object.  It also
+        has methods and attributes including:
+            - info(): return a mimetools.Message object for the headers
+            - geturl(): return the original request URL
+            - code: HTTP status code
+        """
+        host = req.get_host()
+        if not host:
+            raise URLError('no host given')
+
+        # Our change: add the ssl context.
+        h = httpslib.HTTPSConnection(host = host, ssl_context = self.ctx)
+        # End our change
+        h.set_debuglevel(self._debuglevel)
+
+        headers = dict(req.headers)
+        headers.update(req.unredirected_hdrs)
+        # We want to make an HTTP/1.1 request, but the addinfourl
+        # class isn't prepared to deal with a persistent connection.
+        # It will try to read all remaining data from the socket,
+        # which will block while the server waits for the next request.
+        # So make sure the connection gets closed after the (only)
+        # request.
+        headers["Connection"] = "close"
+        try:
+            h.request(req.get_method(), req.get_selector(), req.data, headers)
+            r = h.getresponse()
+        except socket.error, err: # XXX what error?
+            raise URLError(err)
+
+        # Pick apart the HTTPResponse object to get the addinfourl
+        # object initialized properly.
+
+        # Wrap the HTTPResponse object in socket's file object adapter
+        # for Windows.  That adapter calls recv(), so delegate recv()
+        # to read().  This weird wrapping allows the returned object to
+        # have readline() and readlines() methods.
+
+        # XXX It might be better to extract the read buffering code
+        # out of socket._fileobject() and into a base class.
+
+        r.recv = r.read
+        fp = socket._fileobject(r)
+
+        resp = addinfourl(fp, r.msg, req.get_full_url())
+        resp.code = r.status
+        resp.msg = r.reason
+        return resp
+
+        
+    https_request = AbstractHTTPHandler.do_request_
+
+
+# Copied from urllib2 with modifications for ssl
+def build_opener(ssl_context = None, *handlers):
+    """Create an opener object from a list of handlers.
+
+    The opener will use several default handlers, including support
+    for HTTP and FTP.
+
+    If any of the handlers passed as arguments are subclasses of the
+    default handlers, the default handlers will not be used.
+    """
+
+    opener = OpenerDirector()
+    default_classes = [ProxyHandler, UnknownHandler, HTTPHandler,
+                       HTTPDefaultErrorHandler, HTTPRedirectHandler,
+                       FTPHandler, FileHandler, HTTPErrorProcessor]
+    skip = []
+    for klass in default_classes:
+        for check in handlers:
+            if inspect.isclass(check):
+                if issubclass(check, klass):
+                    skip.append(klass)
+            elif isinstance(check, klass):
+                skip.append(klass)
+    for klass in skip:
+        default_classes.remove(klass)
+
+    for klass in default_classes:
+        opener.add_handler(klass())
+
+    # Add the HTTPS handler with ssl_context
+    if HTTPSHandler not in skip:
+        opener.add_handler(HTTPSHandler(ssl_context))
+
+
+    for h in handlers:
+        if inspect.isclass(h):
+            h = h()
+        opener.add_handler(h)
+    return opener
diff -urN m2crypto/tests/test_ssl.py m2crypto-0.16/tests/test_ssl.py
--- m2crypto/tests/test_ssl.py	2006-05-25 00:54:03.000000000 +0200
+++ m2crypto-0.16/tests/test_ssl.py	2006-10-20 16:04:57.000000000 +0200
@@ -556,6 +556,54 @@
             self.stop_server(pid)
         self.failIf(string.find(data, 's_server -quiet -www') == -1)
 
+    # XXX Don't actually know how to use m2urllib safely!
+    #def test_urllib_safe_context(self):
+    #def test_urllib_safe_context_fail(self):
+
+    def test_urllib2(self):
+        pid = self.start_server(self.args)
+        try:
+            from M2Crypto import m2urllib2
+            opener = m2urllib2.build_opener()
+            opener.addheaders = [('Connection', 'close')]
+            u = opener.open('https://%s:%s/' % (srv_host, srv_port))
+            data = u.read()
+            u.close()
+        finally:
+            self.stop_server(pid)
+        self.failIf(string.find(data, 's_server -quiet -www') == -1)
+
+    def test_urllib2_secure_context(self):
+        pid = self.start_server(self.args)
+        try:
+            ctx = SSL.Context()
+            ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9)
+            ctx.load_verify_locations('ca.pem')
+            
+            from M2Crypto import m2urllib2
+            opener = m2urllib2.build_opener(ctx)
+            opener.addheaders = [('Connection', 'close')]           
+            u = opener.open('https://%s:%s/' % (srv_host, srv_port))
+            data = u.read()
+            u.close()
+        finally:
+            self.stop_server(pid)
+        self.failIf(string.find(data, 's_server -quiet -www') == -1)
+
+    def test_urllib2_secure_context_fail(self):
+        pid = self.start_server(self.args)
+        try:
+            ctx = SSL.Context()
+            ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9)
+            ctx.load_verify_locations('server.pem')
+            
+            from M2Crypto import m2urllib2
+            opener = m2urllib2.build_opener(ctx)
+            opener.addheaders = [('Connection', 'close')]
+            self.assertRaises(SSL.SSLError, opener.open, 'https://%s:%s/' % (srv_host, srv_port))
+        finally:
+            self.stop_server(pid)
+
     def test_blocking0(self):
         pid = self.start_server(self.args)
         try:
@@ -597,6 +645,8 @@
             from twisted.internet import reactor
             import M2Crypto.SSL.TwistedProtocolWrapper as wrapper
         except ImportError:
+            import warnings
+            warnings.warn('Skipping twisted wrapper test because twisted not found')
             return
         
         class EchoClient(LineReceiver):