Compare commits

...

3 Commits

Author SHA1 Message Date
Brad Warren
1d0f25df4b add unrecognized 2020-05-26 16:43:30 -07:00
Brad Warren
8f79859b10 add note 2020-05-26 16:29:04 -07:00
Brad Warren
3734ae7b04 Propose interfaces 2020-05-26 16:25:55 -07:00
2 changed files with 68 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
"""Certbot client interfaces."""
import abc
import enum
import six
import zope.interface
@@ -589,6 +590,43 @@ class RenewableCert(object):
"""
@six.add_metaclass(abc.ABCMeta):
class OCSPResponse(object):
"""I'll have a real description someday."""
@abc.abstractproperty
def certificate_status(self):
"""Cert status
:rtype: OCSPCertStatus
"""
@abc.abstractproperty
def next_update(self):
"""Next update
:rtype: stdlib datetime thing
"""
@abc.abstractpoperty
def raw_bytes(self):
"""Raw bytes of the OCSP Response
:rtype: bytes
"""
class OCSPCertStatus(enum):
GOOD = 1
REVOKED = 2
UNRECOGNIZED = 3
"""There are other OCSP statuses, but we may not have code to recognize them yet."""
# Updater interfaces
#
# When "certbot renew" is run, Certbot will iterate over each lineage and check

View File

@@ -20,6 +20,7 @@ from acme.magic_typing import Optional
from acme.magic_typing import Tuple
from certbot import crypto_util
from certbot import errors
from certbot import interfaces
from certbot import util
from certbot.compat.os import getenv
from certbot.interfaces import RenewableCert # pylint: disable=unused-import
@@ -29,19 +30,23 @@ try:
# and signature_hash_algorithm attribute in OCSPResponse class
from cryptography.x509 import ocsp # pylint: disable=ungrouped-imports
getattr(ocsp.OCSPResponse, 'signature_hash_algorithm')
CRYPTOGRAPHY_OCSP_AVAILABLE = True
except (ImportError, AttributeError): # pragma: no cover
ocsp = None # type: ignore
CRYPTOGRAPHY_OCSP_AVAILABLE = False
logger = logging.getLogger(__name__)
class _CryptographyOCSPResponse(interfaces.OCSPResponse):
"""Cryptography implementation of given interface."""
class RevocationChecker(object):
"""This class figures out OCSP checking on this system, and performs it."""
def __init__(self, enforce_openssl_binary_usage=False):
self.broken = False
self.use_openssl_binary = enforce_openssl_binary_usage or not ocsp
self.use_openssl_binary = enforce_openssl_binary_usage or not CRYPTOGRAPHY_OCSP_AVAILABLE
if self.use_openssl_binary:
if not util.exe_exists("openssl"):
@@ -58,6 +63,29 @@ class RevocationChecker(object):
else:
self.host_args = lambda host: ["Host", host]
def ocsp_response_by_paths(self, cert_path, chain_path, timeout=10):
"""Obtains a validated OCSP response.
The OCSP response could have any cert status, however, if an
OCSP response is returned from this function, the caller knows
it is properly timestamped, signed, etc.
.. note:: This function currently works when cryptography is
used for OCSP. Whether a new enough version of crypography
with OCSP support is available can be checked through
CRYPTOGRAPHY_OCSP_AVAILABLE. If it is not available, None is
always returned by this function for now.
:param str cert_path: Certificate filepath
:param str chain_path: Certificate chain
:param int timeout: Timeout (in seconds) for the OCSP query
:returns: The OCSP response if it could be obtained and
validated, otherwise, None
:rtype: interfaces.OCSPResponse or None
"""
def ocsp_revoked(self, cert):
# type: (RenewableCert) -> bool
"""Get revoked status for a particular cert version.