Commit 21f38e4b authored by Vincent Pelletier's avatar Vincent Pelletier

client: Fix CA and CRL update when a CA is expired.

Otherwise, the expired CA causes an error when it is being loaded, before
the time comparison.
Also, CRL signed by that CA also causes an error (as its signature cannot
be checked).
Catch these errors so the corresponding unusable PEMs are discarded.
parent f7d8281d
0.9.10 (not released yet)
0.9.10 (2021-04-07)
===================
* Properly handle present but expired CA certificates.
* Properly handle CRLs whose CA certificate is missing.
* Add caucase.client.CaucaseClient.close method.
0.9.9 (2021-03-02)
......
......@@ -22,7 +22,6 @@
Caucase - Certificate Authority for Users, Certificate Authority for SErvices
"""
from __future__ import absolute_import
import datetime
import httplib
import json
import ssl
......@@ -31,6 +30,7 @@ from cryptography import x509
from cryptography.hazmat.backends import default_backend
import cryptography.exceptions
import pem
from . import exceptions
from . import utils
from . import version
......@@ -96,12 +96,14 @@ class CaucaseClient(object):
loaded_ca_pem_list = utils.getCertList(ca_crt_path)
else:
updated = False
now = datetime.datetime.utcnow()
ca_pem_list = [
x
for x in loaded_ca_pem_list
if utils.load_ca_certificate(x).not_valid_after > now
]
ca_pem_list = []
for loaded_ca_pem in loaded_ca_pem_list:
try:
utils.load_ca_certificate(loaded_ca_pem)
except exceptions.CertificateVerificationError:
continue
else:
ca_pem_list.append(loaded_ca_pem)
with cls(ca_url=url, ca_crt_pem_list=ca_pem_list) as client:
ca_pem_list.extend(client.getCACertificateChain())
if ca_pem_list != loaded_ca_pem_list:
......@@ -126,14 +128,19 @@ class CaucaseClient(object):
Return whether an update happened.
"""
def _asCRLDict(crl_list):
return {
utils.getAuthorityKeyIdentifier(utils.load_crl(x, ca_list)): x
for x in crl_list
}
def _asCRLDict(crl_pem_list):
result = {}
for crl_pem in crl_pem_list:
try:
crl = utils.load_crl(crl_pem, ca_list)
except cryptography.exceptions.InvalidSignature:
continue
else:
result[utils.getAuthorityKeyIdentifier(crl)] = crl_pem
return result
local_crl_list = utils.getCRLList(crl_path)
try:
local_crl_dict = _asCRLDict(crl_list=local_crl_list)
local_crl_dict = _asCRLDict(crl_pem_list=local_crl_list)
except x509.extensions.ExtensionNotFound:
# BBB: caucased used to issue CRLs without the AuthorityKeyIdentifier
# extension. In such case, local CRLs need to be replaced.
......
......@@ -55,6 +55,7 @@ import unittest
from urllib import quote, urlencode
import urlparse
from cryptography import x509
import cryptography.exceptions
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from caucase import cli
......@@ -1745,6 +1746,25 @@ class CaucaseTest(unittest.TestCase):
[old_cau_pem, new_cau_pem],
)
self._startServer()
# The old CA certificate is properly expired
self.assertRaises(
exceptions.CertificateVerificationError,
utils.load_ca_certificate,
old_cau_pem,
)
# Loading the CRL signed by the old CA certificate fails
new_cau = utils.load_ca_certificate(new_cau_pem)
try:
for crl_pem in (crl_pem_a, crl_pem_b):
utils.load_crl(crl_pem, [new_cau])
except cryptography.exceptions.InvalidSignature:
pass
else:
raise AssertionError(
'cryptography.exceptions.InvalidSignature was not raised',
)
# CA renewal works
updateCAFile()
# Non-renewed user certificate is rejected
self.assertRaises(CaucaseError, _checkUserAccess, user_key_path)
# Revoked and non-renewed user certificate is rejected
......@@ -1755,7 +1775,7 @@ class CaucaseTest(unittest.TestCase):
_checkUserAccess(user3_key)
# A client without established trust anchor only gets valid CA certs.
os.unlink(self._client_user_ca_crt)
self._runClient('--mode', 'user')
self._runClient('--mode', 'user', '--update-user')
self.assertItemsEqual(
[new_cau_pem],
utils.getCertList(self._client_user_ca_crt),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment