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
self.success = True # if that the last element of the loop raises an exception
break # 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: if self.verbose and self.connect_to is None:
print("Could not connect to %s" % addrinfo[0][0]) print(e, file=sys.stderr)
print("Trying another IP address")
# we could not establish a connection
if not self.success:
# we tried all the resolved IPs # we tried all the resolved IPs
if i == (len(addrinfo_set) - 1):
if self.verbose and self.connect_to is None: if self.verbose and self.connect_to is None:
print("No other IP address") print("No other IP address")
# join all the errors into a single string
error = "Could not connect to \"%s\"" % self.server err = ', '.join( "%s: %s" % (e[0], e[1]) for e in errors)
if self.connect_to is not None: raise homer.ConnectionDOTException(err)
error += " on %s" % self.connect_to if self.verbose and self.connect_to is None:
raise homer.ConnectionDOTException(error) print("Could not connect to %s" % addrinfo[0][0])
print("Trying another IP address")
else:
self.success = True
break
i += 1
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