From c546dddd7f6896d52b32eb1bce19c39615abc88d Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Mon, 13 Jul 2015 15:11:11 +0000 Subject: [PATCH] Add DVSNIResponse.verify_cert. --- acme/acme/challenges.py | 23 ++++++++++++++++++----- acme/acme/challenges_test.py | 33 ++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index e60655ea1..f2fc5ed07 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -9,6 +9,7 @@ import socket import OpenSSL import requests +from acme import errors from acme import crypto_util from acme import interfaces from acme import jose @@ -247,7 +248,23 @@ class DVSNIResponse(ChallengeResponse): return self.z(chall) + self.DOMAIN_SUFFIX def simple_verify(self, chall, domain, key, **kwargs): - """Verify DVSNI. + """Simple verify. + + Probes DVSNI certificate and checks it using `verify_cert`; + hence all arguments documented in `verify_cert`. + + """ + try: + cert = chall.probe_cert(domain=domain, **kwargs) + except errors.Error as error: + logger.debug(error, exc_info=True) + return False + # TODO: check "It is a valid self-signed certificate" and + # return False if not + return self.verify_cert(chall, domain, key, cert) + + def verify_cert(self, chall, domain, key, cert): + """Verify DVSNI certificate. :param .challenges.DVSNI chall: Corresponding challenge. :param str domain: Domain name being validated. @@ -260,10 +277,6 @@ class DVSNIResponse(ChallengeResponse): :rtype: bool """ - cert = chall.probe_cert(domain=domain, **kwargs) - # TODO: check "It is a valid self-signed certificate" and - # return False if not - # pylint: disable=protected-access sans = crypto_util._pyopenssl_cert_or_req_san(cert) logging.debug('Certificate %s. SANs: %s', cert.digest('sha1'), sans) diff --git a/acme/acme/challenges_test.py b/acme/acme/challenges_test.py index f76bdf05a..a68a62ab4 100644 --- a/acme/acme/challenges_test.py +++ b/acme/acme/challenges_test.py @@ -6,6 +6,7 @@ import OpenSSL import requests import urlparse +from acme import errors from acme import jose from acme import other from acme import test_util @@ -245,12 +246,34 @@ class DVSNIResponseTest(unittest.TestCase): from acme.challenges import DVSNIResponse hash(DVSNIResponse.from_json(self.jmsg)) - def test_simple_verify(self): # TODO + @mock.patch('acme.challenges.DVSNIResponse.verify_cert') + def test_simple_verify(self, mock_verify_cert): + chall = mock.Mock() + chall.probe_cert.return_value = mock.sentinel.cert + mock_verify_cert.return_value = 'x' + self.assertEqual('x', self.msg.simple_verify( + chall, mock.sentinel.domain, mock.sentinel.key)) + chall.probe_cert.assert_called_once_with(domain=mock.sentinel.domain) + self.msg.verify_cert.assert_called_once_with( + chall, mock.sentinel.domain, mock.sentinel.key, + mock.sentinel.cert) + + def test_simple_verify_false_on_probe_error(self): + chall = mock.Mock() + chall.probe_cert.side_effect = errors.Error + self.assertFalse(self.msg.simple_verify( + chall=chall, domain=None, key=None)) + + def test_verify_cert_postive(self): + pass # XXX + + def test_verify_cert_negative(self): chall = mock.MagicMock() - chall.probe_cert.return_value = OpenSSL.crypto.load_certificate( - OpenSSL.crypto.FILETYPE_PEM, test_util.load_vector('cert.pem')) - self.assertFalse(self.msg.simple_verify(chall, "example.com", key=None)) - # TODO: key not None + self.assertFalse(self.msg.verify_cert( + chall, domain="example.com", key=None, + cert=OpenSSL.crypto.load_certificate( + OpenSSL.crypto.FILETYPE_PEM, + test_util.load_vector('cert.pem')))) class RecoveryContactTest(unittest.TestCase):