Check valid before/after of external certs

verify_server_cert_validity() and verify_ca_cert_validity() now check
the validity time range of external certificates. The check fails if the
certificate is not valid yet or will expire in less than an hour.

Fixes: https://pagure.io/freeipa/issue/8142
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Christian Heimes 2019-12-10 12:46:14 +01:00
parent 3cae7f4ee6
commit d30dd52920
2 changed files with 35 additions and 0 deletions

View File

@ -19,6 +19,7 @@
from __future__ import absolute_import
import collections
import datetime
import logging
import os
import io
@ -918,12 +919,32 @@ class NSSDatabase:
if certname == nick:
self.delete_cert(nick)
def _verify_cert_validity(self, cert):
"""Common checks for cert validity
"""
utcnow = datetime.datetime.utcnow()
if cert.not_valid_before > utcnow:
raise ValueError(
f"not valid before {cert.not_valid_before} UTC is in the "
"future."
)
if cert.not_valid_after < utcnow:
raise ValueError(
f"has expired {cert.not_valid_after} UTC"
)
# make sure the cert does not expire during installation
if cert.not_valid_after + datetime.timedelta(hours=1) < utcnow:
raise ValueError(
f"expires in less than one hour ({cert.not_valid_after} UTC)"
)
def verify_server_cert_validity(self, nickname, hostname):
"""Verify a certificate is valid for a SSL server with given hostname
Raises a ValueError if the certificate is invalid.
"""
cert = self.get_cert(nickname)
self._verify_cert_validity(cert)
try:
self.run_certutil(
@ -947,6 +968,7 @@ class NSSDatabase:
def verify_ca_cert_validity(self, nickname, minpathlen=None):
cert = self.get_cert(nickname)
self._verify_cert_validity(cert)
if not cert.subject:
raise ValueError("has empty subject")

View File

@ -9,6 +9,7 @@ from ipapython import ipautil
from ipaplatform.osinfo import osinfo
CERTNICK = 'testcert'
CERTSAN = 'testcert.certdb.test'
if osinfo.id == 'fedora':
if osinfo.version_number >= (28,):
@ -33,6 +34,7 @@ def create_selfsigned(nssdb):
'-s', 'CN=testcert',
'-n', CERTNICK,
'-m', '365',
'--extSAN', f'dns:{CERTSAN}'
])
finally:
os.unlink(noisefile)
@ -242,3 +244,14 @@ def test_delete_cert_and_key():
assert len(nssdb.list_certs()) == 1
finally:
os.unlink(p12file)
def test_check_validity():
with NSSDatabase() as nssdb:
nssdb.create_db()
create_selfsigned(nssdb)
with pytest.raises(ValueError):
nssdb.verify_ca_cert_validity(CERTNICK)
nssdb.verify_server_cert_validity(CERTNICK, CERTSAN)
with pytest.raises(ValueError):
nssdb.verify_server_cert_validity(CERTNICK, 'invalid.example')