Commit bfcfd787 authored by Alexandre's avatar Alexandre
Browse files

[DoT] Raise exception on error + tests coverage

Do not print error, instead raise an exception that need to be caught.
The calling method will then decide if the error should be displayed or
not.
parent 588a1919
...@@ -704,6 +704,15 @@ for ip in ip_set: ...@@ -704,6 +704,15 @@ for ip in ip_set:
error("\"%s\" not a name or an IP address" % url) error("\"%s\" not a name or an IP address" % url)
except socket.gaierror: except socket.gaierror:
error("Could not resolve \"%s\"" % url) error("Could not resolve \"%s\"" % url)
except homer.ConnectionDOTException as e:
if not monitoring:
print(e, file=sys.stderr)
err = "Could not connect to \"%s\"" % url
if opts.connectTo is not None:
err += " on %s" % opts.connectTo
error(err)
else:
error(e)
except (homer.ConnectionException, homer.DOHException) as e: except (homer.ConnectionException, homer.DOHException) as e:
error(e) error(e)
if conn.dot and not conn.success: if conn.dot and not conn.success:
......
import sys
import io import io
import socket import socket
import signal import signal
...@@ -110,24 +111,35 @@ class ConnectionDOT(Connection): ...@@ -110,24 +111,35 @@ class ConnectionDOT(Connection):
signal.signal(signal.SIGALRM, homer.exceptions.timeout_connection) signal.signal(signal.SIGALRM, homer.exceptions.timeout_connection)
# contains a set of tuples ('ip address', 'error message')
errors = set()
i = 0
for addrinfo in addrinfo_set: for addrinfo in addrinfo_set:
if self.establish_session(addrinfo[0], addrinfo[1]): # catch the raised exceptions and store them in the error set
# if that the last element of the loop raises an exception
# it will also be catched, but in this case we are sure we can not
# establish a connection therefore we raise an exception containing
# a string with all the errors
try:
self.establish_session(addrinfo[0], addrinfo[1])
except homer.ConnectionDOTException as e:
errors.add((addrinfo[0][0], str(e)))
if self.verbose and self.connect_to is None:
print(e, file=sys.stderr)
# we tried all the resolved IPs
if i == (len(addrinfo_set) - 1):
if self.verbose and self.connect_to is None:
print("No other IP address")
# join all the errors into a single string
err = ', '.join( "%s: %s" % (e[0], e[1]) for e in errors)
raise homer.ConnectionDOTException(err)
if self.verbose and self.connect_to is None:
print("Could not connect to %s" % addrinfo[0][0])
print("Trying another IP address")
else:
self.success = True self.success = True
break break
if self.verbose and self.connect_to is None: i += 1
print("Could not connect to %s" % addrinfo[0][0])
print("Trying another IP address")
# we could not establish a connection
if not self.success:
# we tried all the resolved IPs
if self.verbose and self.connect_to is None:
print("No other IP address")
error = "Could not connect to \"%s\"" % self.server
if self.connect_to is not None:
error += " on %s" % self.connect_to
raise homer.ConnectionDOTException(error)
def establish_session(self, addr, sock_family): def establish_session(self, addr, sock_family):
"""Return True if a TLS session is established.""" """Return True if a TLS session is established."""
...@@ -162,26 +174,16 @@ class ConnectionDOT(Connection): ...@@ -162,26 +174,16 @@ class ConnectionDOT(Connection):
self.session.connect((addr)) self.session.connect((addr))
self.session.do_handshake() self.session.do_handshake()
except homer.exceptions.TimeoutConnectionError: except homer.exceptions.TimeoutConnectionError:
if self.verbose: raise homer.ConnectionDOTException("Timeout")
print("Timeout")
return False
except OSError: except OSError:
if self.verbose: raise homer.ConnectionDOTException("Cannot connect")
print("Cannot connect")
return False
except OpenSSL.SSL.SysCallError as e: except OpenSSL.SSL.SysCallError as e:
if self.verbose: raise homer.ConnectionDOTException("OpenSSL error: %s" % e.args[1])
print("OpenSSL error: %s" % e.args[1], file=sys.stderr)
return False
except OpenSSL.SSL.ZeroReturnError: except OpenSSL.SSL.ZeroReturnError:
# see #18 # see #18
if self.verbose: raise homer.ConnectionDOTException("Error: The SSL connection has been closed (try with --nosni to avoid sending SNI ?)")
print("Error: The SSL connection has been closed (try with --nosni to avoid sending SNI ?)", file=sys.stderr)
return False
except OpenSSL.SSL.Error as e: except OpenSSL.SSL.Error as e:
if self.verbose: raise homer.ConnectionDOTException("OpenSSL error: %s" % ', '.join(err[0][2] for err in e.args))
print("OpenSSL error: %s" % ', '.join(err[0][2] for err in e.args), file=sys.stderr)
return False
# RFC 7858, section 4.2 and appendix A # RFC 7858, section 4.2 and appendix A
self.cert = self.session.get_peer_certificate() self.cert = self.session.get_peer_certificate()
...@@ -201,12 +203,10 @@ class ConnectionDOT(Connection): ...@@ -201,12 +203,10 @@ class ConnectionDOT(Connection):
if self.key is None: if self.key is None:
valid = homer.validate_hostname(self.check_name_cert, self.cert) valid = homer.validate_hostname(self.check_name_cert, self.cert)
if not valid: if not valid:
error("Certificate error: \"%s\" is not in the certificate" % (self.check_name_cert), exit=False) raise homer.ConnectionDOTException("Certificate error: \"%s\" is not in the certificate" % (self.check_name_cert))
return False
else: else:
if key_string != self.key: if key_string != self.key:
error("Key error: expected \"%s\", got \"%s\"" % (self.key, key_string), exit=False) raise homer.ConnectionDOTException("Key error: expected \"%s\", got \"%s\"" % (self.key, key_string))
return False
# restore the timer # restore the timer
signal.alarm(0) signal.alarm(0)
......
...@@ -868,6 +868,20 @@ tests: ...@@ -868,6 +868,20 @@ tests:
stderr: '' stderr: ''
partstdout: 'Cannot find' partstdout: 'Cannot find'
- exe: './check_dot'
name: '[check_dot] Certificate error'
markers:
- 'dot'
- 'monitoring'
- 'exception'
args:
- '-H'
- 'doh.bortzmeyer.fr'
- '-n'
- 'dnsforum.bj'
retcode: 2
partstdout: 'certificate'
################################################################################ ################################################################################
...@@ -1054,6 +1068,20 @@ tests: ...@@ -1054,6 +1068,20 @@ tests:
stderr: '' stderr: ''
partstdout: 'Cannot find' partstdout: 'Cannot find'
- exe: './check_doh'
name: '[check_doh] Certificate error'
markers:
- 'doh'
- 'monitoring'
- 'exception'
args:
- '-H'
- 'dot.bortzmeyer.fr'
- '-n'
- 'dnsforum.bj'
retcode: 2
partstdout: 'certificate'
################################################################################ ################################################################################
- exe: './homer.py' - exe: './homer.py'
......
Markdown is supported
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