diff options
author | Nguyễn Gia Phong <cnx@loang.net> | 2025-06-04 16:36:05 +0900 |
---|---|---|
committer | Nguyễn Gia Phong <cnx@loang.net> | 2025-06-04 16:37:00 +0900 |
commit | 20766657a7146d7a36feebbb297dccd016a1406f (patch) | |
tree | 78493273cbb8f84cdb6e9a7e751e7461a64e0ee6 /src | |
parent | 11d05505cdf25b77cfbdf09f5f1d1be79eeaa0f3 (diff) | |
download | scadere-20766657a7146d7a36feebbb297dccd016a1406f.tar.gz |
Err on invalid cert fetch
Diffstat (limited to 'src')
-rw-r--r-- | src/scadere/check.py | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/src/scadere/check.py b/src/scadere/check.py index aaabe3f..288e599 100644 --- a/src/scadere/check.py +++ b/src/scadere/check.py @@ -31,18 +31,19 @@ from . import __version__, GNUHelpFormatter, NetLoc __all__ = ['main'] -class CtlChrTrans: - """Translator for printing Unicode control characters.""" +def is_control_character(character): + """Check if a Unicode character belongs to the control category.""" + return unicode_category(character) == 'Cc' - def __getitem__(self, ordinal): - if unicode_category(chr(ordinal)) == 'Cc': - return 0xfffd # replacement character '�' - raise KeyError + +def printable(string): + """Check if the given Unicode string is printable.""" + return not any(map(is_control_character, string)) def base64_from_str(string): """Convert string to base64 format in bytes.""" - return base64(string.translate(CtlChrTrans()).encode()).decode() + return base64(string.encode()).decode() def check(netlocs, after, output, fake_ca=None): @@ -55,6 +56,7 @@ def check(netlocs, after, output, fake_ca=None): fake_ca.configure_trust(ctx) for hostname, port in netlocs: + now = datetime.now(tz=timezone.utc).isoformat(timespec='seconds') netloc = f'{hostname}:{port}' stderr.write(f'TLS certificate for {netloc} ') try: @@ -64,19 +66,27 @@ def check(netlocs, after, output, fake_ca=None): cert = conn.getpeercert() except Exception as exception: stderr.write(f'cannot be retrieved: {exception}\n') - now = datetime.now(tz=timezone.utc).isoformat() print(now, 'N/A', hostname, port, 'N/A', base64_from_str(str(exception)), file=output) - else: - ca = dict(chain.from_iterable(cert['issuer']))['organizationName'] + continue + + try: not_before = parsedate(cert['notBefore']) not_after = parsedate(cert['notAfter']) + ca = dict(chain.from_iterable(cert['issuer']))['organizationName'] + if not printable(ca): + raise ValueError(f'CA name contains control character: {ca!r}') + serial = int(cert['serialNumber'], 16) + except Exception as exception: + stderr.write(f'cannot be parsed: {exception}\n') + print(now, 'N/A', hostname, port, 'N/A', + base64_from_str(str(exception)), file=output) + else: if after < not_after: after_seconds = after.isoformat(timespec='seconds') stderr.write(f'will not expire at {after_seconds}\n') else: stderr.write(f'will expire at {not_after.isoformat()}\n') - serial = cert['serialNumber'].translate(CtlChrTrans()) print(not_before.isoformat(), not_after.isoformat(), # As unique identifier hostname, port, serial, |