diff --git a/utils/check_tlsa.py b/utils/check_tlsa.py new file mode 100755 index 00000000..556684c8 --- /dev/null +++ b/utils/check_tlsa.py @@ -0,0 +1,90 @@ +#!/usr/scripts/python.sh +# -*- coding: utf-8 -*- + +import sys +import ssl +import socket +import lc_ldap.shortcuts +import dns.resolver +from gestion.gen_confs.bind import TLSA + +socket.setdefaulttimeout(1) + + +def get_certificat(host, port): + host = str(host) + port = int(str(port)) + tls_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + if port == "25": + smtp = socket.socket() + smtp.connect((host, port)) + smtp.recv(4096) + smtp.send("EHLO localhost\n") + smtp.recv(4096) + smtp.send("STARTTLS\n") + smtp.recv(4096) + smtp = tls_context.wrap_socket(smtp, server_hostname=host) + cert = smtp.getpeercert(True) + smtp.close() + return cert, "der" + else: + sock = tls_context.wrap_socket(socket.socket(), server_hostname=host) + sock.connect((host, port)) + cert = sock.getpeercert(True) + sock.close() + return cert, "der" + + +def check_cert(cert, verbose=False): + + for hostname in cert['hostCert']: + for port in cert['portTCPin']: + try: + if not check_tlsa_record(hostname, port, 'tcp'): + print( + "Le certificat de %s:%s en tcp ne " % (hostname, port) + + "correspond pas a l'enregistrement TLSA." + ) + except socket.error: + if verbose: + print( + "Echec de la récupération du certificat de " + + "%s:%s, vérification passé" % (hostname, port) + ) + + +def check_tlsa_record(hostname, port, transport): + query_name = '_%s._%s.%s' % (port, transport, hostname) + try: + certificat, format = get_certificat(hostname, port) + answers = dns.resolver.query(query_name, 'TLSA') + for rdata in answers: + tlsa = TLSA( + "%s." % hostname, + port, + transport, + certificat, + rdata.usage, + rdata.mtype, + rdata.selector, + r_format=format + ) + if rdata.cert.encode("hex").upper() == tlsa.certhex.upper(): + return True + return False + except dns.resolver.NXDOMAIN: + return True + +if __name__ == '__main__': + if "-v" in sys.argv[1:]: + verbose = True + else: + verbose = False + + conn = lc_ldap.shortcuts.lc_ldap_admin() + + certificates = conn.search(u"objectClass=TLSACert") + + for certificate in certificates: + if 'machineCrans' in certificate.machine()["objectClass"]: + check_cert(certificate, verbose=verbose)