mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-25 02:47:04 +00:00
whats_next: offer DNSSEC DS parameters rather than the full record and in validation allow for other digests than the one we suggest using
fixes #120 (hopefully), in which Gandi generates a SHA1 digest but we were only checking against a SHA256 digest Also see http://discourse.mailinabox.email/t/how-to-set-ds-record-for-gandi-net/24/1 in which a user asks about the DS parameters that Gandi asks for.
This commit is contained in:
parent
30178ef019
commit
6d4fab1e6a
@ -93,7 +93,7 @@ def do_dns_update(env, force=False):
|
|||||||
# Thus we only sign a zone if write_nsd_zone returned True
|
# Thus we only sign a zone if write_nsd_zone returned True
|
||||||
# indicating the zone changed, and thus it got a new serial number.
|
# indicating the zone changed, and thus it got a new serial number.
|
||||||
# write_nsd_zone is smart enough to check if a zone's signature
|
# write_nsd_zone is smart enough to check if a zone's signature
|
||||||
# is nearing experiation and if so it'll bump the serial number
|
# is nearing expiration and if so it'll bump the serial number
|
||||||
# and return True so we get a chance to re-sign it.
|
# and return True so we get a chance to re-sign it.
|
||||||
sign_zone(domain, zonefile, env)
|
sign_zone(domain, zonefile, env)
|
||||||
|
|
||||||
@ -478,12 +478,17 @@ def sign_zone(domain, zonefile, env):
|
|||||||
# zone being signed, so we can't use the .ds files generated when we created the keys.
|
# zone being signed, so we can't use the .ds files generated when we created the keys.
|
||||||
# The DS record points to the KSK only. Write this next to the zone file so we can
|
# The DS record points to the KSK only. Write this next to the zone file so we can
|
||||||
# get it later to give to the user with instructions on what to do with it.
|
# get it later to give to the user with instructions on what to do with it.
|
||||||
|
#
|
||||||
|
# We want to be able to validate DS records too, but multiple forms may be valid depending
|
||||||
|
# on the digest type. So we'll write all (both) valid records. Only one DS record should
|
||||||
|
# actually be deployed. Preferebly the first.
|
||||||
|
with open("/etc/nsd/zones/" + zonefile + ".ds", "w") as f:
|
||||||
|
for digest_type in ('2', '1'):
|
||||||
rr_ds = shell('check_output', ["/usr/bin/ldns-key2ds",
|
rr_ds = shell('check_output', ["/usr/bin/ldns-key2ds",
|
||||||
"-n", # output to stdout
|
"-n", # output to stdout
|
||||||
"-2", # SHA256
|
"-" + digest_type, # 1=SHA1, 2=SHA256
|
||||||
dnssec_keys["KSK"] + ".key"
|
dnssec_keys["KSK"] + ".key"
|
||||||
])
|
])
|
||||||
with open("/etc/nsd/zones/" + zonefile + ".ds", "w") as f:
|
|
||||||
f.write(rr_ds)
|
f.write(rr_ds)
|
||||||
|
|
||||||
# Remove our temporary file.
|
# Remove our temporary file.
|
||||||
|
@ -14,7 +14,7 @@ from dns_update import get_dns_zones
|
|||||||
from web_update import get_web_domains, get_domain_ssl_files
|
from web_update import get_web_domains, get_domain_ssl_files
|
||||||
from mailconfig import get_mail_domains, get_mail_aliases
|
from mailconfig import get_mail_domains, get_mail_aliases
|
||||||
|
|
||||||
from utils import shell, sort_domains
|
from utils import shell, sort_domains, load_env_vars_from_file
|
||||||
|
|
||||||
def run_checks(env):
|
def run_checks(env):
|
||||||
run_system_checks(env)
|
run_system_checks(env)
|
||||||
@ -125,25 +125,47 @@ def check_dns_zone(domain, env, dns_zonefiles):
|
|||||||
control panel to set the nameservers to %s."""
|
control panel to set the nameservers to %s."""
|
||||||
% (existing_ns, correct_ns) )
|
% (existing_ns, correct_ns) )
|
||||||
|
|
||||||
# See if the domain has a DS record set.
|
# See if the domain has a DS record set at the registrar. The DS record may have
|
||||||
|
# several forms. We have to be prepared to check for any valid record. We've
|
||||||
|
# pre-generated all of the valid digests --- read them in.
|
||||||
|
ds_correct = open('/etc/nsd/zones/' + dns_zonefiles[domain] + '.ds').read().strip().split("\n")
|
||||||
|
digests = { }
|
||||||
|
for rr_ds in ds_correct:
|
||||||
|
ds_keytag, ds_alg, ds_digalg, ds_digest = rr_ds.split("\t")[4].split(" ")
|
||||||
|
digests[ds_digalg] = ds_digest
|
||||||
|
|
||||||
|
# Some registrars may want the public key so they can compute the digest. The DS
|
||||||
|
# record that we suggest using is for the KSK (and that's how the DS records were generated).
|
||||||
|
dnssec_keys = load_env_vars_from_file(os.path.join(env['STORAGE_ROOT'], 'dns/dnssec/keys.conf'))
|
||||||
|
dnsssec_pubkey = open(os.path.join(env['STORAGE_ROOT'], 'dns/dnssec/' + dnssec_keys['KSK'] + '.key')).read().split("\t")[3].split(" ")[3]
|
||||||
|
|
||||||
|
# Query public DNS for the DS record at the registrar.
|
||||||
ds = query_dns(domain, "DS", nxdomain=None)
|
ds = query_dns(domain, "DS", nxdomain=None)
|
||||||
ds_correct = open('/etc/nsd/zones/' + dns_zonefiles[domain] + '.ds').read().strip()
|
ds_looks_valid = ds and len(ds.split(" ")) == 4
|
||||||
ds_expected = re.sub(r"\S+\.\s+3600\s+IN\s+DS\s*", "", ds_correct)
|
if ds_looks_valid: ds = ds.split(" ")
|
||||||
if ds == ds_expected:
|
if ds_looks_valid and ds[0] == ds_keytag and ds[1] == '7' and ds[3] == digests.get(ds[2]):
|
||||||
print_ok("DNS 'DS' record is set correctly at registrar.")
|
print_ok("DNS 'DS' record is set correctly at registrar.")
|
||||||
elif ds == None:
|
else:
|
||||||
|
if ds == None:
|
||||||
print_error("""This domain's DNS DS record is not set. The DS record is optional. The DS record activates DNSSEC.
|
print_error("""This domain's DNS DS record is not set. The DS record is optional. The DS record activates DNSSEC.
|
||||||
To set a DS record, you must follow the instructions provided by your domain name registrar and provide to them this information:""")
|
To set a DS record, you must follow the instructions provided by your domain name registrar and provide to them this information:""")
|
||||||
print("")
|
|
||||||
print(" " + ds_correct)
|
|
||||||
print("")
|
|
||||||
else:
|
else:
|
||||||
print_error("""This domain's DNS DS record is incorrect. The chain of trust is broken between the public DNS system
|
print_error("""This domain's DNS DS record is incorrect. The chain of trust is broken between the public DNS system
|
||||||
and this machine's DNS server. It may take several hours for public DNS to update after a change. If you did not recently
|
and this machine's DNS server. It may take several hours for public DNS to update after a change. If you did not recently
|
||||||
make a change, you must resolve this immediately by following the instructions provided by your domain name registrar and
|
make a change, you must resolve this immediately by following the instructions provided by your domain name registrar and
|
||||||
provide to them this information:""")
|
provide to them this information:""")
|
||||||
print("")
|
print()
|
||||||
print(" " + ds_correct)
|
print("\tKey Tag: " + ds_keytag + ("" if not ds_looks_valid or ds[0] == ds_keytag else " (Got '%s')" % ds[0]))
|
||||||
|
print("\tKey Flags: KSK")
|
||||||
|
print("\tAlgorithm: 7 / RSASHA1-NSEC3-SHA1" + ("" if not ds_looks_valid or ds[1] == '7' else " (Got '%s')" % ds[1]))
|
||||||
|
print("\tDigest Type: 2 / SHA-256")
|
||||||
|
print("\tDigest: " + digests['2'])
|
||||||
|
if ds_looks_valid and ds[3] != digests.get(ds[2]):
|
||||||
|
print("\t(Got digest type %s and digest %s which do not match.)" % (ds[2], ds[3]))
|
||||||
|
print("\tPublic Key: " + dnsssec_pubkey)
|
||||||
|
print()
|
||||||
|
print("\tBulk/Record Format:")
|
||||||
|
print("\t" + ds_correct[0])
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
def check_mail_domain(domain, env):
|
def check_mail_domain(domain, env):
|
||||||
|
Loading…
Reference in New Issue
Block a user