diff --git a/CHANGELOG.md b/CHANGELOG.md index c119323cc..140d5df40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,6 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). * Avoid reprocessing challenges that are already validated when a certificate is issued. -* If possible, Certbot uses built-in support for OCSP from recent cryptography - versions instead of the OpenSSL binary: as a consequence Certbot does not need - the OpenSSL binary to be installed anymore if cryptography>=2.5 is installed. * Support for initiating (but not solving end-to-end) TLS-ALPN-01 challenges with the `acme` module. diff --git a/certbot/crypto_util.py b/certbot/crypto_util.py index 66c68eb38..c4a389cd5 100644 --- a/certbot/crypto_util.py +++ b/certbot/crypto_util.py @@ -19,7 +19,7 @@ from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey # https://github.com/python/typeshed/tree/master/third_party/2/cryptography -from cryptography import x509 # type: ignore +from cryptography import x509 # type: ignore from OpenSSL import crypto from OpenSSL import SSL # type: ignore @@ -226,7 +226,7 @@ def verify_renewable_cert(renewable_cert): def verify_renewable_cert_sig(renewable_cert): - """Verifies the signature of a `.storage.RenewableCert` object. + """ Verifies the signature of a `.storage.RenewableCert` object. :param `.storage.RenewableCert` renewable_cert: cert to verify @@ -239,8 +239,22 @@ def verify_renewable_cert_sig(renewable_cert): cert = x509.load_pem_x509_certificate(cert_file.read(), default_backend()) pk = chain.public_key() with warnings.catch_warnings(): - verify_signed_payload(pk, cert.signature, cert.tbs_certificate_bytes, - cert.signature_hash_algorithm) + warnings.simplefilter("ignore") + if isinstance(pk, RSAPublicKey): + # https://github.com/python/typeshed/blob/master/third_party/2/cryptography/hazmat/primitives/asymmetric/rsa.pyi + verifier = pk.verifier( # type: ignore + cert.signature, PKCS1v15(), cert.signature_hash_algorithm + ) + verifier.update(cert.tbs_certificate_bytes) + verifier.verify() + elif isinstance(pk, EllipticCurvePublicKey): + verifier = pk.verifier( + cert.signature, ECDSA(cert.signature_hash_algorithm) + ) + verifier.update(cert.tbs_certificate_bytes) + verifier.verify() + else: + raise errors.Error("Unsupported public key type") except (IOError, ValueError, InvalidSignature) as e: error_str = "verifying the signature of the cert located at {0} has failed. \ Details: {1}".format(renewable_cert.cert, e) @@ -248,37 +262,6 @@ def verify_renewable_cert_sig(renewable_cert): raise errors.Error(error_str) -def verify_signed_payload(public_key, signature, payload, signature_hash_algorithm): - """Check the signature of a payload. - - :param RSAPublicKey/EllipticCurvePublicKey public_key: the public_key to check signature - :param bytes signature: the signature bytes - :param bytes payload: the payload bytes - :param cryptography.hazmat.primitives.hashes.HashAlgorithm - signature_hash_algorithm: algorithm used to hash the payload - - :raises InvalidSignature: If signature verification fails. - :raises errors.Error: If public key type is not supported - """ - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - if isinstance(public_key, RSAPublicKey): - # https://github.com/python/typeshed/blob/master/third_party/2/cryptography/hazmat/primitives/asymmetric/rsa.pyi - verifier = public_key.verifier( # type: ignore - signature, PKCS1v15(), signature_hash_algorithm - ) - verifier.update(payload) - verifier.verify() - elif isinstance(public_key, EllipticCurvePublicKey): - verifier = public_key.verifier( - signature, ECDSA(signature_hash_algorithm) - ) - verifier.update(payload) - verifier.verify() - else: - raise errors.Error("Unsupported public key type") - - def verify_cert_matches_priv_key(cert_path, key_path): """ Verifies that the private key and cert match. diff --git a/certbot/ocsp.py b/certbot/ocsp.py index 0abfd3c23..049e14827 100644 --- a/certbot/ocsp.py +++ b/certbot/ocsp.py @@ -1,79 +1,53 @@ """Tools for checking certificate revocation.""" import logging import re -from datetime import datetime, timedelta + from subprocess import Popen, PIPE -try: - # Only cryptography>=2.5 has ocsp module - # and signature_hash_algorithm attribute in OCSPResponse class - from cryptography.x509 import ocsp # pylint: disable=import-error - getattr(ocsp.OCSPResponse, 'signature_hash_algorithm') -except (ImportError, AttributeError): # pragma: no cover - ocsp = None # type: ignore -from cryptography import x509 -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives import hashes # type: ignore -from cryptography.exceptions import UnsupportedAlgorithm, InvalidSignature -import requests - -from acme.magic_typing import Optional, Tuple # pylint: disable=unused-import, no-name-in-module -from certbot import crypto_util from certbot import errors from certbot import util logger = logging.getLogger(__name__) - class RevocationChecker(object): - """This class figures out OCSP checking on this system, and performs it.""" + "This class figures out OCSP checking on this system, and performs it." - def __init__(self, enforce_openssl_binary_usage=False): + def __init__(self): self.broken = False - self.use_openssl_binary = enforce_openssl_binary_usage or not ocsp - if self.use_openssl_binary: - if not util.exe_exists("openssl"): - logger.info("openssl not installed, can't check revocation") - self.broken = True - return + if not util.exe_exists("openssl"): + logger.info("openssl not installed, can't check revocation") + self.broken = True + return + + # New versions of openssl want -header var=val, old ones want -header var val + test_host_format = Popen(["openssl", "ocsp", "-header", "var", "val"], + stdout=PIPE, stderr=PIPE, universal_newlines=True) + _out, err = test_host_format.communicate() + if "Missing =" in err: + self.host_args = lambda host: ["Host=" + host] + else: + self.host_args = lambda host: ["Host", host] - # New versions of openssl want -header var=val, old ones want -header var val - test_host_format = Popen(["openssl", "ocsp", "-header", "var", "val"], - stdout=PIPE, stderr=PIPE, universal_newlines=True) - _out, err = test_host_format.communicate() - if "Missing =" in err: - self.host_args = lambda host: ["Host=" + host] - else: - self.host_args = lambda host: ["Host", host] def ocsp_revoked(self, cert_path, chain_path): - # type: (str, str) -> bool """Get revoked status for a particular cert version. .. todo:: Make this a non-blocking call :param str cert_path: Path to certificate :param str chain_path: Path to intermediate cert + :rtype bool or None: :returns: True if revoked; False if valid or the check failed - :rtype: bool """ if self.broken: return False - url, host = _determine_ocsp_server(cert_path) - if not host or not url: + + url, host = self.determine_ocsp_server(cert_path) + if not host: return False - - if self.use_openssl_binary: - return self._check_ocsp_openssl_bin(cert_path, chain_path, host, url) - else: - return _check_ocsp_cryptography(cert_path, chain_path, url) - - def _check_ocsp_openssl_bin(self, cert_path, chain_path, host, url): - # type: (str, str, str, str) -> bool # jdkasten thanks "Bulletproof SSL and TLS - Ivan Ristic" for documenting this! cmd = ["openssl", "ocsp", "-no_nonce", @@ -91,117 +65,33 @@ class RevocationChecker(object): except errors.SubprocessError: logger.info("OCSP check failed for %s (are we offline?)", cert_path) return False + return _translate_ocsp_query(cert_path, output, err) -def _determine_ocsp_server(cert_path): - # type: (str) -> Tuple[Optional[str], Optional[str]] - """Extract the OCSP server host from a certificate. + def determine_ocsp_server(self, cert_path): + """Extract the OCSP server host from a certificate. - :param str cert_path: Path to the cert we're checking OCSP for - :rtype tuple: - :returns: (OCSP server URL or None, OCSP server host or None) + :param str cert_path: Path to the cert we're checking OCSP for + :rtype tuple: + :returns: (OCSP server URL or None, OCSP server host or None) - """ - with open(cert_path, 'rb') as file_handler: - cert = x509.load_pem_x509_certificate(file_handler.read(), default_backend()) - try: - extension = cert.extensions.get_extension_for_class(x509.AuthorityInformationAccess) - ocsp_oid = x509.AuthorityInformationAccessOID.OCSP - descriptions = [description for description in extension.value - if description.access_method == ocsp_oid] - - url = descriptions[0].access_location.value - except (x509.ExtensionNotFound, IndexError): - logger.info("Cannot extract OCSP URI from %s", cert_path) - return None, None - - url = url.rstrip() - host = url.partition("://")[2].rstrip("/") - - if host: - return url, host - else: - logger.info("Cannot process OCSP host from URL (%s) in cert at %s", url, cert_path) - return None, None - - -def _check_ocsp_cryptography(cert_path, chain_path, url): - # type: (str, str, str) -> bool - # Retrieve OCSP response - with open(chain_path, 'rb') as file_handler: - issuer = x509.load_pem_x509_certificate(file_handler.read(), default_backend()) - with open(cert_path, 'rb') as file_handler: - cert = x509.load_pem_x509_certificate(file_handler.read(), default_backend()) - builder = ocsp.OCSPRequestBuilder() - builder = builder.add_certificate(cert, issuer, hashes.SHA1()) - request = builder.build() - request_binary = request.public_bytes(serialization.Encoding.DER) - response = requests.post(url, data=request_binary, - headers={'Content-Type': 'application/ocsp-request'}) - if response.status_code != 200: - logger.info("OCSP check failed for %s (are we offline?)", cert_path) - return False - response_ocsp = ocsp.load_der_ocsp_response(response.content) - - # Check OCSP response validity - if response_ocsp.response_status != ocsp.OCSPResponseStatus.SUCCESSFUL: - logger.error("Invalid OCSP response status for %s: %s", - cert_path, response_ocsp.response_status) - return False - - # Check OCSP signature - try: - _check_ocsp_response(response_ocsp, request, issuer) - except UnsupportedAlgorithm as e: - logger.error(str(e)) - except errors.Error as e: - logger.error(str(e)) - except InvalidSignature: - logger.error('Invalid signature on OCSP response for %s', cert_path) - except AssertionError as error: - logger.error('Invalid OCSP response for %s: %s.', cert_path, str(error)) - else: - # Check OCSP certificate status - logger.debug("OCSP certificate status for %s is: %s", - cert_path, response_ocsp.certificate_status) - return response_ocsp.certificate_status == ocsp.OCSPCertStatus.REVOKED - - return False - - -def _check_ocsp_response(response_ocsp, request_ocsp, issuer_cert): - """Verify that the OCSP is valid for serveral criterias""" - # Assert OCSP response corresponds to the certificate we are talking about - if response_ocsp.serial_number != request_ocsp.serial_number: - raise AssertionError('the certificate in response does not correspond ' - 'to the certificate in request') - - # Assert signature is valid - _check_ocsp_response_signature(response_ocsp, issuer_cert) - - # Assert issuer in response is the expected one - if (not isinstance(response_ocsp.hash_algorithm, type(request_ocsp.hash_algorithm)) - or response_ocsp.issuer_key_hash != request_ocsp.issuer_key_hash - or response_ocsp.issuer_name_hash != request_ocsp.issuer_name_hash): - raise AssertionError('the issuer does not correspond to issuer of the certificate.') - - # Assert nextUpdate is in the future, and that thisUpdate is not too old - if response_ocsp.next_update: - if response_ocsp.next_update < datetime.now() - timedelta(minutes=5): - raise AssertionError('next update is in the past.') - interval = response_ocsp.next_update - response_ocsp.this_update - if datetime.now() - response_ocsp.this_update > interval + timedelta(minutes=5): - raise AssertionError('this update is too old.') - - -def _check_ocsp_response_signature(response_ocsp, issuer_cert): - """Verify an OCSP response signature against certificate issuer""" - # Following line may raise UnsupportedAlgorithm - chosen_hash = response_ocsp.signature_hash_algorithm - crypto_util.verify_signed_payload(issuer_cert.public_key(), response_ocsp.signature, - response_ocsp.tbs_response_bytes, chosen_hash) + """ + try: + url, _err = util.run_script( + ["openssl", "x509", "-in", cert_path, "-noout", "-ocsp_uri"], + log=logger.debug) + except errors.SubprocessError: + logger.info("Cannot extract OCSP URI from %s", cert_path) + return None, None + url = url.rstrip() + host = url.partition("://")[2].rstrip("/") + if host: + return url, host + else: + logger.info("Cannot process OCSP host from URL (%s) in cert at %s", url, cert_path) + return None, None def _translate_ocsp_query(cert_path, ocsp_output, ocsp_errors): """Parse openssl's weird output to work out what it means.""" @@ -212,7 +102,7 @@ def _translate_ocsp_query(cert_path, ocsp_output, ocsp_errors): warning = good.group(1) if good else None - if ("Response verify OK" not in ocsp_errors) or (good and warning) or unknown: + if (not "Response verify OK" in ocsp_errors) or (good and warning) or unknown: logger.info("Revocation status for %s is unknown", cert_path) logger.debug("Uncertain output:\n%s\nstderr:\n%s", ocsp_output, ocsp_errors) return False @@ -225,5 +115,6 @@ def _translate_ocsp_query(cert_path, ocsp_output, ocsp_errors): return True else: logger.warning("Unable to properly parse OCSP output: %s\nstderr:%s", - ocsp_output, ocsp_errors) + ocsp_output, ocsp_errors) return False + diff --git a/certbot/tests/ocsp_test.py b/certbot/tests/ocsp_test.py index ad3467e5a..55cd24adb 100644 --- a/certbot/tests/ocsp_test.py +++ b/certbot/tests/ocsp_test.py @@ -1,33 +1,18 @@ """Tests for ocsp.py""" # pylint: disable=protected-access -import unittest -from datetime import datetime, timedelta -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes # type: ignore -from cryptography.exceptions import UnsupportedAlgorithm, InvalidSignature -from cryptography import x509 -try: - # Only cryptography>=2.5 has ocsp module - # and signature_hash_algorithm attribute in OCSPResponse class - from cryptography.x509 import ocsp as ocsp_lib # pylint: disable=import-error - getattr(ocsp_lib.OCSPResponse, 'signature_hash_algorithm') -except (ImportError, AttributeError): # pragma: no cover - ocsp_lib = None # type: ignore +import unittest + import mock from certbot import errors -from certbot.tests import util as test_util out = """Missing = in header key=value ocsp: Use -help for summary. """ +class OCSPTest(unittest.TestCase): -class OCSPTestOpenSSL(unittest.TestCase): - """ - OCSP revokation tests using OpenSSL binary. - """ def setUp(self): from certbot import ocsp @@ -37,7 +22,7 @@ class OCSPTestOpenSSL(unittest.TestCase): mock_communicate.communicate.return_value = (None, out) mock_popen.return_value = mock_communicate mock_exists.return_value = True - self.checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) + self.checker = ocsp.RevocationChecker() def tearDown(self): pass @@ -52,23 +37,23 @@ class OCSPTestOpenSSL(unittest.TestCase): mock_exists.return_value = True from certbot import ocsp - checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) + checker = ocsp.RevocationChecker() self.assertEqual(mock_popen.call_count, 1) self.assertEqual(checker.host_args("x"), ["Host=x"]) mock_communicate.communicate.return_value = (None, out.partition("\n")[2]) - checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) + checker = ocsp.RevocationChecker() self.assertEqual(checker.host_args("x"), ["Host", "x"]) self.assertEqual(checker.broken, False) mock_exists.return_value = False mock_popen.call_count = 0 - checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) + checker = ocsp.RevocationChecker() self.assertEqual(mock_popen.call_count, 0) self.assertEqual(mock_log.call_count, 1) self.assertEqual(checker.broken, True) - @mock.patch('certbot.ocsp._determine_ocsp_server') + @mock.patch('certbot.ocsp.RevocationChecker.determine_ocsp_server') @mock.patch('certbot.util.run_script') def test_ocsp_revoked(self, mock_run, mock_determine): self.checker.broken = True @@ -86,12 +71,21 @@ class OCSPTestOpenSSL(unittest.TestCase): self.assertEqual(self.checker.ocsp_revoked("x", "y"), False) self.assertEqual(mock_run.call_count, 2) - def test_determine_ocsp_server(self): - cert_path = test_util.vector_path('google_certificate.pem') - from certbot import ocsp - result = ocsp._determine_ocsp_server(cert_path) - self.assertEqual(('http://ocsp.digicert.com', 'ocsp.digicert.com'), result) + @mock.patch('certbot.ocsp.logger.info') + @mock.patch('certbot.util.run_script') + def test_determine_ocsp_server(self, mock_run, mock_info): + uri = "http://ocsp.stg-int-x1.letsencrypt.org/" + host = "ocsp.stg-int-x1.letsencrypt.org" + mock_run.return_value = uri, "" + self.assertEqual(self.checker.determine_ocsp_server("beep"), (uri, host)) + mock_run.return_value = "ftp:/" + host + "/", "" + self.assertEqual(self.checker.determine_ocsp_server("beep"), (None, None)) + self.assertEqual(mock_info.call_count, 1) + + c = "confusion" + mock_run.side_effect = errors.SubprocessError(c) + self.assertEqual(self.checker.determine_ocsp_server("beep"), (None, None)) @mock.patch('certbot.ocsp.logger') @mock.patch('certbot.util.run_script') @@ -118,129 +112,6 @@ class OCSPTestOpenSSL(unittest.TestCase): self.assertEqual(mock_log.info.call_count, 1) -@unittest.skipIf(not ocsp_lib, - reason='This class tests functionalities available only on cryptography>=2.5.0') -class OSCPTestCryptography(unittest.TestCase): - """ - OCSP revokation tests using Cryptography >= 2.4.0 - """ - - def setUp(self): - from certbot import ocsp - self.checker = ocsp.RevocationChecker() - self.cert_path = test_util.vector_path('google_certificate.pem') - self.chain_path = test_util.vector_path('google_issuer_certificate.pem') - - @mock.patch('certbot.ocsp._determine_ocsp_server') - @mock.patch('certbot.ocsp._check_ocsp_cryptography') - def test_ensure_cryptography_toggled(self, mock_revoke, mock_determine): - mock_determine.return_value = ('http://example.com', 'example.com') - self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - mock_revoke.assert_called_once_with(self.cert_path, self.chain_path, 'http://example.com') - - @mock.patch('certbot.ocsp.requests.post') - @mock.patch('certbot.ocsp.ocsp.load_der_ocsp_response') - def test_revoke(self, mock_ocsp_response, mock_post): - with mock.patch('certbot.ocsp.crypto_util.verify_signed_payload'): - mock_ocsp_response.return_value = _construct_mock_ocsp_response( - ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) - mock_post.return_value = mock.Mock(status_code=200) - revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - self.assertTrue(revoked) - - @mock.patch('certbot.ocsp.crypto_util.verify_signed_payload') - @mock.patch('certbot.ocsp.requests.post') - @mock.patch('certbot.ocsp.ocsp.load_der_ocsp_response') - def test_revoke_resiliency(self, mock_ocsp_response, mock_post, mock_check): - # Server return an invalid HTTP response - mock_ocsp_response.return_value = _construct_mock_ocsp_response( - ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) - mock_post.return_value = mock.Mock(status_code=400) - revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - self.assertFalse(revoked) - - # OCSP response in invalid - mock_ocsp_response.return_value = _construct_mock_ocsp_response( - ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.UNAUTHORIZED) - mock_post.return_value = mock.Mock(status_code=200) - revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - self.assertFalse(revoked) - - # OCSP response is valid, but certificate status is unknown - mock_ocsp_response.return_value = _construct_mock_ocsp_response( - ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) - mock_post.return_value = mock.Mock(status_code=200) - revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - self.assertFalse(revoked) - - # The OCSP response says that the certificate is revoked, but certificate - # does not contain the OCSP extension. - mock_ocsp_response.return_value = _construct_mock_ocsp_response( - ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) - mock_post.return_value = mock.Mock(status_code=200) - with mock.patch('cryptography.x509.Extensions.get_extension_for_class', - side_effect=x509.ExtensionNotFound( - 'Not found', x509.AuthorityInformationAccessOID.OCSP)): - revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - self.assertFalse(revoked) - - # Valid response, OCSP extension is present, - # but OCSP response uses an unsupported signature. - mock_ocsp_response.return_value = _construct_mock_ocsp_response( - ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) - mock_post.return_value = mock.Mock(status_code=200) - mock_check.side_effect = UnsupportedAlgorithm('foo') - revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - self.assertFalse(revoked) - - # And now, the signature itself is invalid. - mock_ocsp_response.return_value = _construct_mock_ocsp_response( - ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) - mock_post.return_value = mock.Mock(status_code=200) - mock_check.side_effect = InvalidSignature('foo') - revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - self.assertFalse(revoked) - - # Finally, assertion error on OCSP response validity - mock_ocsp_response.return_value = _construct_mock_ocsp_response( - ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) - mock_post.return_value = mock.Mock(status_code=200) - mock_check.side_effect = AssertionError('foo') - revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) - - self.assertFalse(revoked) - - -def _construct_mock_ocsp_response(certificate_status, response_status): - cert = x509.load_pem_x509_certificate( - test_util.load_vector('google_certificate.pem'), default_backend()) - issuer = x509.load_pem_x509_certificate( - test_util.load_vector('google_issuer_certificate.pem'), default_backend()) - builder = ocsp_lib.OCSPRequestBuilder() - builder = builder.add_certificate(cert, issuer, hashes.SHA1()) - request = builder.build() - - return mock.Mock( - response_status=response_status, - certificate_status=certificate_status, - serial_number=request.serial_number, - issuer_key_hash=request.issuer_key_hash, - issuer_name_hash=request.issuer_name_hash, - hash_algorithm=hashes.SHA1(), - next_update=datetime.now() + timedelta(days=1), - this_update=datetime.now() - timedelta(days=1), - signature_algorithm_oid=x509.oid.SignatureAlgorithmOID.RSA_WITH_SHA1, - ) - - # pylint: disable=line-too-long openssl_confused = ("", """ /etc/letsencrypt/live/example.org/cert.pem: good @@ -294,6 +165,5 @@ revoked """, """Response verify OK""") - if __name__ == '__main__': unittest.main() # pragma: no cover diff --git a/certbot/tests/testdata/google_certificate.pem b/certbot/tests/testdata/google_certificate.pem deleted file mode 100644 index c26fea0b1..000000000 --- a/certbot/tests/testdata/google_certificate.pem +++ /dev/null @@ -1,41 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO1pVzllk7ZFHzANBgkqhkiG9w0BAQsFADB1 -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVk -IFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEy -MDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYB -BAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQF -Ewc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQG -A1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYD -VQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -xjyq8jyXDDrBTyitcnB90865tWBzpHSbindG/XqYQkzFMBlXmqkzC+FdTRBYyneZ -w5Pz+XWQvL+74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj -/4x+ogEG3dF/U5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero+5ZAKfYVMLUE -sMwFtoTDJFmVf6JlkOWwsxp1WcQ/MRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQ -xbcaI+GwfQL1FB7Jy+h+KjME9lE/UpgV6Qt2R1xNSmvFCBWu+NFX6epwFP/JRbkM -fLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdag -re7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV+rJfQmzQ84mqhJ6kipMCUG -A1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB/wQE -AwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0 -oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcy -LmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2Vy -dmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG/WwCATAqMCgGCCsGAQUFBwIB -FhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEF -BQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBS -BggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0 -U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAA -MIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWY -BPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe/uPT -Wnsu/m4BEC2+dIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFg -U5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAE -AwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51 -vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d+8H4pxtZOUI5eqkntHOFeV -CqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N+XcqcK0OJYrN -8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxG -eOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW/ip2oJ5grAH8mqQfaunuCVE+v -ac+88lkDK/LVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vN -HnXVUGw+yxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVB -Kqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc/2z2shNoDvxvFUYyY1Oe67xINk -myQKc+ygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma+FXsXBIq -WUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna/teik= ------END CERTIFICATE----- diff --git a/certbot/tests/testdata/google_issuer_certificate.pem b/certbot/tests/testdata/google_issuer_certificate.pem deleted file mode 100644 index 50db47bc4..000000000 --- a/certbot/tests/testdata/google_issuer_certificate.pem +++ /dev/null @@ -1,26 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEXDCCA0SgAwIBAgINAeOpMBz8cgY4P5pTHTANBgkqhkiG9w0BAQsFADBMMSAw -HgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFs -U2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xNzA2MTUwMDAwNDJaFw0yMTEy -MTUwMDAwNDJaMFQxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVHb29nbGUgVHJ1c3Qg -U2VydmljZXMxJTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzMw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKUkvqHv/OJGuo2nIYaNVW -XQ5IWi01CXZaz6TIHLGp/lOJ+600/4hbn7vn6AAB3DVzdQOts7G5pH0rJnnOFUAK -71G4nzKMfHCGUksW/mona+Y2emJQ2N+aicwJKetPKRSIgAuPOB6Aahh8Hb2XO3h9 -RUk2T0HNouB2VzxoMXlkyW7XUR5mw6JkLHnA52XDVoRTWkNty5oCINLvGmnRsJ1z -ouAqYGVQMc/7sy+/EYhALrVJEA8KbtyX+r8snwU5C1hUrwaW6MWOARa8qBpNQcWT -kaIeoYvy/sGIJEmjR0vFEwHdp1cSaWIr6/4g72n7OqXwfinu7ZYW97EfoOSQJeAz -AgMBAAGjggEzMIIBLzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUH -AwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHfCuFCa -Z3Z2sS3ChtCDoH6mfrpLMB8GA1UdIwQYMBaAFJviB1dnHB7AagbeWbSaLd/cGYYu -MDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AucGtpLmdv -b2cvZ3NyMjAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLnBraS5nb29nL2dz -cjIvZ3NyMi5jcmwwPwYDVR0gBDgwNjA0BgZngQwBAgIwKjAoBggrBgEFBQcCARYc -aHR0cHM6Ly9wa2kuZ29vZy9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEA -HLeJluRT7bvs26gyAZ8so81trUISd7O45skDUmAge1cnxhG1P2cNmSxbWsoiCt2e -ux9LSD+PAj2LIYRFHW31/6xoic1k4tbWXkDCjir37xTTNqRAMPUyFRWSdvt+nlPq -wnb8Oa2I/maSJukcxDjNSfpDh/Bd1lZNgdd/8cLdsE3+wypufJ9uXO1iQpnh9zbu -FIwsIONGl1p3A8CgxkqI/UAih3JaGOqcpcdaCIzkBaR9uYQ1X4k2Vg5APRLouzVy -7a8IVk6wuy6pm+T7HT4LY8ibS5FEZlfAFLSW8NwsVz9SBK2Vqn1N0PIMn5xA6NZV -c7o835DLAFshEWfC7TIe3g== ------END CERTIFICATE----- diff --git a/certbot/util.py b/certbot/util.py index 097593e9d..416075ce8 100644 --- a/certbot/util.py +++ b/certbot/util.py @@ -62,7 +62,7 @@ def run_script(params, log=logger.error): """Run the script with the given params. :param list params: List of parameters to pass to Popen - :param callable log: Logger method to use for errors + :param logging.Logger log: Logger to use for errors """ try: diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 8aaa1e3fb..48ddfb570 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -1034,26 +1034,26 @@ ConfigArgParse==0.12.0 \ configobj==5.0.6 \ --hash=sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902 \ --no-binary configobj -cryptography==2.5 \ - --hash=sha256:9e29af877c29338f0cab5f049ccc8bd3ead289a557f144376c4fbc7d1b98914f \ - --hash=sha256:b13c80b877e73bcb6f012813c6f4a9334fcf4b0e96681c5a15dac578f2eedfa0 \ - --hash=sha256:8504661ffe324837f5c4607347eeee4cf0fcad689163c6e9c8d3b18cf1f4a4ad \ - --hash=sha256:e091bd424567efa4b9d94287a952597c05d22155a13716bf5f9f746b9dc906d3 \ - --hash=sha256:42fad67d7072216a49e34f923d8cbda9edacbf6633b19a79655e88a1b4857063 \ - --hash=sha256:9a30384cc402eac099210ab9b8801b2ae21e591831253883decdb4513b77a3cd \ - --hash=sha256:08b753df3672b7066e74376f42ce8fc4683e4fd1358d34c80f502e939ee944d2 \ - --hash=sha256:6f841c7272645dd7c65b07b7108adfa8af0aaea57f27b7f59e01d41f75444c85 \ - --hash=sha256:bfe66b577a7118e05b04141f0f1ed0959552d45672aa7ecb3d91e319d846001e \ - --hash=sha256:522fdb2809603ee97a4d0ef2f8d617bc791eb483313ba307cb9c0a773e5e5695 \ - --hash=sha256:05b3ded5e88747d28ee3ef493f2b92cbb947c1e45cf98cfef22e6d38bb67d4af \ - --hash=sha256:fa2b38c8519c5a3aa6e2b4e1cf1a549b54acda6adb25397ff542068e73d1ed00 \ - --hash=sha256:ab50da871bc109b2d9389259aac269dd1b7c7413ee02d06fe4e486ed26882159 \ - --hash=sha256:9260b201ce584d7825d900c88700aa0bd6b40d4ebac7b213857bd2babee9dbca \ - --hash=sha256:06826e7f72d1770e186e9c90e76b4f84d90cdb917b47ff88d8dc59a7b10e2b1e \ - --hash=sha256:2cd29bd1911782baaee890544c653bb03ec7d95ebeb144d714b0f5c33deb55c7 \ - --hash=sha256:7d335e35306af5b9bc0560ca39f740dfc8def72749645e193dd35be11fb323b3 \ - --hash=sha256:31e5637e9036d966824edaa91bf0aa39dc6f525a1c599f39fd5c50340264e079 \ - --hash=sha256:4946b67235b9d2ea7d31307be9d5ad5959d6c4a8f98f900157b47abddf698401 +cryptography==2.2.2 \ + --hash=sha256:3f3b65d5a16e6b52fba63dc860b62ca9832f51f1a2ae5083c78b6840275f12dd \ + --hash=sha256:5251e7de0de66810833606439ca65c9b9e45da62196b0c88bfadf27740aac09f \ + --hash=sha256:551a3abfe0c8c6833df4192a63371aa2ff43afd8f570ed345d31f251d78e7e04 \ + --hash=sha256:5cb990056b7cadcca26813311187ad751ea644712022a3976443691168781b6f \ + --hash=sha256:60bda7f12ecb828358be53095fc9c6edda7de8f1ef571f96c00b2363643fa3cd \ + --hash=sha256:64b5c67acc9a7c83fbb4b69166f3105a0ab722d27934fac2cb26456718eec2ba \ + --hash=sha256:6fef51ec447fe9f8351894024e94736862900d3a9aa2961528e602eb65c92bdb \ + --hash=sha256:77d0ad229d47a6e0272d00f6bf8ac06ce14715a9fd02c9a97f5a2869aab3ccb2 \ + --hash=sha256:808fe471b1a6b777f026f7dc7bd9a4959da4bfab64972f2bbe91e22527c1c037 \ + --hash=sha256:9b62fb4d18529c84b961efd9187fecbb48e89aa1a0f9f4161c61b7fc42a101bd \ + --hash=sha256:9e5bed45ec6b4f828866ac6a6bedf08388ffcfa68abe9e94b34bb40977aba531 \ + --hash=sha256:9fc295bf69130a342e7a19a39d7bbeb15c0bcaabc7382ec33ef3b2b7d18d2f63 \ + --hash=sha256:abd070b5849ed64e6d349199bef955ee0ad99aefbad792f0c587f8effa681a5e \ + --hash=sha256:ba6a774749b6e510cffc2fb98535f717e0e5fd91c7c99a61d223293df79ab351 \ + --hash=sha256:c332118647f084c983c6a3e1dba0f3bcb051f69d12baccac68db8d62d177eb8a \ + --hash=sha256:d6f46e862ee36df81e6342c2177ba84e70f722d9dc9c6c394f9f1f434c4a5563 \ + --hash=sha256:db6013746f73bf8edd9c3d1d3f94db635b9422f503db3fc5ef105233d4c011ab \ + --hash=sha256:f57008eaff597c69cf692c3518f6d4800f0309253bb138b526a37fe9ef0c7471 \ + --hash=sha256:f6c821ac253c19f2ad4c8691633ae1d1a17f120d5b01ea1d256d7b602bc59887 enum34==1.1.2 ; python_version < '3.4' \ --hash=sha256:2475d7fcddf5951e92ff546972758802de5260bf409319a9f1934e6bbc8b1dc7 \ --hash=sha256:35907defb0f992b75ab7788f65fedc1cf20ffa22688e0e6f6f12afc06b3ea501 diff --git a/letsencrypt-auto-source/pieces/dependency-requirements.txt b/letsencrypt-auto-source/pieces/dependency-requirements.txt index dff57dfd5..1fac78836 100644 --- a/letsencrypt-auto-source/pieces/dependency-requirements.txt +++ b/letsencrypt-auto-source/pieces/dependency-requirements.txt @@ -60,26 +60,26 @@ ConfigArgParse==0.12.0 \ configobj==5.0.6 \ --hash=sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902 \ --no-binary configobj -cryptography==2.5 \ - --hash=sha256:9e29af877c29338f0cab5f049ccc8bd3ead289a557f144376c4fbc7d1b98914f \ - --hash=sha256:b13c80b877e73bcb6f012813c6f4a9334fcf4b0e96681c5a15dac578f2eedfa0 \ - --hash=sha256:8504661ffe324837f5c4607347eeee4cf0fcad689163c6e9c8d3b18cf1f4a4ad \ - --hash=sha256:e091bd424567efa4b9d94287a952597c05d22155a13716bf5f9f746b9dc906d3 \ - --hash=sha256:42fad67d7072216a49e34f923d8cbda9edacbf6633b19a79655e88a1b4857063 \ - --hash=sha256:9a30384cc402eac099210ab9b8801b2ae21e591831253883decdb4513b77a3cd \ - --hash=sha256:08b753df3672b7066e74376f42ce8fc4683e4fd1358d34c80f502e939ee944d2 \ - --hash=sha256:6f841c7272645dd7c65b07b7108adfa8af0aaea57f27b7f59e01d41f75444c85 \ - --hash=sha256:bfe66b577a7118e05b04141f0f1ed0959552d45672aa7ecb3d91e319d846001e \ - --hash=sha256:522fdb2809603ee97a4d0ef2f8d617bc791eb483313ba307cb9c0a773e5e5695 \ - --hash=sha256:05b3ded5e88747d28ee3ef493f2b92cbb947c1e45cf98cfef22e6d38bb67d4af \ - --hash=sha256:fa2b38c8519c5a3aa6e2b4e1cf1a549b54acda6adb25397ff542068e73d1ed00 \ - --hash=sha256:ab50da871bc109b2d9389259aac269dd1b7c7413ee02d06fe4e486ed26882159 \ - --hash=sha256:9260b201ce584d7825d900c88700aa0bd6b40d4ebac7b213857bd2babee9dbca \ - --hash=sha256:06826e7f72d1770e186e9c90e76b4f84d90cdb917b47ff88d8dc59a7b10e2b1e \ - --hash=sha256:2cd29bd1911782baaee890544c653bb03ec7d95ebeb144d714b0f5c33deb55c7 \ - --hash=sha256:7d335e35306af5b9bc0560ca39f740dfc8def72749645e193dd35be11fb323b3 \ - --hash=sha256:31e5637e9036d966824edaa91bf0aa39dc6f525a1c599f39fd5c50340264e079 \ - --hash=sha256:4946b67235b9d2ea7d31307be9d5ad5959d6c4a8f98f900157b47abddf698401 +cryptography==2.2.2 \ + --hash=sha256:3f3b65d5a16e6b52fba63dc860b62ca9832f51f1a2ae5083c78b6840275f12dd \ + --hash=sha256:5251e7de0de66810833606439ca65c9b9e45da62196b0c88bfadf27740aac09f \ + --hash=sha256:551a3abfe0c8c6833df4192a63371aa2ff43afd8f570ed345d31f251d78e7e04 \ + --hash=sha256:5cb990056b7cadcca26813311187ad751ea644712022a3976443691168781b6f \ + --hash=sha256:60bda7f12ecb828358be53095fc9c6edda7de8f1ef571f96c00b2363643fa3cd \ + --hash=sha256:64b5c67acc9a7c83fbb4b69166f3105a0ab722d27934fac2cb26456718eec2ba \ + --hash=sha256:6fef51ec447fe9f8351894024e94736862900d3a9aa2961528e602eb65c92bdb \ + --hash=sha256:77d0ad229d47a6e0272d00f6bf8ac06ce14715a9fd02c9a97f5a2869aab3ccb2 \ + --hash=sha256:808fe471b1a6b777f026f7dc7bd9a4959da4bfab64972f2bbe91e22527c1c037 \ + --hash=sha256:9b62fb4d18529c84b961efd9187fecbb48e89aa1a0f9f4161c61b7fc42a101bd \ + --hash=sha256:9e5bed45ec6b4f828866ac6a6bedf08388ffcfa68abe9e94b34bb40977aba531 \ + --hash=sha256:9fc295bf69130a342e7a19a39d7bbeb15c0bcaabc7382ec33ef3b2b7d18d2f63 \ + --hash=sha256:abd070b5849ed64e6d349199bef955ee0ad99aefbad792f0c587f8effa681a5e \ + --hash=sha256:ba6a774749b6e510cffc2fb98535f717e0e5fd91c7c99a61d223293df79ab351 \ + --hash=sha256:c332118647f084c983c6a3e1dba0f3bcb051f69d12baccac68db8d62d177eb8a \ + --hash=sha256:d6f46e862ee36df81e6342c2177ba84e70f722d9dc9c6c394f9f1f434c4a5563 \ + --hash=sha256:db6013746f73bf8edd9c3d1d3f94db635b9422f503db3fc5ef105233d4c011ab \ + --hash=sha256:f57008eaff597c69cf692c3518f6d4800f0309253bb138b526a37fe9ef0c7471 \ + --hash=sha256:f6c821ac253c19f2ad4c8691633ae1d1a17f120d5b01ea1d256d7b602bc59887 enum34==1.1.2 ; python_version < '3.4' \ --hash=sha256:2475d7fcddf5951e92ff546972758802de5260bf409319a9f1934e6bbc8b1dc7 \ --hash=sha256:35907defb0f992b75ab7788f65fedc1cf20ffa22688e0e6f6f12afc06b3ea501