commit 9ce8d2481a42dff048980eb1f312000c2805e314
parent ca1a0a62e6af6a49d61c46e6946ed34345ba4c1c
Author: Solderpunk <solderpunk@sdf.org>
Date: Sun, 17 May 2020 20:38:06 +0200
Use cryptography library to do better certificate checking, if it's available.
Diffstat:
M | av98.py | | | 29 | ++++++++++++++++++++++++++++- |
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git 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