From 57e60f9a9bd96a6cd81651dfd8b833ea82c509c6 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Wed, 30 Jan 2019 11:51:15 +0100 Subject: [PATCH] DNSSEC: Complete support for key delegations to sub-domains - key-delegate script for constructing DS record sets in dss/* - DS macro for importing DS record sets to zones - DSFOR macro for adding dependencies on DS record sets to Makefile - key-update does not choke on empty directories - resign-stamp moved back to keys, so that it is not deleted by key hash cleanups - dnssec-signzone cannot be told to skip creation of dsset files, so redirect them from current directory to tmp/ - terminology: domain vs. zone --- TODO | 3 +-- bin/genzone | 7 ++++--- bin/key-delegate | 25 +++++++++++++++++++++++++ bin/key-gen | 2 +- bin/key-update | 4 ++-- bin/nsconfig | 2 +- cf.dist/domains | 1 + cf.dist/example.com | 3 ++- m4/dnslib.m4 | 1 + m4/mkmf.m4 | 14 +++++++++++--- m4/mkshell-env.m4 | 1 + m4/nsc.m4 | 6 ++++++ 12 files changed, 56 insertions(+), 13 deletions(-) create mode 100755 bin/key-delegate diff --git a/TODO b/TODO index f666f35..15b6d8b 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,5 @@ freebsd: don't use `-f' in hostname - Update or delete nsc.lsm DNSSEC: -- DS records and dependencies on them - in reverse zones, file name != zone name => need to pass zone name to genzone -- dependencies on resign-stamp +- signing reverse zones diff --git a/bin/genzone b/bin/genzone index 6c7bffc..cee907f 100755 --- a/bin/genzone +++ b/bin/genzone @@ -15,8 +15,8 @@ shift CURRENT_HASH=$($M4 -DHASHING m4/nsc.m4 "$@" | md5sum | cut -d " " -f1) if [ -f khash/$Z ] ; then CURRENT_HASH=$CURRENT_HASH:$(cat khash/$Z) - if [ -f khash/resign-stamp ] ; then - CURRENT_HASH=$CURRENT_HASH:$(stat -c '%Y' khash/resign-stamp) + if [ -f keys/resign-stamp ] ; then + CURRENT_HASH=$CURRENT_HASH:$(stat -c '%Y' keys/resign-stamp) fi fi @@ -28,12 +28,13 @@ else $M4 -DVERS=ver/$Z m4/nsc.m4 "$@" >zone/$Z.new NEWVER="$(sed -e "s/^;;; VERSION: //; t; d" zone/$Z.new)" if [ -f khash/$Z ] ; then - if ! dnssec-signzone -a -d dss -g -K keys/$Z $SIGNZONE_OPTIONS -f zone/$Z.signed -o $Z -S -3 - zone/$Z.new &>zone/$Z.tmp ; then + if ! dnssec-signzone -a -d tmp -K keys/$Z $SIGNZONE_OPTIONS -f zone/$Z.signed -o $Z -S -3 - zone/$Z.new &>zone/$Z.tmp ; then cat zone/$Z.tmp echo >&2 "FATAL: Signing failed" exit 1 fi rm -f zone/$Z.tmp + rm -f tmp/dsset-* mv zone/$Z.signed zone/$Z SIGNED=" (signed)" else diff --git a/bin/key-delegate b/bin/key-delegate new file mode 100755 index 0000000..bb4c5cd --- /dev/null +++ b/bin/key-delegate @@ -0,0 +1,25 @@ +#!/bin/bash +# NSC -- DNSSEC key delegation +# (c) 2019 Martin Mares + +set -e +shopt -s nullglob +. bin/shell-env + +if [ $# -ne 1 ] ; then + echo >&2 "Usage: $0 " + exit 1 +fi +Z=$1 + +>dss/$Z.new +for K in keys/$Z/*.key ; do + B=$(basename $K .key) + if grep -q '; This is a key-signing key,' $K ; then + echo "** $B: Adding" + dnssec-dsfromkey $DSFROMKEY_OPTIONS $K >>dss/$Z.new + else + echo "-- $B: Not a KSK" + fi +done +mv dss/$Z.new dss/$Z diff --git a/bin/key-gen b/bin/key-gen index 2494ebf..b73fd59 100755 --- a/bin/key-gen +++ b/bin/key-gen @@ -6,7 +6,7 @@ set -e . bin/shell-env if [ -z "$1" ] ; then - echo >&2 "Usage: $0 []" + echo >&2 "Usage: $0 []" exit 1 fi D="$1" diff --git a/bin/key-update b/bin/key-update index 9242b44..e7efe36 100755 --- a/bin/key-update +++ b/bin/key-update @@ -7,7 +7,7 @@ shopt -s nullglob . bin/shell-env if [ $# -gt 1 ] ; then - echo >&2 "Usage: $0 []" + echo >&2 "Usage: $0 []" exit 1 fi @@ -16,7 +16,7 @@ update () local D=$1 local K=keys/$D local H=khash/$D - cat $K/*.key | sha1sum | cut -f1 -d' ' >$H.new + cat /dev/null $K/*.key | sha1sum | cut -f1 -d' ' >$H.new if [ ! -f $H ] || ! cmp -s $H $H.new ; then echo "** $D: New key hash" mv $H.new $H diff --git a/bin/nsconfig b/bin/nsconfig index 122cc98..229dc36 100755 --- a/bin/nsconfig +++ b/bin/nsconfig @@ -12,7 +12,7 @@ if [ ! -f $DOMAINS ] ; then exit 1 fi -mkdir -p zone bak hash ver keys khash dss +mkdir -p zone bak hash ver keys khash dss tmp $M4 m4/mkconf.m4 $DOMAINS >named.conf $M4 m4/mkmf.m4 $DOMAINS >Makefile $M4 -DM4=$M4 m4/mkshell-env.m4 >bin/shell-env diff --git a/cf.dist/domains b/cf.dist/domains index 7d3dcd7..35d1d94 100644 --- a/cf.dist/domains +++ b/cf.dist/domains @@ -33,6 +33,7 @@ BLACKHOLE(REV(192.168)) DNSSEC(` PRIMARY(example.com) +DSFOR(a.example.com) ') ; It also has a couple of sub-domains and one of them resides on another server diff --git a/cf.dist/example.com b/cf.dist/example.com index 65f57c7..b5e900c 100644 --- a/cf.dist/example.com +++ b/cf.dist/example.com @@ -39,10 +39,11 @@ H(text) TXT(Once upon a midnight dreary) TXT(When I pondered weak and weary) -; A subdomain called a.example.com +; A subdomain called a.example.com with DNSSEC keys D(a) NS(ns1.example.com, ns2.example.com) +DS() ; Another subdomain (b.example.com), but this time one of the nameservers ; is inside, so we need to specify a glue record diff --git a/m4/dnslib.m4 b/m4/dnslib.m4 index 02609e7..5c43bc6 100644 --- a/m4/dnslib.m4 +++ b/m4/dnslib.m4 @@ -106,6 +106,7 @@ define(`MAINTNAME', `root'.`nsc_corr_dot(NSNAME)') define(`KEYGEN_OPTIONS', `-a RSASHA256 -b 1024') define(`SIGNZONE_OPTIONS', `-e +'DAYS(365)) +define(`DSFROMKEY_OPTIONS', `') # And finally we change comments to semicolons to be compatible with the zone files diff --git a/m4/mkmf.m4 b/m4/mkmf.m4 index 7d0f5d5..29c8fd5 100644 --- a/m4/mkmf.m4 +++ b/m4/mkmf.m4 @@ -10,8 +10,9 @@ define(`PRIMARIES', `') define(`nsc_prepend_cf_one', ` 'CFDIR/`nsc_file_name($1)') define(`nsc_prepend_cf_multi', `nsc_iterate(`nsc_prepend_cf_one', $@)') -define(`nsc_key_dep', `ifelse(USE_DNSSEC,,,` 'khash/$1 khash/resign-stamp)') -define(`PRIMARY', `divert(0)zone/nsc_file_name($1):nsc_prepend_cf_multi($@)nsc_key_dep($1) $(DDEPS) +define(`nsc_key_dep', `ifelse(USE_DNSSEC,,,` 'khash/$1 keys/resign-stamp)') +define(`PRIMARY', `define(`CURRENT_TARGET',zone/nsc_file_name($1)) +divert(0)CURRENT_TARGET:nsc_prepend_cf_multi($@)nsc_key_dep($1) $(DDEPS) @bin/genzone nsc_file_name($1)`'nsc_prepend_cf_multi($@) divert(-1) @@ -22,6 +23,10 @@ define(`REVERSE', `PRIMARY(nsc_if_v6($1,`nsc_revblock6($1)',`nsc_revaddr($1)'), define(`BLACKHOLE', `define(`NEED_BLACKHOLE', 1)') +define(`DSFOR', `divert(0)CURRENT_TARGET: dss/$1 + +divert(-1)') + # Insertion of raw makefile material define(`MAKEFILE', `divert(0)$1 @@ -37,8 +42,11 @@ ver/.version: CFDIR/domains ROOTCACHE`'PRIMARIES`'ifdef(`NEED_BLACKHOLE',` zone/ NAMED_RESTART_CMD touch ver/.version +keys/resign-stamp: + touch `$'@ + clean: - find bak zone hash -maxdepth 1 -type f | xargs rm -f + find bak zone hash tmp -maxdepth 1 -type f | xargs rm -f clobber: clean rm -f Makefile named.conf bin/shell-env diff --git a/m4/mkshell-env.m4 b/m4/mkshell-env.m4 index 6a134ba..1d02f73 100644 --- a/m4/mkshell-env.m4 +++ b/m4/mkshell-env.m4 @@ -9,3 +9,4 @@ divert(0)dnl `M4'=M4 `KEYGEN_OPTIONS'="KEYGEN_OPTIONS" `SIGNZONE_OPTIONS'="SIGNZONE_OPTIONS" +`DSFROMKEY_OPTIONS'="DSFROMKEY_OPTIONS" diff --git a/m4/nsc.m4 b/m4/nsc.m4 index ad9ed24..cf7a81d 100644 --- a/m4/nsc.m4 +++ b/m4/nsc.m4 @@ -31,6 +31,7 @@ define(`VERSION',TODAY_CODE`'format(`%02d', SUBVER_NUM)) define(nsc_set_name, `define(`CURRENT_NAME', nsc_corr_dot($1))define(`PRINT_NAME', CURRENT_NAME)') define(nsc_emit_name, `ifdef(`PRINT_NAME', `PRINT_NAME`'undefine(`PRINT_NAME')', `')') define(nsc_abs_name, `ifelse(CURRENT_NAME, translit(CURRENT_NAME,.,:), CURRENT_NAME.CURRENT_DOMAIN, CURRENT_NAME)') +define(nsc_abs_name_nodot, `define(`nsc_tmp', nsc_abs_name)substr(nsc_tmp,0,decr(len(nsc_tmp)))') # SOA record @@ -144,6 +145,11 @@ define(CNAME, `$1 `CNAME' nsc_corr_dot($2)') define(PTR, `$1 `PTR' nsc_corr_dot($2)') +# DS records (DNSSEC keys for subdomains) + +define(DS, `ifdef(`REVERSE_MODE',,`nsc_DS')') +define(nsc_DS, `undivert(dss/nsc_abs_name_nodot)') + # Shortcut for classless reverse delegation of a block define(REVBLOCK, `nsc_forloop(`i', $2, $3, `i' `CNAME' `i'.$1 -- 2.39.2