From b612f422bf156a3b3927038472ad885b1afa556e Mon Sep 17 00:00:00 2001
From: kali <kali@leap.se>
Date: Mon, 3 Sep 2012 02:51:41 +0900
Subject: providercertchecks:check_https_is_working

implementing a https server with its own base testcase
for convenience. https is delicate, and I think it's better
checking against a real implementation than mocking everything
here.
---
 src/leap/eip/tests/test_checks.py | 124 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

(limited to 'src/leap/eip/tests')

diff --git a/src/leap/eip/tests/test_checks.py b/src/leap/eip/tests/test_checks.py
index 1e629203..781fdad5 100644
--- a/src/leap/eip/tests/test_checks.py
+++ b/src/leap/eip/tests/test_checks.py
@@ -1,3 +1,4 @@
+from BaseHTTPServer import BaseHTTPRequestHandler
 import copy
 import json
 try:
@@ -18,6 +19,16 @@ from leap.eip import specs as eipspecs
 from leap.eip import exceptions as eipexceptions
 from leap.eip.tests import data as testdata
 from leap.testing.basetest import BaseLeapTest
+from leap.testing.https_server import BaseHTTPSServerTestCase
+
+
+class NoLogRequestHandler:
+    def log_message(self, *args):
+        # don't write log msg to stderr
+        pass
+
+    def read(self, n=None):
+        return ''
 
 
 class EIPCheckTest(BaseLeapTest):
@@ -157,5 +168,118 @@ class EIPCheckTest(BaseLeapTest):
         sampleconfig = copy.copy(testdata.EIP_SAMPLE_JSON)
         checker.check_complete_eip_config(config=sampleconfig)
 
+
+class ProviderCertCheckerTest(BaseLeapTest):
+
+    __name__ = "provider_cert_checker_tests"
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    # test methods are there, and can be called from run_all
+
+    def test_checker_should_implement_check_methods(self):
+        checker = eipchecks.ProviderCertChecker()
+
+        # For MVS+
+        self.assertTrue(hasattr(checker, "download_ca_cert"),
+                        "missing meth")
+        self.assertTrue(hasattr(checker, "download_ca_signature"),
+                        "missing meth")
+        self.assertTrue(hasattr(checker, "get_ca_signatures"), "missing meth")
+        self.assertTrue(hasattr(checker, "is_there_trust_path"),
+                        "missing meth")
+
+        # For MVS
+        self.assertTrue(hasattr(checker, "is_there_provider_ca"),
+                        "missing meth")
+        self.assertTrue(hasattr(checker, "is_https_working"), "missing meth")
+        self.assertTrue(hasattr(checker, "download_new_client_cert"),
+                        "missing meth")
+
+    def test_checker_should_actually_call_all_tests(self):
+        checker = eipchecks.ProviderCertChecker()
+
+        mc = Mock()
+        checker.run_all(checker=mc)
+        # XXX MVS+
+        #self.assertTrue(mc.download_ca_cert.called, "not called")
+        #self.assertTrue(mc.download_ca_signature.called, "not called")
+        #self.assertTrue(mc.get_ca_signatures.called, "not called")
+        #self.assertTrue(mc.is_there_trust_path.called, "not called")
+
+        # For MVS
+        self.assertTrue(mc.is_there_provider_ca.called, "not called")
+        self.assertTrue(mc.is_https_working.called,
+                        "not called")
+        self.assertTrue(mc.download_new_client_cert.called,
+                        "not called")
+
+    # test individual check methods
+
+    def test_is_there_provider_ca(self):
+        checker = eipchecks.ProviderCertChecker()
+        self.assertTrue(
+            checker.is_there_provider_ca())
+
+
+class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase):
+    class request_handler(NoLogRequestHandler, BaseHTTPRequestHandler):
+        def do_GET(self):
+            #XXX use path to deliver foo stuff
+            #path = urlparse.urlparse(self.path)
+            #print path
+            message = '\n'.join([
+                'OK',
+                ''])
+            self.send_response(200)
+            self.end_headers()
+            self.wfile.write(message)
+
+    def test_is_https_working(self):
+        fetcher = requests
+        uri = "https://%s/" % (self.get_server())
+        # bare requests call. this should just pass (if there is
+        # an https service there).
+        fetcher.get(uri, verify=False)
+        checker = eipchecks.ProviderCertChecker(fetcher=fetcher)
+        self.assertTrue(checker.is_https_working(uri=uri, verify=False))
+
+        # for local debugs, when in doubt
+        #self.assertTrue(checker.is_https_working(uri="https://github.com",
+                        #verify=True))
+
+        # for the two checks below, I know they fail because no ca
+        # cert is passed to them, and I know that's the error that
+        # requests return with our implementation. However, I believe
+        # the right error should be SSL23_READ_BYTES: alert bad certificate
+        # or something similar. I guess we're receiving this because our
+        # server is dying prematurely when the handshake is interrupted on the
+        # client side. In any case I think that requests could handle
+        # this error more consistently and return a ConnectionError on a
+        # higher level.
+        with self.assertRaises(requests.exceptions.SSLError) as exc:
+            fetcher.get(uri, verify=True)
+            self.assertTrue(
+                "SSL23_GET_SERVER_HELLO:unknown protocol" in exc.message)
+        with self.assertRaises(requests.exceptions.SSLError) as exc:
+            checker.is_https_working(uri=uri, verify=True)
+            self.assertTrue(
+                "SSL23_GET_SERVER_HELLO:unknown protocol" in exc.message)
+
+        # XXX get cacert from testing.https_server
+
+    def test_download_new_client_cert(self):
+        checker = eipchecks.ProviderCertChecker()
+        self.assertTrue(checker.download_new_client_cert())
+
+    #def test_download_bad_client_cert(self):
+        #checker = eipchecks.ProviderCertChecker()
+        #self.assertTrue(checker.download_new_client_cert())
+
+
 if __name__ == "__main__":
     unittest.main()
-- 
cgit v1.2.3


From 090aed5e7c569e07b14d74ca71068a277cc39152 Mon Sep 17 00:00:00 2001
From: kali <kali@leap.se>
Date: Mon, 3 Sep 2012 04:18:15 +0900
Subject: basic download cert functionality

---
 src/leap/eip/tests/test_checks.py | 63 ++++++++++++++++++++++++++++-----------
 1 file changed, 46 insertions(+), 17 deletions(-)

(limited to 'src/leap/eip/tests')

diff --git a/src/leap/eip/tests/test_checks.py b/src/leap/eip/tests/test_checks.py
index 781fdad5..541b884b 100644
--- a/src/leap/eip/tests/test_checks.py
+++ b/src/leap/eip/tests/test_checks.py
@@ -6,6 +6,7 @@ try:
 except ImportError:
     import unittest
 import os
+import urlparse
 
 from mock import patch, Mock
 
@@ -20,6 +21,7 @@ from leap.eip import exceptions as eipexceptions
 from leap.eip.tests import data as testdata
 from leap.testing.basetest import BaseLeapTest
 from leap.testing.https_server import BaseHTTPSServerTestCase
+from leap.testing.https_server import where as where_cert
 
 
 class NoLogRequestHandler:
@@ -228,13 +230,18 @@ class ProviderCertCheckerTest(BaseLeapTest):
 
 class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase):
     class request_handler(NoLogRequestHandler, BaseHTTPRequestHandler):
+        responses = {
+            '/': ['OK', ''],
+            '/client.cert': [
+                '-----BEGIN CERTIFICATE-----',
+                '-----END CERTIFICATE-----'],
+            '/badclient.cert': [
+                'BADCERT']}
+
         def do_GET(self):
-            #XXX use path to deliver foo stuff
-            #path = urlparse.urlparse(self.path)
-            #print path
-            message = '\n'.join([
-                'OK',
-                ''])
+            path = urlparse.urlparse(self.path)
+            message = '\n'.join(self.responses.get(
+                path.path, None))
             self.send_response(200)
             self.end_headers()
             self.wfile.write(message)
@@ -254,13 +261,13 @@ class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase):
 
         # for the two checks below, I know they fail because no ca
         # cert is passed to them, and I know that's the error that
-        # requests return with our implementation. However, I believe
-        # the right error should be SSL23_READ_BYTES: alert bad certificate
-        # or something similar. I guess we're receiving this because our
+        # requests return with our implementation.
+        # We're receiving this because our
         # server is dying prematurely when the handshake is interrupted on the
-        # client side. In any case I think that requests could handle
-        # this error more consistently and return a ConnectionError on a
-        # higher level.
+        # client side.
+        # Since we have access to the server, we could check that
+        # the error raised has been:
+        # SSL23_READ_BYTES: alert bad certificate
         with self.assertRaises(requests.exceptions.SSLError) as exc:
             fetcher.get(uri, verify=True)
             self.assertTrue(
@@ -270,15 +277,37 @@ class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase):
             self.assertTrue(
                 "SSL23_GET_SERVER_HELLO:unknown protocol" in exc.message)
 
-        # XXX get cacert from testing.https_server
+        # get cacert from testing.https_server
+        cacert = where_cert('cacert.pem')
+        fetcher.get(uri, verify=cacert)
+        self.assertTrue(checker.is_https_working(uri=uri, verify=cacert))
+
+        # same, but get cacert from leap.custom
+        # XXX TODO!
 
     def test_download_new_client_cert(self):
+        uri = "https://%s/client.cert" % (self.get_server())
+        cacert = where_cert('cacert.pem')
         checker = eipchecks.ProviderCertChecker()
-        self.assertTrue(checker.download_new_client_cert())
+        self.assertTrue(checker.download_new_client_cert(
+                        uri=uri, verify=cacert))
 
-    #def test_download_bad_client_cert(self):
-        #checker = eipchecks.ProviderCertChecker()
-        #self.assertTrue(checker.download_new_client_cert())
+        # now download a malformed cert
+        uri = "https://%s/badclient.cert" % (self.get_server())
+        cacert = where_cert('cacert.pem')
+        checker = eipchecks.ProviderCertChecker()
+        with self.assertRaises(ValueError):
+            self.assertTrue(checker.download_new_client_cert(
+                            uri=uri, verify=cacert))
+
+        # did we write cert to its path?
+        self.assertTrue(os.path.isfile(eipspecs.client_cert_path()))
+        certfile = eipspecs.client_cert_path()
+        with open(certfile, 'r') as cf:
+            certcontent = cf.read()
+        self.assertEqual(certcontent,
+                         '\n'.join(
+                             self.request_handler.responses['/client.cert']))
 
 
 if __name__ == "__main__":
-- 
cgit v1.2.3


From 37d7e272b7f8a649034a0cf60f6c4a1424bf767a Mon Sep 17 00:00:00 2001
From: kali <kali@leap.se>
Date: Tue, 4 Sep 2012 01:08:05 +0900
Subject: better separate cert validation/download logic

stubbing out the timestamp validity check (waiting for #507)
also some more deep tests are missing, wrote todo in tests.
---
 src/leap/eip/tests/test_checks.py | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

(limited to 'src/leap/eip/tests')

diff --git a/src/leap/eip/tests/test_checks.py b/src/leap/eip/tests/test_checks.py
index 541b884b..09fdaabf 100644
--- a/src/leap/eip/tests/test_checks.py
+++ b/src/leap/eip/tests/test_checks.py
@@ -199,7 +199,7 @@ class ProviderCertCheckerTest(BaseLeapTest):
         self.assertTrue(hasattr(checker, "is_there_provider_ca"),
                         "missing meth")
         self.assertTrue(hasattr(checker, "is_https_working"), "missing meth")
-        self.assertTrue(hasattr(checker, "download_new_client_cert"),
+        self.assertTrue(hasattr(checker, "check_new_cert_needed"),
                         "missing meth")
 
     def test_checker_should_actually_call_all_tests(self):
@@ -217,7 +217,7 @@ class ProviderCertCheckerTest(BaseLeapTest):
         self.assertTrue(mc.is_there_provider_ca.called, "not called")
         self.assertTrue(mc.is_https_working.called,
                         "not called")
-        self.assertTrue(mc.download_new_client_cert.called,
+        self.assertTrue(mc.check_new_cert_needed.called,
                         "not called")
 
     # test individual check methods
@@ -233,6 +233,7 @@ class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase):
         responses = {
             '/': ['OK', ''],
             '/client.cert': [
+                # XXX get sample cert
                 '-----BEGIN CERTIFICATE-----',
                 '-----END CERTIFICATE-----'],
             '/badclient.cert': [
@@ -301,13 +302,30 @@ class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase):
                             uri=uri, verify=cacert))
 
         # did we write cert to its path?
-        self.assertTrue(os.path.isfile(eipspecs.client_cert_path()))
+        clientcertfile = eipspecs.client_cert_path()
+        self.assertTrue(os.path.isfile(clientcertfile))
         certfile = eipspecs.client_cert_path()
         with open(certfile, 'r') as cf:
             certcontent = cf.read()
         self.assertEqual(certcontent,
                          '\n'.join(
                              self.request_handler.responses['/client.cert']))
+        os.remove(clientcertfile)
+
+    def test_is_cert_valid(self):
+        checker = eipchecks.ProviderCertChecker()
+        # TODO: better exception catching
+        with self.assertRaises(Exception) as exc:
+            self.assertFalse(checker.is_cert_valid())
+            exc.message = "missing cert"
+
+    def test_check_new_cert_needed(self):
+        # check: missing cert
+        checker = eipchecks.ProviderCertChecker()
+        self.assertTrue(checker.check_new_cert_needed(skip_download=True))
+        # TODO check: malformed cert
+        # TODO check: expired cert
+        # TODO check: pass test server uri instead of skip
 
 
 if __name__ == "__main__":
-- 
cgit v1.2.3