Skip to content

Commit

Permalink
CRL DPs for root CAs don't get an IDP, for intermediate CAs use the C…
Browse files Browse the repository at this point in the history
…A CRL url (see #64)
  • Loading branch information
mathiasertl committed Sep 5, 2020
1 parent d5bd177 commit b957de4
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
18 changes: 18 additions & 0 deletions ca/django_ca/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,24 @@ def get_crl(self, expires=86400, algorithm=None, password=None, scope=None, coun
if kwargs.get('full_name'):
full_name = kwargs['full_name']
full_name = [parse_general_name(n) for n in full_name]

# CRLs for root CAs with scope "ca" do not add an IssuingDistributionPoint extension by default. For
# full path validation with CRLs, the CRL is also used for validating the Root CA (which does not
# contain a CRL Distribution Point). But the Full Name in the CRL IDP and the CA CRL DP have to match.
# See also:
# https://github.com/mathiasertl/django-ca/issues/64
elif scope == 'ca' and self.parent is None:
full_name = None

# If CA_DEFAULT_HOSTNAME is set, CRLs with scope "ca" add the same URL in the IssuingDistributionPoint
# extension that is also added in the CRL Distribution Points extension for CAs issued by this CA.
# See also:
# https://github.com/mathiasertl/django-ca/issues/64
elif scope == 'ca':
crl_path = reverse('django_ca:ca-crl', kwargs={'serial': self.serial})
full_name = [x509.UniformResourceIdentifier(
'http://%s%s' % (settings.CA_DEFAULT_HOSTNAME, crl_path)
)]
elif self.crl_url:
crl_url = [url.strip() for url in self.crl_url.split()]
full_name = [x509.UniformResourceIdentifier(c) for c in crl_url]
Expand Down
15 changes: 14 additions & 1 deletion ca/django_ca/tests/tests_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def test_full_crl_tz(self):
@freeze_time('2019-04-14 12:26:00')
def test_ca_crl(self):
ca = self.cas['root']
idp = self.get_idp(full_name=self.get_idp_full_name(ca), only_contains_ca_certs=True)
idp = self.get_idp(only_contains_ca_certs=True) # root CAs don't have a full name (github issue #64)

crl = ca.get_crl(scope='ca').public_bytes(Encoding.PEM)
self.assertCRL(crl, idp=idp, signer=ca)
Expand All @@ -205,6 +205,19 @@ def test_ca_crl(self):
crl = ca.get_crl(scope='ca').public_bytes(Encoding.PEM)
self.assertCRL(crl, idp=idp, certs=[child_ca], crl_number=1, signer=ca)

@override_tmpcadir()
@freeze_time('2019-04-14 12:26:00')
def test_intermediate_ca_crl(self):
# Intermediate CAs have a DP in the CRL that has the CA url
ca = self.cas['child']
full_name = [x509.UniformResourceIdentifier(
'http://%s/django_ca/crl/ca/%s/' % (ca_settings.CA_DEFAULT_HOSTNAME, ca.serial)
)]
idp = self.get_idp(full_name=full_name, only_contains_ca_certs=True)

crl = ca.get_crl(scope='ca').public_bytes(Encoding.PEM)
self.assertCRL(crl, idp=idp, signer=ca)

@freeze_time('2019-04-14 12:26:00')
@override_tmpcadir()
def test_user_crl(self):
Expand Down
20 changes: 19 additions & 1 deletion ca/django_ca/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

from django.core.cache import cache
from django.test import Client
from django.urls import include
from django.urls import path
from django.urls import re_path
from django.urls import reverse

Expand All @@ -32,7 +34,10 @@
from .base import override_settings
from .base import override_tmpcadir

app_name = 'django_ca'
urlpatterns = [
path('django_ca/', include('django_ca.urls')),

re_path(r'^crl/(?P<serial>[0-9A-F:]+)/$', CertificateRevocationListView.as_view(), name='default'),
re_path(r'^full/(?P<serial>[0-9A-F:]+)/$', CertificateRevocationListView.as_view(scope=None),
name='full'),
Expand Down Expand Up @@ -103,7 +108,7 @@ def test_full_scope(self):
def test_ca_crl(self):
root = self.cas['root']
child = self.cas['child']
idp = self.get_idp(full_name=self.get_idp_full_name(root), only_contains_ca_certs=True)
idp = self.get_idp(only_contains_ca_certs=True) # root CAs don't have a full name (github issue #64)
self.assertIsNotNone(root.key(password=None))

response = self.client.get(reverse('ca_crl', kwargs={'serial': root.serial}))
Expand All @@ -127,6 +132,19 @@ def test_ca_crl(self):
self.assertEqual(response['Content-Type'], 'text/plain')
self.assertCRL(response.content, expires=600, idp=idp, certs=[child], crl_number=1, signer=root)

@override_tmpcadir()
def test_ca_crl_intermediate(self):
child = self.cas['child']
full_name = 'http://%s/django_ca/crl/ca/%s/' % (ca_settings.CA_DEFAULT_HOSTNAME, child.serial)
full_name = [x509.UniformResourceIdentifier(full_name)]
idp = self.get_idp(full_name=full_name, only_contains_ca_certs=True)
self.assertIsNotNone(child.key(password=None))

response = self.client.get(reverse('ca_crl', kwargs={'serial': child.serial}))
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'text/plain')
self.assertCRL(response.content, expires=600, idp=idp, signer=child)

@override_tmpcadir()
def test_password(self):
ca = self.cas['pwd']
Expand Down

0 comments on commit b957de4

Please sign in to comment.