mirror of
https://github.com/certbot/certbot.git
synced 2026-01-26 07:41:33 +03:00
Validate OCSP responses in case an explicit responder is designated (#7054)
* Validate OCSP response for responders that are not the certificate's issuer. * Improve OCSP tests using a issuer/responder pair for OCSP responses * Clean code * Update ocsp_test.py * Add various comments * Add several cases of ocsp responder. More factories for the resilience tests. * Update ocsp_test.py
This commit is contained in:
committed by
Joona Hoikkala
parent
09b7d2f461
commit
889aeb31df
@@ -155,7 +155,7 @@ def _check_ocsp_cryptography(cert_path, chain_path, url):
|
||||
|
||||
# Check OCSP signature
|
||||
try:
|
||||
_check_ocsp_response(response_ocsp, request, issuer)
|
||||
_check_ocsp_response(response_ocsp, request, issuer, cert_path)
|
||||
except UnsupportedAlgorithm as e:
|
||||
logger.error(str(e))
|
||||
except errors.Error as e:
|
||||
@@ -173,7 +173,7 @@ def _check_ocsp_cryptography(cert_path, chain_path, url):
|
||||
return False
|
||||
|
||||
|
||||
def _check_ocsp_response(response_ocsp, request_ocsp, issuer_cert):
|
||||
def _check_ocsp_response(response_ocsp, request_ocsp, issuer_cert, cert_path):
|
||||
"""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:
|
||||
@@ -181,7 +181,7 @@ def _check_ocsp_response(response_ocsp, request_ocsp, issuer_cert):
|
||||
'to the certificate in request')
|
||||
|
||||
# Assert signature is valid
|
||||
_check_ocsp_response_signature(response_ocsp, issuer_cert)
|
||||
_check_ocsp_response_signature(response_ocsp, issuer_cert, cert_path)
|
||||
|
||||
# Assert issuer in response is the expected one
|
||||
if (not isinstance(response_ocsp.hash_algorithm, type(request_ocsp.hash_algorithm))
|
||||
@@ -207,11 +207,52 @@ def _check_ocsp_response(response_ocsp, request_ocsp, issuer_cert):
|
||||
raise AssertionError('param nextUpdate is in the past.')
|
||||
|
||||
|
||||
def _check_ocsp_response_signature(response_ocsp, issuer_cert):
|
||||
"""Verify an OCSP response signature against certificate issuer"""
|
||||
def _check_ocsp_response_signature(response_ocsp, issuer_cert, cert_path):
|
||||
"""Verify an OCSP response signature against certificate issuer or responder"""
|
||||
if response_ocsp.responder_name == issuer_cert.subject:
|
||||
# Case where the OCSP responder is also the certificate issuer
|
||||
logger.debug('OCSP response for certificate %s is signed by the certificate\'s issuer.',
|
||||
cert_path)
|
||||
responder_cert = issuer_cert
|
||||
else:
|
||||
# Case where the OCSP responder is not the certificate issuer
|
||||
logger.debug('OCSP response for certificate %s is delegated to an external responder.',
|
||||
cert_path)
|
||||
|
||||
responder_certs = [cert for cert in response_ocsp.certificates
|
||||
if cert.subject == response_ocsp.responder_name]
|
||||
if not responder_certs:
|
||||
raise AssertionError('no matching responder certificate could be found')
|
||||
|
||||
# We suppose here that the ACME server support only one certificate in the OCSP status
|
||||
# request. This is currently the case for LetsEncrypt servers.
|
||||
# See https://github.com/letsencrypt/boulder/issues/2331
|
||||
responder_cert = responder_certs[0]
|
||||
|
||||
if responder_cert.issuer != issuer_cert.subject:
|
||||
raise AssertionError('responder certificate is not signed '
|
||||
'by the certificate\'s issuer')
|
||||
|
||||
try:
|
||||
extension = responder_cert.extensions.get_extension_for_class(x509.ExtendedKeyUsage)
|
||||
delegate_authorized = x509.oid.ExtendedKeyUsageOID.OCSP_SIGNING in extension.value
|
||||
except (x509.ExtensionNotFound, IndexError):
|
||||
delegate_authorized = False
|
||||
if not delegate_authorized:
|
||||
raise AssertionError('responder is not authorized by issuer to sign OCSP responses')
|
||||
|
||||
# Following line may raise UnsupportedAlgorithm
|
||||
chosen_hash = responder_cert.signature_hash_algorithm
|
||||
# For a delegate OCSP responder, we need first check that its certificate is effectively
|
||||
# signed by the certificate issuer.
|
||||
crypto_util.verify_signed_payload(issuer_cert.public_key(), responder_cert.signature,
|
||||
responder_cert.tbs_certificate_bytes, chosen_hash)
|
||||
|
||||
# Following line may raise UnsupportedAlgorithm
|
||||
chosen_hash = response_ocsp.signature_hash_algorithm
|
||||
crypto_util.verify_signed_payload(issuer_cert.public_key(), response_ocsp.signature,
|
||||
# We check that the OSCP response is effectively signed by the responder
|
||||
# (an authorized delegate one or the certificate issuer itself).
|
||||
crypto_util.verify_signed_payload(responder_cert.public_key(), response_ocsp.signature,
|
||||
response_ocsp.tbs_response_bytes, chosen_hash)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Tests for ocsp.py"""
|
||||
# pylint: disable=protected-access
|
||||
import contextlib
|
||||
import unittest
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
@@ -87,11 +88,11 @@ class OCSPTestOpenSSL(unittest.TestCase):
|
||||
self.assertEqual(mock_run.call_count, 2)
|
||||
|
||||
def test_determine_ocsp_server(self):
|
||||
cert_path = test_util.vector_path('google_certificate.pem')
|
||||
cert_path = test_util.vector_path('ocsp_certificate.pem')
|
||||
|
||||
from certbot import ocsp
|
||||
result = ocsp._determine_ocsp_server(cert_path)
|
||||
self.assertEqual(('http://ocsp.digicert.com', 'ocsp.digicert.com'), result)
|
||||
self.assertEqual(('http://ocsp.test4.buypass.com', 'ocsp.test4.buypass.com'), result)
|
||||
|
||||
@mock.patch('certbot.ocsp.logger')
|
||||
@mock.patch('certbot.util.run_script')
|
||||
@@ -128,8 +129,8 @@ class OSCPTestCryptography(unittest.TestCase):
|
||||
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')
|
||||
self.cert_path = test_util.vector_path('ocsp_certificate.pem')
|
||||
self.chain_path = test_util.vector_path('ocsp_issuer_certificate.pem')
|
||||
|
||||
@mock.patch('certbot.ocsp._determine_ocsp_server')
|
||||
@mock.patch('certbot.ocsp._check_ocsp_cryptography')
|
||||
@@ -139,91 +140,140 @@ class OSCPTestCryptography(unittest.TestCase):
|
||||
|
||||
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)
|
||||
def test_revoke(self):
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL):
|
||||
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)
|
||||
def test_responder_is_issuer(self):
|
||||
issuer = x509.load_pem_x509_certificate(
|
||||
test_util.load_vector('ocsp_issuer_certificate.pem'), default_backend())
|
||||
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED,
|
||||
ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks:
|
||||
mocks['mock_response'].return_value.responder_name = issuer.subject
|
||||
self.checker.ocsp_revoked(self.cert_path, self.chain_path)
|
||||
# Here responder and issuer are the same. So only the signature of the OCSP
|
||||
# response is checked (using the issuer/responder public key).
|
||||
self.assertEqual(mocks['mock_check'].call_count, 1)
|
||||
self.assertEqual(mocks['mock_check'].call_args[0][0].public_numbers(),
|
||||
issuer.public_key().public_numbers())
|
||||
|
||||
def test_responder_is_authorized_delegate(self):
|
||||
issuer = x509.load_pem_x509_certificate(
|
||||
test_util.load_vector('ocsp_issuer_certificate.pem'), default_backend())
|
||||
responder = x509.load_pem_x509_certificate(
|
||||
test_util.load_vector('ocsp_responder_certificate.pem'), default_backend())
|
||||
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED,
|
||||
ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks:
|
||||
self.checker.ocsp_revoked(self.cert_path, self.chain_path)
|
||||
# Here responder and issuer are not the same. Two signatures will be checked then,
|
||||
# first to verify the responder cert (using the issuer public key), second to
|
||||
# to verify the OCSP response itself (using the responder public key).
|
||||
self.assertEqual(mocks['mock_check'].call_count, 2)
|
||||
self.assertEqual(mocks['mock_check'].call_args_list[0][0][0].public_numbers(),
|
||||
issuer.public_key().public_numbers())
|
||||
self.assertEqual(mocks['mock_check'].call_args_list[1][0][0].public_numbers(),
|
||||
responder.public_key().public_numbers())
|
||||
|
||||
def test_revoke_resiliency(self):
|
||||
# Server return an invalid HTTP response
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL,
|
||||
http_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)
|
||||
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.UNAUTHORIZED):
|
||||
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)
|
||||
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL):
|
||||
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)):
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL):
|
||||
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)
|
||||
|
||||
# OCSP response uses an unsupported signature.
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL,
|
||||
check_signature_side_effect=UnsupportedAlgorithm('foo')):
|
||||
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)
|
||||
|
||||
# OSCP signature response is invalid.
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL,
|
||||
check_signature_side_effect=InvalidSignature('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)
|
||||
|
||||
# Assertion error on OCSP response validity
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL,
|
||||
check_signature_side_effect=AssertionError('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)
|
||||
|
||||
# No responder cert in OCSP response
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED,
|
||||
ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks:
|
||||
mocks['mock_response'].return_value.certificates = []
|
||||
revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path)
|
||||
self.assertFalse(revoked)
|
||||
|
||||
# Responder cert is not signed by certificate issuer
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED,
|
||||
ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks:
|
||||
cert = mocks['mock_response'].return_value.certificates[0]
|
||||
mocks['mock_response'].return_value.certificates[0] = mock.Mock(
|
||||
issuer='fake', subject=cert.subject)
|
||||
revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path)
|
||||
self.assertFalse(revoked)
|
||||
|
||||
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL):
|
||||
# This mock is necessary to avoid the first call contained in _determine_ocsp_server
|
||||
# of the method cryptography.x509.Extensions.get_extension_for_class.
|
||||
with mock.patch('certbot.ocsp._determine_ocsp_server') as mock_server:
|
||||
mock_server.return_value = ('https://example.com', 'example.com')
|
||||
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)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _ocsp_mock(certificate_status, response_status,
|
||||
http_status_code=200, check_signature_side_effect=None):
|
||||
with mock.patch('certbot.ocsp.ocsp.load_der_ocsp_response') as mock_response:
|
||||
mock_response.return_value = _construct_mock_ocsp_response(
|
||||
certificate_status, response_status)
|
||||
with mock.patch('certbot.ocsp.requests.post') as mock_post:
|
||||
mock_post.return_value = mock.Mock(status_code=http_status_code)
|
||||
with mock.patch('certbot.ocsp.crypto_util.verify_signed_payload') as mock_check:
|
||||
if check_signature_side_effect:
|
||||
mock_check.side_effect = check_signature_side_effect
|
||||
yield {
|
||||
'mock_response': mock_response,
|
||||
'mock_post': mock_post,
|
||||
'mock_check': mock_check,
|
||||
}
|
||||
|
||||
|
||||
def _construct_mock_ocsp_response(certificate_status, response_status):
|
||||
cert = x509.load_pem_x509_certificate(
|
||||
test_util.load_vector('google_certificate.pem'), default_backend())
|
||||
test_util.load_vector('ocsp_certificate.pem'), default_backend())
|
||||
issuer = x509.load_pem_x509_certificate(
|
||||
test_util.load_vector('google_issuer_certificate.pem'), default_backend())
|
||||
test_util.load_vector('ocsp_issuer_certificate.pem'), default_backend())
|
||||
responder = x509.load_pem_x509_certificate(
|
||||
test_util.load_vector('ocsp_responder_certificate.pem'), default_backend())
|
||||
builder = ocsp_lib.OCSPRequestBuilder()
|
||||
builder = builder.add_certificate(cert, issuer, hashes.SHA1())
|
||||
request = builder.build()
|
||||
@@ -234,6 +284,8 @@ def _construct_mock_ocsp_response(certificate_status, response_status):
|
||||
serial_number=request.serial_number,
|
||||
issuer_key_hash=request.issuer_key_hash,
|
||||
issuer_name_hash=request.issuer_name_hash,
|
||||
responder_name=responder.subject,
|
||||
certificates=[responder],
|
||||
hash_algorithm=hashes.SHA1(),
|
||||
next_update=datetime.now() + timedelta(days=1),
|
||||
this_update=datetime.now() - timedelta(days=1),
|
||||
|
||||
41
certbot/tests/testdata/google_certificate.pem
vendored
41
certbot/tests/testdata/google_certificate.pem
vendored
@@ -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-----
|
||||
@@ -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-----
|
||||
37
certbot/tests/testdata/ocsp_certificate.pem
vendored
Normal file
37
certbot/tests/testdata/ocsp_certificate.pem
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGYDCCBEigAwIBAgIKcjrC4hZcebbtODANBgkqhkiG9w0BAQsFADBRMQswCQYD
|
||||
VQQGEwJOTzEdMBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIzAhBgNVBAMM
|
||||
GkJ1eXBhc3MgQ2xhc3MgMiBUZXN0NCBDQSA1MB4XDTE5MDUxMjE1NTgyMVoXDTE5
|
||||
MTEwODIyNTkwMFowADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK9P
|
||||
b+YhJPypm4ui+AZUHPrJ6IsB9R/6Wvgec2G/GuW/UNQFktIhU10HOHAbiJeYLqNZ
|
||||
1Cia8JD6NXXGbprOjIbZWvjulYTaLSlClcK0H7HZrcgrK60OeIGEtur27ga68RML
|
||||
hs1FG7TNyWVysifOtwW9Oo1mZQQtxViiE2Yb+Q4QqIxitnbrnFmKrVJSUHVXi8/I
|
||||
BK1yLrJiRBZMIw0wvAWcWEG2Gpp9PAbemlb11Zx8sm/RSGh7u60rmETbB2Pu941s
|
||||
XJCSQRtq5yKdtjIJTIgbe12SPkknqTqa3aUh7hgho0IymlDSeeocL60SUiUAsPEr
|
||||
QRWleodOR1ChXz5mFokCAwEAAaOCAokwggKFMAkGA1UdEwQCMAAwHwYDVR0jBBgw
|
||||
FoAUd9nQBpFm2N0ZJo1JrNowL2p7YrEwHQYDVR0OBBYEFExS23I6sLCeO6KIxzoc
|
||||
tr9s+HmiMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
|
||||
BQUHAwIwIAYDVR0gBBkwFzALBglghEIBGgEAAgcwCAYGZ4EMAQIBMEIGA1UdHwQ7
|
||||
MDkwN6A1oDOGMWh0dHA6Ly9jcmwudGVzdDQuYnV5cGFzcy5uby9jcmwvQlBDbGFz
|
||||
czJUNENBNS5jcmwwIQYDVR0RAQH/BBcwFYITYnV5cGFzcy5wYWNhbGlzLm5ldDB4
|
||||
BggrBgEFBQcBAQRsMGowKQYIKwYBBQUHMAGGHWh0dHA6Ly9vY3NwLnRlc3Q0LmJ1
|
||||
eXBhc3MuY29tMD0GCCsGAQUFBzAChjFodHRwOi8vY3J0LnRlc3Q0LmJ1eXBhc3Mu
|
||||
bm8vY3J0L0JQQ2xhc3MyVDRDQTUuY2VyMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDw
|
||||
AHYAsMyD5aX5fWuvfAnMKEkEhyrH6IsTLGNQt8b9JuFsbHcAAAFqrMQ/cQAABAMA
|
||||
RzBFAiEA1oWB4c6q7+tqGA4HhLNACOemr9c2aIUuWxeQE7/PlSYCIEolZ7pWVs1J
|
||||
VyQW/AqeuXGB7qScwUgLh9C1uOJoeRe6AHYAsMyD5aX5fWuvfAnMKEkEhyrH6IsT
|
||||
LGNQt8b9JuFsbHcAAAFqrMQ/cQAABAMARzBFAiAoLaNvIwMDifsDAXJBsAKHlYx7
|
||||
QPLXL8onYKm8f+Sf1wIhAMepo2GX84UR7WtooqzkBZLG+PaBy1zMuUAG6mwnroF9
|
||||
MA0GCSqGSIb3DQEBCwUAA4ICAQAPWLdjNS5lLL5SEtghYebtDmNj2968NYSDvb1L
|
||||
1/uFwg3LCVRR1Xb3z1Hc/sc1W0IFXU0zOqEQiuP8jkVP7UqkaWuK5Eu0eP0zPI83
|
||||
WBZM0+eBwxwzIMK/Q7fYKTu1+vg/FlH0WhtV43DQSik66366zvPi2Tfag9IPvRei
|
||||
DOjbSOBF0o4er2oCrtI0lK5YrHOdWtD7xwQIuA606P9ucuufMf+JcmduRJsVZ2Zu
|
||||
3K32SMDdAnyjvQWZNbt1ex3G8vuFQEi690UBhPcha/SO8QvLS89wcaLJnyMIWdv7
|
||||
54cbw+fa1nLKM7qph6Mk1yb0qpomPqLmKw4T6WX36c0vDlFSpexJLGgWDFqLUxPN
|
||||
qV7cJz4mi1qaYfdWXRrnyU4bl55pHTTgEzbohV7apsmytkCe1uFNrpcTh8jzAhGN
|
||||
PQqarX9UoESR56B/ufbBGlBWi0pkV49BFks6Ue0GVKo7djoxuV6+SsmYSE+6MNPv
|
||||
IUsm54TSnwxjA8WyG7pl14g1hkGFQ4NRYJMiVqK3DMABaPxVmT7NRxUQQiM0mmM7
|
||||
EKNzLBeWHJF5ecdDR1MiIF3ayn+RiZb0r8aSQBMLwN1YwUZw+hSYz1eCd7bHN1gC
|
||||
1ksxP61f8LBz0SwDoyOTr8wY++wqF26KfoYuKQ3LjLeHvuUtL3EMnAhiyuej8ZOZ
|
||||
22spng==
|
||||
-----END CERTIFICATE-----
|
||||
38
certbot/tests/testdata/ocsp_issuer_certificate.pem
vendored
Normal file
38
certbot/tests/testdata/ocsp_issuer_certificate.pem
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
22spng==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
PJrUUjM8OQ==
|
||||
-----END CERTIFICATE-----
|
||||
27
certbot/tests/testdata/ocsp_responder_certificate.pem
vendored
Normal file
27
certbot/tests/testdata/ocsp_responder_certificate.pem
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEpjCCAo6gAwIBAgINARMIGYlEsD1LTt6D7zANBgkqhkiG9w0BAQsFADBRMQsw
|
||||
CQYDVQQGEwJOTzEdMBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIzAhBgNV
|
||||
BAMMGkJ1eXBhc3MgQ2xhc3MgMiBUZXN0NCBDQSA1MB4XDTE5MDQwNTEwMDAwMFoX
|
||||
DTE5MDcwNDEwMDAwMFowSTELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3Mg
|
||||
QVMtOTgzMTYzMzI3MRswGQYDVQQDDBJCdXlwYXNzIFRlc3Q0IE9DU1AwggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKGF+kYNd1fbhYT7Vf9xouZlx+4w45
|
||||
Y5EowPoaSKFo4uUDDxkj4PwmMiH4w9Q2bGrCbZRrDrvlNVY/kwzLu4CIk6Ip0dgm
|
||||
VZGNFB3Xo9nai7rI5pn/YVvVnDIQXh1LRbekzLVyHvhRgMpRb19xN/iYsxaOJDph
|
||||
8eAgbTKf6eitvfbvn/zXHj4KGKycuULI4+mwlfV3uioT4ulbT7PTVJetgi/XXFDO
|
||||
xMjbqx6I1ZMmzKJ6LNaFlfx6GdZsaLRDCidHzGp8Fm4ZdV+UPvMZcVDQO6rvQ3wU
|
||||
iGyCqgfE5e0aFvfeLoBPBtaoT0Ht1CvGdTfVet6PXrF6gh40fdEH5Ob5AgMBAAGj
|
||||
gYQwgYEwCQYDVR0TBAIwADAfBgNVHSMEGDAWgBR32dAGkWbY3RkmjUms2jAvanti
|
||||
sTAdBgNVHQ4EFgQU3VlR+sSIVpmXklieP7IlpVUcXIowDgYDVR0PAQH/BAQDAgeA
|
||||
MBMGA1UdJQQMMAoGCCsGAQUFBwMJMA8GCSsGAQUFBzABBQQCBQAwDQYJKoZIhvcN
|
||||
AQELBQADggIBAFBRLVsBadNFAoFi0HOrfxYsiqggZGJLlgxGyi/0NBIgduG4kcpM
|
||||
THvplwBwMQEqyp5511pSEbLPAFj8EqC5c46hXZXmT49xlfRvr2Bo+qtTPV9szuWr
|
||||
8muEIejwRrkATpqWPZWR2zVTXfB90mU2oGuRvxUVmnW4v+FrCChJo7+9yTocZJKx
|
||||
p4vxYfPMeggomdGAAUz94+0ppSjOLDzs3MA8uOcR0zJ2Y7UHb7PBf/HiM3GO2uKB
|
||||
sRgdDaGIf/PNpav0xJ/abGNNNwvXzHiMgqqImsuv/JoncPQWbClNurhXpdN7xt9C
|
||||
HcLX2AdggabcogjWm4guBFuFTsL1i0l8Bsu/6iPJ7ddCeANfYzf7h6AcQq12uFl3
|
||||
070F29DtPh8D3FPWgRZZsxoANFjXErxfj4a4+DR+jhhkb9YM/wI0vCOM7W6PKxVn
|
||||
ZK5kHGOQTcQMj7RCX52gEf27M33zC7HVam+kKhGvwq7D9Bs5hZclzcbjpR4eIxT7
|
||||
tzuiy5VpPh1DRLPrphPUB4xsA1dy6zbkg8OqddG6NxD++ja/iZyzSB3SeWyO02qA
|
||||
QoK2FzDasxpZ9rT3ioAcms3wVNe4lcd4OP8gHZONuat/gvxk6OZvAld6cnIrQZYB
|
||||
Tbu89ZWvhsyI3p4YC/15pUvA95j9Y0te+G+CF22Eoyb+rtz6mMletnUB
|
||||
-----END CERTIFICATE-----
|
||||
Reference in New Issue
Block a user