Skip to content

Commit a145bf2

Browse files
committed
Allow additional critical extensions to be used during validate_path
Some certificates will contain critical extensions that certvalidator doesn't know about. If the caller knows those critical extensions, it can pass them into ValidationContext so that validate_path doesn't error when it gets to the critical extensions check.
1 parent fc82b79 commit a145bf2

File tree

2 files changed

+32
-17
lines changed

2 files changed

+32
-17
lines changed

certvalidator/context.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ class ValidationContext():
3131
# options include: "md2", "md5", "sha1"
3232
weak_hash_algos = None
3333

34+
# A set of unicode strings of critical extensions. If an intermediate certificate
35+
# has a critical extension not in this set, it will fail validation.
36+
critical_extensions = None
37+
3438
# A set of byte strings of the SHA-1 hashes of certificates that are whitelisted
3539
_whitelisted_certs = None
3640

@@ -102,7 +106,7 @@ class ValidationContext():
102106
def __init__(self, trust_roots=None, extra_trust_roots=None, other_certs=None,
103107
whitelisted_certs=None, moment=None, allow_fetching=False, crls=None,
104108
crl_fetch_params=None, ocsps=None, ocsp_fetch_params=None,
105-
revocation_mode="soft-fail", weak_hash_algos=None):
109+
revocation_mode="soft-fail", weak_hash_algos=None, additional_critical_extensions=None):
106110
"""
107111
:param trust_roots:
108112
If the operating system's trust list should not be used, instead
@@ -329,6 +333,31 @@ def __init__(self, trust_roots=None, extra_trust_roots=None, other_certs=None,
329333
else:
330334
weak_hash_algos = set(['md2', 'md5'])
331335

336+
supported_critical_extensions = set([
337+
'authority_information_access',
338+
'authority_key_identifier',
339+
'basic_constraints',
340+
'crl_distribution_points',
341+
'extended_key_usage',
342+
'freshest_crl',
343+
'key_identifier',
344+
'key_usage',
345+
'ocsp_no_check',
346+
'certificate_policies',
347+
'policy_mappings',
348+
'policy_constraints',
349+
'inhibit_any_policy',
350+
])
351+
if additional_critical_extensions is not None:
352+
if not isinstance(additional_critical_extensions, set):
353+
raise TypeError(pretty_message(
354+
'''
355+
additional_critical_extensions must be a set of unicode strings, not %s
356+
''',
357+
type_name(additional_critical_extensions)
358+
))
359+
supported_critical_extensions |= additional_critical_extensions
360+
332361
self.certificate_registry = CertificateRegistry(
333362
trust_roots,
334363
extra_trust_roots,
@@ -362,6 +391,7 @@ def __init__(self, trust_roots=None, extra_trust_roots=None, other_certs=None,
362391
self._revocation_mode = revocation_mode
363392
self._soft_fail_exceptions = []
364393
self.weak_hash_algos = weak_hash_algos
394+
self.critical_extensions = supported_critical_extensions
365395

366396
@property
367397
def crls(self):

certvalidator/validate.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -664,22 +664,7 @@ def _validate_path(validation_context, path, end_entity_name_override=None):
664664

665665
# Step 3 o
666666
# Check for critical unsupported extensions
667-
supported_extensions = set([
668-
'authority_information_access',
669-
'authority_key_identifier',
670-
'basic_constraints',
671-
'crl_distribution_points',
672-
'extended_key_usage',
673-
'freshest_crl',
674-
'key_identifier',
675-
'key_usage',
676-
'ocsp_no_check',
677-
'certificate_policies',
678-
'policy_mappings',
679-
'policy_constraints',
680-
'inhibit_any_policy',
681-
])
682-
unsupported_critical_extensions = cert.critical_extensions - supported_extensions
667+
unsupported_critical_extensions = cert.critical_extensions - validation_context.critical_extensions
683668
if unsupported_critical_extensions:
684669
raise PathValidationError(pretty_message(
685670
'''

0 commit comments

Comments
 (0)