Skip to content

Commit

Permalink
system: CRL/cert subject hash mismatch in certctl.py, closes #7993
Browse files Browse the repository at this point in the history
Since pyOpenSSL doesn't support generating hashses for CRL's, we calculated one with the functions available in the libraries.
Unfortunately X509Name doesn't seem to support duplicate attributes, causing mismatches on our end.

This commit replaces the previous logic with a direct call to openssl, although it's slower, it will deliver the expected outcome.
  • Loading branch information
AdSchellevis committed Oct 21, 2024
1 parent 3d34e7e commit e78e243
Showing 1 changed file with 11 additions and 9 deletions.
20 changes: 11 additions & 9 deletions src/opnsense/scripts/system/certctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import glob
import sys
import os
import subprocess
import warnings
warnings.filterwarnings('ignore', message='.*cryptography', )
import OpenSSL.crypto
Expand All @@ -43,26 +44,27 @@

def certificate_iterator(filename):
fext = os.path.splitext(filename)[1][1:].lower()
needs_copy = False
try:
if fext == 'crl':
x509_items = [x509.load_pem_x509_crl(open(filename, 'rb').read())]
x509_items = [filename]
elif fext in ['pem', 'cer', 'crt']:
x509_items = x509.load_pem_x509_certificates(open(filename, 'rb').read())
needs_copy = len(x509_items) > 1
else:
# not supported
return None
except (ValueError, TypeError):
return None

needs_copy = len(x509_items) > 1
for x509_item in x509_items:
data = x509_item.public_bytes(serialization.Encoding.PEM) if needs_copy else filename
# XXX: need to check subject_name_hash as below for crl does not offer the same results in all cases
if fext == 'crl':
tmp = OpenSSL.crypto.X509().get_issuer()
for item in x509_item.issuer:
setattr(tmp, item.rfc4514_attribute_name, item.value)
hashval = hex(tmp.hash()).lstrip('0x').zfill(8)
# XXX: pyOpenSSL doesn't offer access to subject_name_hash(), so we have to call openssl direct here
spparams = ['/usr/bin/openssl', 'crl', '-in', filename, '-hash', '-noout']
sp = subprocess.run(spparams, capture_output=True, text=True)
if sp.returncode != 0:
continue
hashval = sp.stdout
else:
cert = OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_PEM,
Expand All @@ -73,7 +75,7 @@ def certificate_iterator(filename):
'hash': hashval,
'target_pattern': '%s.%s%%d' % (hashval, 'r' if fext == 'crl' else ''),
'type': 'copy' if needs_copy else 'link',
'data': data,
'data': x509_item.public_bytes(serialization.Encoding.PEM) if needs_copy and x509_item else filename,
'filename': filename
}

Expand Down

0 comments on commit e78e243

Please sign in to comment.