about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
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,