Skip to content

Commit

Permalink
Use ssl to verify hostname
Browse files Browse the repository at this point in the history
This commit re-uses python 3's `ssl.match_hostname()` function to validate
hostname instead of relying on home grown algorithm.
  • Loading branch information
deathaxe committed Feb 3, 2024
1 parent 0c7ed39 commit 041d9ac
Showing 1 changed file with 7 additions and 38 deletions.
45 changes: 7 additions & 38 deletions package_control/http/validating_https_connection.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import base64
import hashlib
import os
import re
import socket
import ssl

Expand Down Expand Up @@ -73,38 +72,6 @@ def __init__(self, host, port=None, ca_certs=None, extra_ca_certs=None, **kwargs

self._context = context

def get_valid_hosts_for_cert(self, cert):
"""
Returns a list of valid hostnames for an SSL certificate
:param cert: A dict from SSLSocket.getpeercert()
:return: An array of hostnames
"""

if 'subjectAltName' in cert:
return [x[1] for x in cert['subjectAltName'] if x[0].lower() == 'dns']
else:
return [x[0][1] for x in cert['subject'] if x[0][0].lower() == 'commonname']

def validate_cert_host(self, cert, hostname):
"""
Checks if the cert is valid for the hostname
:param cert: A dict from SSLSocket.getpeercert()
:param hostname: A string hostname to check
:return: A boolean if the cert is valid for the hostname
"""

hosts = self.get_valid_hosts_for_cert(cert)
for host in hosts:
host_re = host.replace('.', r'\.').replace('*', r'[^.]*')
if re.search('^%s$' % (host_re,), hostname, re.I):
return True
return False

# Compatibility for python 3.3 vs 3.8
# python 3.8 replaced _set_hostport() by _get_hostport()
if not hasattr(DebuggableHTTPConnection, '_set_hostport'):
Expand Down Expand Up @@ -393,11 +360,13 @@ def connect(self):
if 'notAfter' in cert:
console_write(' expire date: %s', cert['notAfter'], prefix=False)

if not self.validate_cert_host(cert, hostname):
try:
ssl.match_hostname(cert, hostname)
if self.debuglevel == -1:
console_write(' Certificate INVALID', prefix=False)
console_write(' Certificate validated for %s', hostname, prefix=False)

raise InvalidCertificateException(hostname, cert, 'hostname mismatch')
except ssl.CertificateError as e:
if self.debuglevel == -1:
console_write(' Certificate INVALID: %s', e, prefix=False)

if self.debuglevel == -1:
console_write(' Certificate validated for %s', hostname, prefix=False)
raise InvalidCertificateException(hostname, cert, e)

0 comments on commit 041d9ac

Please sign in to comment.