commit 9091a9220e05e9c2006a08b247466084150c8df4 Author: Isis Lovecruft isis@torproject.org Date: Tue Mar 4 04:58:56 2014 +0000
Add unittests for bridgedb.crypto.SSLVerifyingContextFactory. --- lib/bridgedb/test/test_crypto.py | 104 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+)
diff --git a/lib/bridgedb/test/test_crypto.py b/lib/bridgedb/test/test_crypto.py index cc1ee9a..5d69a55 100644 --- a/lib/bridgedb/test/test_crypto.py +++ b/lib/bridgedb/test/test_crypto.py @@ -14,16 +14,38 @@ from __future__ import print_function from __future__ import unicode_literals
+import logging import os
+import OpenSSL + +from twisted.internet import defer from twisted.trial import unittest +from twisted.test.proto_helpers import StringTransport +from twisted.web.test import test_agent as txtagent + from bridgedb import crypto +from bridgedb import txrecaptcha
+logging.disable(50) + SEKRIT_KEY = b'v\x16Xm\xfc\x1b}\x063\x85\xaa\xa5\xf9\xad\x18\xb2P\x93\xc6k\xf9' SEKRIT_KEY += b'\x8bI\xd9\xb8xw\xf5\xec\x1b\x7f\xa8'
+class DummyEndpoint(object): + """An endpoint that uses a fake transport.""" + + def connect(self, factory): + """Returns a connection to a + :api:`twisted.test.proto_helpers.StringTransport`. + """ + protocol = factory.buildProtocol(None) + protocol.makeConnection(StringTransport()) + return defer.succeed(protocol) + + class GetKeyTests(unittest.TestCase): """Tests for :func:`bridgedb.crypto.getKey`."""
@@ -56,3 +78,85 @@ class GetKeyTests(unittest.TestCase): key (in hex): %s SEKRIT_KEY (in hex): %s""" % (key.encode('hex'), SEKRIT_KEY.encode('hex'))) + + +class SSLVerifyingContextFactoryTests(unittest.TestCase, + txtagent.FakeReactorAndConnectMixin): + """Tests for :class:`bridgedb.crypto.SSLVerifyingContextFactory`.""" + + _certificateText = ( + "-----BEGIN CERTIFICATE-----\n" + "MIIEdjCCA16gAwIBAgIITcyHZlE/AhQwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE\n" + "BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl\n" + "cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMjEyMTUxMTE2WhcNMTQwNjEyMDAwMDAw\n" + "WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN\n" + "TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3\n" + "Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt3TOf\n" + "VOf4vfy4IROcEyiFzAJA+B3xkMccwA4anaD6VyGSFglRn5Oht3t+G0Mnu/LMuGba\n" + "EE6NEBEUEbH8KMlAcVRj58LoFIzulaRCdkVX7JK9R+kU05sggvIl1Q2quaWSjiMQ\n" + "SpyvKz1I2cmU5Gm4MfW/66M5ZJO323VrV19ydrgAtdbNnvVj85asrSyzwEBNxzNC\n" + "N6OQtOmTt4I7KLXqkROtTmTFvhAGBsvhG0hJZWhoP1aVsFO+KcE2OaIIxWQ4ckW7\n" + "BJEgYaXfgHo01LdR55aevGUqLfsdyT+GMZrG9k7eqAw4cq3ML2Y6RiyzskqoQL30\n" + "3OdYjKTIcU+i3BoFAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI\n" + "KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE\n" + "XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0\n" + "MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G\n" + "A1UdDgQWBBQN7uQBzGDjvKRna111g9iPPtaXVTAMBgNVHRMBAf8EAjAAMB8GA1Ud\n" + "IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW\n" + "eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB\n" + "RzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBrVp/xys2ABQvWPxpVrYaXiaoBXdxu\n" + "RVVXp5Lyu8IipKqFJli81hOX9eqPG7biYeph9HiKnW31xsXebaVlWWL3NXOh5X83\n" + "wpzozL0AkxskTMHQknrbIGLtmG67H71aKYyCthHEjawLmYjjvkcF6f9fKdYENM4C\n" + "skz/yjtlPBQFAuT6J9w0b3qtc42sHNlpgIOdIRQc2YCD0p6jAo+wKjoRuRu3ILKj\n" + "oCVrOPbDMPN4a2gSmK8Ur0aHuEpcNghg6HJsVSANokIIwQ/r4niqL5yotsangP/5\n" + "rR97EIYKFz7C6LMy/PIe8xFTIyKMtM59IcpUDIwCLlM9JtNdwN4VpyKy\n" + "-----END CERTIFICATE-----\n") + + def setUp(self): + """Create a fake reactor for these tests.""" + self.reactor = self.Reactor() + self.url = 'https://www.example.com/someresource.html#andatag' + + def test_getHostnameFromURL(self): + """``getHostnameFromURL()`` should return a hostname from a URI.""" + agent = txrecaptcha._getAgent(self.reactor, self.url) + contextFactory = agent._contextFactory + self.assertRegexpMatches(contextFactory.hostname, + '.*www.example.com') + + def test_verifyHostname_mismatching(self): + """Check that ``verifyHostname()`` returns ``False`` when the + ``SSLVerifyingContextFactory.hostname`` does not match the one found + in the level 0 certificate subject CN. + """ + agent = txrecaptcha._getAgent(self.reactor, self.url) + contextFactory = agent._contextFactory + x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + self._certificateText) + conn = DummyEndpoint() + result = contextFactory.verifyHostname(conn, x509, 0, 0, True) + self.assertIs(result, False) + + def test_verifyHostname_matching(self): + """Check that ``verifyHostname()`` returns ``True`` when the + ``SSLVerifyingContextFactory.hostname`` matches the one found in the + level 0 certificate subject CN. + """ + hostname = 'www.google.com' + url = 'https://' + hostname + '/recaptcha' + contextFactory = crypto.SSLVerifyingContextFactory(url) + self.assertEqual(contextFactory.hostname, hostname) + + x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + self._certificateText) + conn = DummyEndpoint() + result = contextFactory.verifyHostname(conn, x509, 0, 0, True) + self.assertTrue(result) + + def test_getContext(self): + """The context factory's ``getContext()`` method should produce an + ``OpenSSL.SSL.Context`` object. + """ + contextFactory = crypto.SSLVerifyingContextFactory(self.url) + self.assertIsInstance(contextFactory.getContext(), + OpenSSL.SSL.Context)
tor-commits@lists.torproject.org