From 9ce8d2481a42dff048980eb1f312000c2805e314 Mon Sep 17 00:00:00 2001 From: Solderpunk Date: Sun, 17 May 2020 20:38:06 +0200 Subject: [PATCH] Use cryptography library to do better certificate checking, if it's available. --- av98.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/av98.py b/av98.py index 8512c51..d159603 100755 --- a/av98.py +++ b/av98.py @@ -25,6 +25,7 @@ import shutil import socket import sqlite3 import ssl +from ssl import CertificateError import subprocess import sys import tempfile @@ -38,6 +39,14 @@ try: except ModuleNotFoundError: import textwrap +try: + from cryptography import x509 + from cryptography.hazmat.backends import default_backend + _HAS_CRYPTOGRAPHY = True + _BACKEND = default_backend() +except ModuleNotFoundError: + _HAS_CRYPTOGRAPHY = False + _VERSION = "0.0.1" _MAX_REDIRECTS = 5 @@ -642,10 +651,28 @@ Slow internet connection? Use 'set timeout' to be more patient.""") return addresses def _validate_cert(self, address, host, cert): + + now = datetime.datetime.now() + if _HAS_CRYPTOGRAPHY: + # Using the cryptography module we can get detailed access + # to the properties of even self-signed certs, unlike in + # the standard ssl library... + c = x509.load_der_x509_certificate(cert, _BACKEND) + + # Check certificate validity dates + if c.not_valid_before >= now: + raise CertificateError("Certificate is not yet valid!") + elif c.not_valid_after <= now: + raise CertificateError("Certificate has expired!") + + # Check certificate hostname + # TODO: Check alternative names too + common_name = c.subject.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)[0].value + ssl._dnsname_match(common_name, host) + sha = hashlib.sha256() sha.update(cert) fingerprint = sha.hexdigest() - now = datetime.datetime.now() # Have we been here before? self.db_cur.execute("""SELECT fingerprint, first_seen, last_seen, count