diff --git a/gestion/gen_confs/bind.py b/gestion/gen_confs/bind.py index 669f0315..79a42d0a 100755 --- a/gestion/gen_confs/bind.py +++ b/gestion/gen_confs/bind.py @@ -7,9 +7,11 @@ Licence : GPLv3 """ import sys +import ssl import time import base64 import hashlib +import binascii import netaddr sys.path.append('/usr/scripts/') @@ -48,6 +50,62 @@ class ResourceRecord(object): def __repr__(self): return str(self) +class TLSA(ResourceRecord): + def __init__(self, name, port, proto, cert, certtype, reftype, compat=True, ttl=None): + """ + name: nom du domaine du certificat + port: port où écoute le service utilisant le certificat + proto: udp ou tcp + cert: le certificat au format pem (selector est donc toujours à 0) + certtype: type d'enregistrement 0 = CA pinning, 1 = cert pinning, 2 = self trusted CA, 3 = self trusted cert + reftype: 0 = plain cert, 1 = sha256, 2 = sha512 + compat: on génère un enregistement compris même par les serveurs dns n'implémentant pas TLSA + """ + selector = 0 + if cert is None and proto == 'tcp': + try: + cert = ssl.get_server_certificate((name[:-1], port)) + sys.stderr.write("Warning: it is not safe to retrive cert for %s through the network, consider using an other solution\n" % name[:-1]) + except Exception as e: + raise ValueError("Unable de retrieve cert dynamically: %s" % e) + elif cert is None: + raise ValueError("cert can only be retrive if proto is tcp") + dercert = ssl.PEM_cert_to_DER_cert(cert) + if not dercert: + raise ValueError("Impossible de convertir le certificat au format DER %s %s %s\n%s" % (name, port, proto, cert)) + certhex = TLSA.hashCert(reftype, dercert) + if compat: + super(TLSA, self).__init__( + 'TYPE52', + '_%s._%s%s' % (port, proto, '.' + name if name else ''), + "\# %s 0%s0%s0%s%s" % (len(certhex)/2 +3, certtype, selector, reftype, certhex), + ttl + ) + else: + super(TLSA, self).__init__( + 'TLSA', + '_%s._%s%s' % (port, proto, '.' + name if name else ''), + "%s %s %s %s"% (certtype, selector, reftype, certhex), + ttl + ) + + @staticmethod + def hashCert(reftype, certblob): + """ + certblob: un certificat au format DER + """ + if reftype == 0: + return binascii.b2a_hex(certblob).upper() + elif reftype == 1: + hashobj = hashlib.sha256() + hashobj.update(certblob) + elif reftype == 2: + hashobj = hashlib.sha512() + hashobj.update(certblob) + else: + raise ValueError("reftype sould be 0 1 or 2, not %s" % reftype) + return hashobj.hexdigest().upper() + class SOA(ResourceRecord): def __init__(self, master, email, serial, refresh, retry, expire, ttl): super(SOA, self).__init__('SOA', '@', '%s. %s. (\n %s ; numero de serie\n %s ; refresh (s)\n %s ; retry (s)\n %s ; expire (s)\n %s ; TTL (s)\n )' % (master, email, serial, refresh, retry, expire, ttl))