aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNguyễn Gia Phong <cnx@loang.net>2025-06-04 16:36:05 +0900
committerNguyễn Gia Phong <cnx@loang.net>2025-06-04 16:37:00 +0900
commit20766657a7146d7a36feebbb297dccd016a1406f (patch)
tree78493273cbb8f84cdb6e9a7e751e7461a64e0ee6 /src
parent11d05505cdf25b77cfbdf09f5f1d1be79eeaa0f3 (diff)
downloadscadere-20766657a7146d7a36feebbb297dccd016a1406f.tar.gz
Err on invalid cert fetch
Diffstat (limited to 'src')
-rw-r--r--src/scadere/check.py32
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,