#!/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)
