예제 #1
0
class TestLocalVerifier(unittest.TestCase):
    def setUp(self):
        self.verifier = LocalVerifier()

    def test_expired_assertion(self):
        # It is invalid because it is expired.
        self.assertRaises(ValueError, self.verifier.verify, EXPIRED_ASSERTION)
        # But it'll verify OK if we wind back the clock.
        data = self.verifier.verify(EXPIRED_ASSERTION, now=0)
        self.assertEquals(data["audience"], "http://myfavoritebeer.org")
        # And will fail if we give the wrong audience.
        self.assertRaises(ValueError, self.verifier.verify, EXPIRED_ASSERTION, "h", 0)

    def test_expired_assertion_dev(self):
        # It is invalid because it is expired.
        self.assertRaises(ValueError, self.verifier.verify, EXPIRED_ASSERTION_DEV)
        # But it'll verify OK if we wind back the clock.
        data = self.verifier.verify(EXPIRED_ASSERTION_DEV, now=0)
        self.assertEquals(data["audience"], "http://dev.myfavoritebeer.org")
        # And will fail if we give the wrong audience.
        self.assertRaises(ValueError, self.verifier.verify, EXPIRED_ASSERTION_DEV, "h", 0)

    def test_junk(self):
        self.assertRaises(ValueError, self.verifier.verify, "JUNK")
        self.assertRaises(ValueError, self.verifier.verify, "J")
        self.assertRaises(ValueError, self.verifier.verify, "\x01\x02")
예제 #2
0
    def test_cache_eviction_based_on_time(self):
        certs = CertificatesManager(FIFOCache(cache_timeout=0.1))
        verifier = LocalVerifier(certs=certs, warning=False)
        # Prime the cache by verifying an assertion.
        assertion = make_assertion("*****@*****.**", "")
        self.assertTrue(verifier.verify(assertion))
        # Make it error out if re-fetching the keys

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            verifier.fetch_public_key = fetch_public_key
            # It should be in the cache, so this works fine.
            verifier.verify(assertion)
            # But after sleeping it gets evicted and the error is triggered.
            time.sleep(0.1)
            self.assertRaises(RuntimeError, verifier.verify, assertion)
예제 #3
0
    def test_cache_eviction_during_write(self):
        certs = CertificatesManager(cache_timeout=0.1)
        verifier = LocalVerifier(certs=certs, warning=False)
        # Prime the cache by verifying an assertion.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        self.assertEquals(len(certs.cache), 1)
        # Let that cached key expire
        time.sleep(0.1)
        # Now grab a different key; caching it should purge the expired key.
        assertion2 = make_assertion("*****@*****.**", "", "2.com")
        self.assertTrue(verifier.verify(assertion2))
        self.assertEquals(len(certs.cache), 1)
        # Check that only the second entry is in cache.

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
예제 #4
0
    def test_cache_eviction_based_on_size(self):
        certs = CertificatesManager(max_size=2)
        verifier = LocalVerifier(certs=certs, warning=False)
        # Prime the cache by verifying some assertions.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        assertion2 = make_assertion("*****@*****.**", "", "2.com")
        self.assertTrue(verifier.verify(assertion2))
        self.assertEquals(len(certs.cache), 2)
        # Hitting a third host should evict the first public key.
        assertion3 = make_assertion("*****@*****.**", "", "3.com")
        self.assertTrue(verifier.verify(assertion3))
        self.assertEquals(len(certs.cache), 2)
        # Make it error out if re-fetching any keys

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            # It should have to re-fetch for 1, but not 2.
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
예제 #5
0
class TestLocalVerifier(unittest.TestCase):
    def setUp(self):
        self.verifier = LocalVerifier()

    def test_expired_assertion(self):
        # It is invalid because it is expired.
        self.assertRaises(ValueError, self.verifier.verify, EXPIRED_ASSERTION)
        # But it'll verify OK if we find back the clock.
        data = self.verifier.verify(EXPIRED_ASSERTION, now=0)
        self.assertEquals(data["audience"], "http://myfavoritebeer.org")
        self.assertEquals(data["email"], "*****@*****.**")

    def test_junk(self):
        self.assertRaises(ValueError, self.verifier.verify, "JUNK")
        self.assertRaises(ValueError, self.verifier.verify, "J")
        self.assertRaises(ValueError, self.verifier.verify, "\x01\x02")
예제 #6
0
 def setUp(self):
     with warnings.catch_warnings(record=True) as w:
         warnings.simplefilter("always")
         self.verifier = LocalVerifier()
     # There should be a warning about using this verifier.
     self.assertEquals(w[0].category, FutureWarning)
예제 #7
0
class TestLocalVerifier(unittest.TestCase, VerifierTestCases):

    def setUp(self):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            self.verifier = LocalVerifier()
        # There should be a warning about using this verifier.
        self.assertEquals(w[0].category, FutureWarning)

    def test_error_while_fetching_public_key(self):
        def urlopen(*args, **kwds):
            raise RuntimeError("TESTING")
        self.verifier.urlopen = urlopen
        self.assertRaises(ConnectionError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_missing_well_known_document(self):
        def urlopen(url, data):
            raise RuntimeError("404 Not Found")
        self.verifier.urlopen = urlopen
        self.assertRaises(InvalidIssuerError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_malformed_well_known_document(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "I AINT NO JSON, FOOL!"
            return response
        self.verifier.urlopen = urlopen
        self.assertRaises(InvalidIssuerError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_malformed_pub_key_document(self):
        called = []

        def urlopen(url, data):
            # First call must raise 404 so it will look for /pk.
            # Second call must return invalid JSON.
            class response(object):
                @staticmethod
                def read():
                    if not called:
                        called.append(True)
                        raise ValueError("404 Not Found")
                    return "I AINT NO JSON, FOOL!"
            return response
        self.verifier.urlopen = urlopen
        self.assertRaises(InvalidIssuerError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_well_known_doc_with_no_public_key(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "{}"
            return response
        self.verifier.urlopen = urlopen
        self.assertRaises(InvalidIssuerError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_well_known_doc_with_public_key(self):
        #  The browserid.org server doesn't currently have /.well-known/vep.
        #  This simulates it with a dummy key.
        def urlopen(url, data):  # NOQA
            class response(object):
                @staticmethod
                def read():
                    key = DummyVerifier.fetch_public_key("browserid.org")
                    return json.dumps({"public-key": key})
            return response
        self.verifier.urlopen = urlopen
        assertion = DummyVerifier.make_assertion("*****@*****.**", "http://e.com")
        self.assertTrue(self.verifier.verify(assertion))

    def test_handling_of_invalid_content_length_header_from_server(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def info():
                    return {"Content-Length": "forty-two"}
                @staticmethod  # NOQA
                def read(size):
                    raise RuntimeError  # pragma: nocover
            return response
        self.verifier.urlopen = urlopen
        self.assertRaises(ConnectionError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_error_handling_in_verify_certificate_chain(self):
        self.assertRaises(ValueError,
                          self.verifier.verify_certificate_chain, [])
        certs = decode_json_bytes(EXPIRED_ASSERTION)["certificates"]
        certs = [jwt.parse(cert) for cert in certs]
        self.assertRaises(ExpiredSignatureError,
                          self.verifier.verify_certificate_chain, certs)
예제 #8
0
 def setUp(self):
     self.verifier = LocalVerifier()
예제 #9
0
 def setUp(self):
     with warnings.catch_warnings(record=True):
         warnings.simplefilter("default")
         self.verifier = LocalVerifier()
예제 #10
0
class TestLocalVerifier(unittest.TestCase, VerifierTestCases):

    def setUp(self):
        with warnings.catch_warnings(record=True):
            warnings.simplefilter("default")
            self.verifier = LocalVerifier()

    def test_expired_assertion(self):
        super(TestLocalVerifier, self).test_expired_assertion()
        # It'll verify OK if we wind back the clock.
        data = self.verifier.verify(EXPIRED_ASSERTION, now=0)
        self.assertEquals(data["audience"], "http://myfavoritebeer.org")
        # And will fail if we give the wrong audience.
        self.assertRaises(AudienceMismatchError,
                          self.verifier.verify, EXPIRED_ASSERTION, "h", 0)

    def test_expired_assertion_dev(self):
        super(TestLocalVerifier, self).test_expired_assertion_dev()
        # It'll verify OK if we wind back the clock.
        data = self.verifier.verify(EXPIRED_ASSERTION_DEV, now=0)
        self.assertEquals(data["audience"], "http://dev.myfavoritebeer.org")
        # And will fail if we give the wrong audience.
        self.assertRaises(AudienceMismatchError,
                          self.verifier.verify, EXPIRED_ASSERTION_DEV, "h", 0)

    def test_error_while_fetching_public_key(self):
        def fetch_public_key(hostname):
            raise RuntimeError("TESTING")
        self.verifier.fetch_public_key = fetch_public_key
        self.assertRaises(ConnectionError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_missing_host_meta_document(self):
        def urlopen(url, data):
            raise RuntimeError("404 Not Found")
        self.verifier.urlopen = urlopen
        self.assertRaises(ConnectionError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_malformed_host_meta_document(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "I AINT NO XML, FOOL!"
            return response
        self.verifier.urlopen = urlopen
        self.assertRaises(ConnectionError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_host_meta_with_no_key_link(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "<Meta>"\
                           " <Link rel='not the key link' href='haha' />"\
                           "</Meta>"
            return response
        self.verifier.urlopen = urlopen
        self.assertRaises(ConnectionError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_host_meta_with_key_link(self):
        #  The browserid.org server doesn't currently have host-meta.
        #  This simulates it with a link to the known public key URL.
        called = []
        orig_urlopen = self.verifier.urlopen
        def urlopen(url, data):
            if called:
                return orig_urlopen("https://browserid.org/pk")
            called.append(True)
            class response(object):
                @staticmethod
                def read():
                    rel = self.verifier.HOST_META_REL_PUBKEY
                    return "<Meta>"\
                           " <Link rel='" + rel + "' href='haha' />"\
                           "</Meta>"
            return response
        self.verifier.urlopen = urlopen
        self.assertTrue(self.verifier.verify(EXPIRED_ASSERTION, now=0))

    def test_handling_of_invalid_content_length_header_from_server(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def info():
                    return {"Content-Length": "forty-two"}
                @staticmethod
                def read(size):
                    raise RuntimeError  # pragma: nocover
            return response
        self.verifier.urlopen = urlopen
        self.assertRaises(ConnectionError,
                          self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_error_handling_in_verify_certificate_chain(self):
        self.assertRaises(ValueError,
                          self.verifier.verify_certificate_chain, [])
        certs = decode_json_bytes(EXPIRED_ASSERTION)["certificates"]
        certs = [JWT.parse(cert) for cert in certs]
        self.assertRaises(ExpiredSignatureError,
                          self.verifier.verify_certificate_chain, certs)
        self.assertTrue(self.verifier.verify_certificate_chain(certs, 0))
예제 #11
0
 def setUp(self):
     self.patched = patched_key_fetching()
     self.patched.__enter__()
     self.verifier = LocalVerifier(warning=False)
예제 #12
0
class TestDummyVerifier(unittest.TestCase, VerifierTestCases):
    def setUp(self):
        self.patched = patched_key_fetching()
        self.patched.__enter__()
        self.verifier = LocalVerifier(warning=False)

    def tearDown(self):
        self.patched.__exit__(None, None, None)

    def test_verification_of_valid_dummy_assertion(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience)
        self.assertTrue(self.verifier.verify(assertion))
        self.assertTrue(self.verifier.verify(assertion, audience))
        self.assertRaises(AudienceMismatchError, self.verifier.verify, assertion, "http://moz.com")

    def test_verification_of_oldstyle_dummy_assertion(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience, new_style=False)
        self.assertTrue(self.verifier.verify(assertion))
        self.assertTrue(self.verifier.verify(assertion, audience))
        self.assertRaises(AudienceMismatchError, self.verifier.verify, assertion, "http://moz.com")

    def test_verification_of_untrusted_issuer(self):
        audience = "http://example.com"
        issuer = "moz.com"
        # Assertions for @moz.com addresses can come from moz.com
        assertion = make_assertion("*****@*****.**", audience, issuer=issuer)
        self.assertTrue(self.verifier.verify(assertion, audience))
        # But assertions for other addresses cannot.
        assertion = make_assertion("*****@*****.**", audience, issuer=issuer)
        self.assertRaises(InvalidSignatureError, self.verifier.verify, assertion, audience)

    def test_verification_of_expired_dummy_assertion(self):
        audience = "http://example.com"
        now = time.time() * 1000
        assertion = make_assertion("*****@*****.**", audience, exp=now - 1)
        self.assertTrue(self.verifier.verify(assertion, now=now - 2))
        self.assertRaises(ExpiredSignatureError, self.verifier.verify, assertion)

    def test_verification_of_dummy_assertion_with_bad_assertion_sig(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience, assertion_sig="BADTOTHEBONE")
        self.assertRaises(InvalidSignatureError, self.verifier.verify, assertion)

    def test_verification_of_dummy_assertion_with_bad_certificate_sig(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience, certificate_sig="CORRUPTUS")
        self.assertRaises(InvalidSignatureError, self.verifier.verify, assertion)

    def test_cache_eviction_based_on_time(self):
        certs = CertificatesManager(FIFOCache(cache_timeout=0.1))
        verifier = LocalVerifier(certs=certs, warning=False)
        # Prime the cache by verifying an assertion.
        assertion = make_assertion("*****@*****.**", "")
        self.assertTrue(verifier.verify(assertion))
        # Make it error out if re-fetching the keys

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            verifier.fetch_public_key = fetch_public_key
            # It should be in the cache, so this works fine.
            verifier.verify(assertion)
            # But after sleeping it gets evicted and the error is triggered.
            time.sleep(0.1)
            self.assertRaises(RuntimeError, verifier.verify, assertion)

    def test_cache_eviction_based_on_size(self):
        certs = CertificatesManager(max_size=2)
        verifier = LocalVerifier(certs=certs, warning=False)
        # Prime the cache by verifying some assertions.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        assertion2 = make_assertion("*****@*****.**", "", "2.com")
        self.assertTrue(verifier.verify(assertion2))
        self.assertEquals(len(certs.cache), 2)
        # Hitting a third host should evict the first public key.
        assertion3 = make_assertion("*****@*****.**", "", "3.com")
        self.assertTrue(verifier.verify(assertion3))
        self.assertEquals(len(certs.cache), 2)
        # Make it error out if re-fetching any keys

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            # It should have to re-fetch for 1, but not 2.
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)

    def test_cache_eviction_during_write(self):
        certs = CertificatesManager(cache_timeout=0.1)
        verifier = LocalVerifier(certs=certs, warning=False)
        # Prime the cache by verifying an assertion.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        self.assertEquals(len(certs.cache), 1)
        # Let that cached key expire
        time.sleep(0.1)
        # Now grab a different key; caching it should purge the expired key.
        assertion2 = make_assertion("*****@*****.**", "", "2.com")
        self.assertTrue(verifier.verify(assertion2))
        self.assertEquals(len(certs.cache), 1)
        # Check that only the second entry is in cache.

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
예제 #13
0
 def setUp(self):
     with warnings.catch_warnings(record=True) as w:
         warnings.simplefilter("always")
         self.verifier = LocalVerifier()
     # There should be a warning about using this verifier.
     self.assertEquals(w[0].category, FutureWarning)
예제 #14
0
class TestLocalVerifier(unittest.TestCase, VerifierTestCases):
    def setUp(self):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            self.verifier = LocalVerifier()
        # There should be a warning about using this verifier.
        self.assertEquals(w[0].category, FutureWarning)

    def test_error_while_fetching_public_key(self):
        def urlopen(*args, **kwds):
            raise RuntimeError("TESTING")

        self.verifier.urlopen = urlopen
        self.assertRaises(ConnectionError,
                          self.verifier.verify,
                          EXPIRED_ASSERTION,
                          now=0)

    def test_missing_well_known_document(self):
        def urlopen(url, data):
            raise RuntimeError("404 Not Found")

        self.verifier.urlopen = urlopen
        self.assertRaises(InvalidIssuerError,
                          self.verifier.verify,
                          EXPIRED_ASSERTION,
                          now=0)

    def test_malformed_well_known_document(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "I AINT NO JSON, FOOL!"

            return response

        self.verifier.urlopen = urlopen
        self.assertRaises(InvalidIssuerError,
                          self.verifier.verify,
                          EXPIRED_ASSERTION,
                          now=0)

    def test_malformed_pub_key_document(self):
        called = []

        def urlopen(url, data):
            # First call must raise 404 so it will look for /pk.
            # Second call must return invalid JSON.
            class response(object):
                @staticmethod
                def read():
                    if not called:
                        called.append(True)
                        raise ValueError("404 Not Found")
                    return "I AINT NO JSON, FOOL!"

            return response

        self.verifier.urlopen = urlopen
        self.assertRaises(InvalidIssuerError,
                          self.verifier.verify,
                          EXPIRED_ASSERTION,
                          now=0)

    def test_well_known_doc_with_no_public_key(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "{}"

            return response

        self.verifier.urlopen = urlopen
        self.assertRaises(InvalidIssuerError,
                          self.verifier.verify,
                          EXPIRED_ASSERTION,
                          now=0)

    def test_well_known_doc_with_public_key(self):
        #  The browserid.org server doesn't currently have /.well-known/vep.
        #  This simulates it with a dummy key.
        def urlopen(url, data):  # NOQA
            class response(object):
                @staticmethod
                def read():
                    key = DummyVerifier.fetch_public_key("browserid.org")
                    return json.dumps({"public-key": key})

            return response

        self.verifier.urlopen = urlopen
        assertion = DummyVerifier.make_assertion("*****@*****.**", "http://e.com")
        self.assertTrue(self.verifier.verify(assertion))

    def test_handling_of_invalid_content_length_header_from_server(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def info():
                    return {"Content-Length": "forty-two"}

                @staticmethod  # NOQA
                def read(size):
                    raise RuntimeError  # pragma: nocover

            return response

        self.verifier.urlopen = urlopen
        self.assertRaises(ConnectionError,
                          self.verifier.verify,
                          EXPIRED_ASSERTION,
                          now=0)

    def test_error_handling_in_verify_certificate_chain(self):
        self.assertRaises(ValueError, self.verifier.verify_certificate_chain,
                          [])
        certs = decode_json_bytes(EXPIRED_ASSERTION)["certificates"]
        certs = [jwt.parse(cert) for cert in certs]
        self.assertRaises(ExpiredSignatureError,
                          self.verifier.verify_certificate_chain, certs)