Use special issuer values <selfsigned> and <unknown> in special cases
This way it's easy to find/distinguish selfsigned certificates stored in Lemur.
This commit is contained in:
@ -3,6 +3,8 @@ import unicodedata
|
||||
|
||||
from cryptography import x509
|
||||
from flask import current_app
|
||||
|
||||
from lemur.common.utils import is_selfsigned
|
||||
from lemur.extensions import sentry
|
||||
from lemur.constants import SAN_NAMING_TEMPLATE, DEFAULT_NAMING_TEMPLATE
|
||||
|
||||
@ -229,15 +231,22 @@ def issuer(cert):
|
||||
"""
|
||||
Gets a sane issuer slug from a given certificate, stripping non-alphanumeric characters.
|
||||
|
||||
:param cert:
|
||||
For self-signed certificates, the special value '<selfsigned>' is returned.
|
||||
If issuer cannot be determined, '<unknown>' is returned.
|
||||
|
||||
:param cert: Parsed certificate object
|
||||
:return: Issuer slug
|
||||
"""
|
||||
# If certificate is self-signed, we return a special value -- there really is no distinct "issuer" for it
|
||||
if is_selfsigned(cert):
|
||||
return '<selfsigned>'
|
||||
|
||||
# Try Common Name or fall back to Organization name
|
||||
attrs = (cert.issuer.get_attributes_for_oid(x509.OID_COMMON_NAME) or
|
||||
cert.issuer.get_attributes_for_oid(x509.OID_ORGANIZATION_NAME))
|
||||
if not attrs:
|
||||
current_app.logger.error("Unable to get issuer! Cert serial {:x}".format(cert.serial_number))
|
||||
return "Unknown"
|
||||
return '<unknown>'
|
||||
|
||||
return text_to_slug(attrs[0].value, '')
|
||||
|
||||
|
@ -11,9 +11,10 @@ import string
|
||||
|
||||
import sqlalchemy
|
||||
from cryptography import x509
|
||||
from cryptography.exceptions import InvalidSignature, UnsupportedAlgorithm
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa, ec
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa, ec, padding
|
||||
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
||||
from flask_restful.reqparse import RequestParser
|
||||
from sqlalchemy import and_, func
|
||||
@ -143,6 +144,40 @@ def generate_private_key(key_type):
|
||||
)
|
||||
|
||||
|
||||
def check_cert_signature(cert, issuer_public_key):
|
||||
"""
|
||||
Check a certificate's signature against an issuer public key.
|
||||
On success, returns None; on failure, raises UnsupportedAlgorithm or InvalidSignature.
|
||||
"""
|
||||
if isinstance(issuer_public_key, rsa.RSAPublicKey):
|
||||
# RSA requires padding, just to make life difficult for us poor developers :(
|
||||
if cert.signature_algorithm_oid == x509.SignatureAlgorithmOID.RSASSA_PSS:
|
||||
# In 2005, IETF devised a more secure padding scheme to replace PKCS #1 v1.5. To make sure that
|
||||
# nobody can easily support or use it, they mandated lots of complicated parameters, unlike any
|
||||
# other X.509 signature scheme.
|
||||
# https://tools.ietf.org/html/rfc4056
|
||||
raise UnsupportedAlgorithm("RSASSA-PSS not supported")
|
||||
else:
|
||||
padder = padding.PKCS1v15()
|
||||
issuer_public_key.verify(cert.signature, cert.tbs_certificate_bytes, padder, cert.signature_hash_algorithm)
|
||||
else:
|
||||
# EllipticCurvePublicKey or DSAPublicKey
|
||||
issuer_public_key.verify(cert.signature, cert.tbs_certificate_bytes, cert.signature_hash_algorithm)
|
||||
|
||||
|
||||
def is_selfsigned(cert):
|
||||
"""
|
||||
Returns True if the certificate is self-signed.
|
||||
Returns False for failed verification or unsupported signing algorithm.
|
||||
"""
|
||||
try:
|
||||
check_cert_signature(cert, cert.public_key())
|
||||
# If verification was successful, it's self-signed.
|
||||
return True
|
||||
except InvalidSignature:
|
||||
return False
|
||||
|
||||
|
||||
def is_weekend(date):
|
||||
"""
|
||||
Determines if a given date is on a weekend.
|
||||
|
Reference in New Issue
Block a user