Commit bbffbc9d authored by Alexandre's avatar Alexandre
Browse files

Separate connection class into DoT & DoH classes

parent d3a25ecf
......@@ -180,14 +180,19 @@ class Connection:
else:
self.check = self.server
self.dot = dot
if not self.dot:
self.post = post
self.head = head
if self.dot:
self.hasher = hashlib.sha256()
self.verbose = verbose
self.insecure = insecure
if self.dot:
def __str__(self):
return self.server
class ConnectionDoT(Connection):
def __init__(self, server, servername=None, connect=None, forceIPv4=False, forceIPv6=False,
dot=False, verbose=verbose, insecure=insecure, post=post, head=head):
Connection.__init__(self, server, servername=servername, connect=connect,
forceIPv4=forceIPv4, forceIPv6=forceIPv6, dot=dot,
verbose=verbose, insecure=insecure, post=post, head=head)
if forceIPv4 and forceIPv6:
raise Exception("Force IPv4 *or* IPv6 but not both")
(is_addr, family) = is_valid_ip_address(self.server)
......@@ -201,6 +206,7 @@ class Connection:
family = socket.AF_INET6
else:
family = 0
self.hasher = hashlib.sha256()
addrinfo = socket.getaddrinfo(server, 853, family)
# May be loop over the results of getaddrinfo, to test all
# the IP addresses? See #13.
......@@ -221,7 +227,7 @@ class Connection:
OpenSSL.SSL.VERIFY_CLIENT_ONCE,
lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
self.session = OpenSSL.SSL.Connection(self.context, self.sock)
self.session.set_tlsext_host_name(canonicalize(check).encode()) # Server Name Indication (SNI)
self.session.set_tlsext_host_name(canonicalize(self.check).encode()) # Server Name Indication (SNI)
self.session.connect((self.addr))
# TODO We may here have exceptions such as OpenSSL.SSL.ZeroReturnError
self.session.do_handshake()
......@@ -239,10 +245,23 @@ class Connection:
print("Public key is pin-sha256=\"%s\"" % \
base64.standard_b64encode(self.digest).decode())
if not insecure:
valid = validate_hostname(check, self.cert)
valid = validate_hostname(self.check, self.cert)
if not valid:
error("Certificate error: \"%s\" is not in the certificate" % (check))
else: # DoH
error("Certificate error: \"%s\" is not in the certificate" % (self.check))
def end(self):
self.session.shutdown()
self.session.close()
class ConnectionDoH(Connection):
def __init__(self, server, servername=None, connect=None, forceIPv4=False, forceIPv6=False,
dot=False, verbose=verbose, insecure=insecure, post=post, head=head):
Connection.__init__(self, server, servername=servername, connect=connect,
forceIPv4=forceIPv4, forceIPv6=forceIPv6, dot=dot,
verbose=verbose, insecure=insecure, post=post, head=head)
self.post = post
self.head = head
self.curl = pycurl.Curl()
self.url = server
# Does not work if pycurl was not compiled with nghttp2 (recent Debian
......@@ -283,13 +302,8 @@ class Connection:
self.curl.setopt(pycurl.CONNECT_TO, ["::%s:" % repraddress,])
except AttributeError:
pass # Probably an old version of libcurl, without CONNECT_TO. It appeared with 7.49.0
def __str__(self):
return self.server
def end(self):
if self.dot:
self.session.shutdown()
self.session.close()
else: # DoH
self.curl.close()
# Routine doing one actual test. Returns a tuple, first member is a
......@@ -489,7 +503,12 @@ try:
extracheck = vhostname
else:
extracheck = None
conn = Connection(url, dot=dot, servername=extracheck, connect=connectTo, verbose=verbose,
if dot:
conn = ConnectionDoT(url, dot=dot, servername=extracheck, connect=connectTo, verbose=verbose,
forceIPv4=forceIPv4, forceIPv6=forceIPv6,
insecure=insecure, post=post, head=head)
else:
conn = ConnectionDoH(url, dot=dot, servername=extracheck, connect=connectTo, verbose=verbose,
forceIPv4=forceIPv4, forceIPv6=forceIPv6,
insecure=insecure, post=post, head=head)
except TimeoutError:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment