CRL verify: skip unknown URI schemes like ldap:// and add unit tests (#1027)
This commit is contained in:
parent
bb54085c20
commit
99b10c436a
|
@ -7,7 +7,7 @@
|
||||||
"""
|
"""
|
||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
from requests.exceptions import ConnectionError
|
from requests.exceptions import ConnectionError, InvalidSchema
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
|
||||||
|
@ -69,6 +69,9 @@ def crl_verify(cert_path):
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
raise Exception("Unable to retrieve CRL: {0}".format(point))
|
raise Exception("Unable to retrieve CRL: {0}".format(point))
|
||||||
|
except InvalidSchema:
|
||||||
|
# Unhandled URI scheme (like ldap://); skip this distribution point.
|
||||||
|
continue
|
||||||
except ConnectionError:
|
except ConnectionError:
|
||||||
raise Exception("Unable to retrieve CRL: {0}".format(point))
|
raise Exception("Unable to retrieve CRL: {0}".format(point))
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import datetime
|
||||||
import pytest
|
import pytest
|
||||||
|
from cryptography import x509
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from flask_principal import identity_changed, Identity
|
from flask_principal import identity_changed, Identity
|
||||||
|
|
||||||
from lemur import create_app
|
from lemur import create_app
|
||||||
from lemur.database import db as _db
|
from lemur.database import db as _db
|
||||||
from lemur.auth.service import create_token
|
from lemur.auth.service import create_token
|
||||||
|
from lemur.tests.vectors import PRIVATE_KEY_STR
|
||||||
|
|
||||||
from .factories import ApiKeyFactory, AuthorityFactory, NotificationFactory, DestinationFactory, \
|
from .factories import ApiKeyFactory, AuthorityFactory, NotificationFactory, DestinationFactory, \
|
||||||
CertificateFactory, UserFactory, RoleFactory, SourceFactory, EndpointFactory, RotationPolicyFactory
|
CertificateFactory, UserFactory, RoleFactory, SourceFactory, EndpointFactory, RotationPolicyFactory
|
||||||
|
@ -193,3 +199,19 @@ def logged_in_admin(session, app):
|
||||||
with app.test_request_context():
|
with app.test_request_context():
|
||||||
identity_changed.send(current_app._get_current_object(), identity=Identity(2))
|
identity_changed.send(current_app._get_current_object(), identity=Identity(2))
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def private_key():
|
||||||
|
return load_pem_private_key(PRIVATE_KEY_STR.encode(), password=None, backend=default_backend())
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def cert_builder(private_key):
|
||||||
|
return (x509.CertificateBuilder()
|
||||||
|
.subject_name(x509.Name([x509.NameAttribute(x509.NameOID.COMMON_NAME, 'foo.com')]))
|
||||||
|
.issuer_name(x509.Name([x509.NameAttribute(x509.NameOID.COMMON_NAME, 'foo.com')]))
|
||||||
|
.serial_number(1)
|
||||||
|
.public_key(private_key.public_key())
|
||||||
|
.not_valid_before(datetime.datetime(2017, 12, 22))
|
||||||
|
.not_valid_after(datetime.datetime(2040, 1, 1)))
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import pytest
|
||||||
|
from cryptography import x509
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
from cryptography.hazmat.primitives import serialization, hashes
|
||||||
|
from cryptography.x509 import UniformResourceIdentifier
|
||||||
|
|
||||||
|
from lemur.certificates.verify import verify_string, crl_verify
|
||||||
|
from lemur.tests.vectors import INTERNAL_VALID_LONG_STR
|
||||||
|
from lemur.utils import mktempfile
|
||||||
|
|
||||||
|
|
||||||
|
def test_verify_simple_cert():
|
||||||
|
"""Simple certificate without CRL or OCSP."""
|
||||||
|
# Verification raises an exception for "unknown" if there are no means to verify it
|
||||||
|
with pytest.raises(Exception, match="Failed to verify"):
|
||||||
|
verify_string(INTERNAL_VALID_LONG_STR, '')
|
||||||
|
|
||||||
|
|
||||||
|
def test_verify_crl_unknown_scheme(cert_builder, private_key):
|
||||||
|
"""Unknown distribution point URI schemes should be ignored."""
|
||||||
|
ldap_uri = 'ldap://ldap.example.org/cn=Example%20Certificate%20Authority?certificateRevocationList;binary'
|
||||||
|
crl_dp = x509.DistributionPoint([UniformResourceIdentifier(ldap_uri)],
|
||||||
|
relative_name=None, reasons=None, crl_issuer=None)
|
||||||
|
cert = (cert_builder
|
||||||
|
.add_extension(x509.CRLDistributionPoints([crl_dp]), critical=False)
|
||||||
|
.sign(private_key, hashes.SHA256(), default_backend()))
|
||||||
|
|
||||||
|
with mktempfile() as cert_tmp:
|
||||||
|
with open(cert_tmp, 'wb') as f:
|
||||||
|
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
# Must not raise exception
|
||||||
|
crl_verify(cert_tmp)
|
||||||
|
|
||||||
|
|
||||||
|
def test_verify_crl_unreachable(cert_builder, private_key):
|
||||||
|
"""Unreachable CRL distribution point results in error."""
|
||||||
|
ldap_uri = 'http://invalid.example.org/crl/foobar.crl'
|
||||||
|
crl_dp = x509.DistributionPoint([UniformResourceIdentifier(ldap_uri)],
|
||||||
|
relative_name=None, reasons=None, crl_issuer=None)
|
||||||
|
cert = (cert_builder
|
||||||
|
.add_extension(x509.CRLDistributionPoints([crl_dp]), critical=False)
|
||||||
|
.sign(private_key, hashes.SHA256(), default_backend()))
|
||||||
|
|
||||||
|
with mktempfile() as cert_tmp:
|
||||||
|
with open(cert_tmp, 'wb') as f:
|
||||||
|
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
with pytest.raises(Exception, match="Unable to retrieve CRL:"):
|
||||||
|
crl_verify(cert_tmp)
|
Loading…
Reference in New Issue