1#!/bin/sh 2 3# Copyright (C) Internet Systems Consortium, Inc. ("ISC") 4# 5# SPDX-License-Identifier: MPL-2.0 6# 7# This Source Code Form is subject to the terms of the Mozilla Public 8# License, v. 2.0. If a copy of the MPL was not distributed with this 9# file, you can obtain one at https://mozilla.org/MPL/2.0/. 10# 11# See the COPYRIGHT file distributed with this work for additional 12# information regarding copyright ownership. 13 14SYSTEMTESTTOP=.. 15. $SYSTEMTESTTOP/conf.sh 16 17status=0 18 19pzone=parent.nil 20pfile=parent.db 21 22czone=child.parent.nil 23cfile=child.db 24 25echo_i "generating child's keys" 26# active zsk 27czsk1=`$KEYGEN -q -a rsasha1 -L 30 $czone` 28 29# not yet published or active 30czsk2=`$KEYGEN -q -a rsasha1 -P none -A none $czone` 31 32# published but not active 33czsk3=`$KEYGEN -q -a rsasha1 -A none $czone` 34 35# inactive 36czsk4=`$KEYGEN -q -a rsasha1 -P now-24h -A now-24h -I now $czone` 37 38# active in 12 hours, inactive 12 hours after that... 39czsk5=`$KEYGEN -q -a rsasha1 -P now+12h -A now+12h -I now+24h $czone` 40 41# explicit successor to czk5 42# (suppressing warning about lack of removal date) 43czsk6=`$KEYGEN -q -S $czsk5 -i 6h 2>/dev/null` 44 45# active ksk 46cksk1=`$KEYGEN -q -a rsasha1 -fk -L 30 $czone` 47 48# published but not YET active; will be active in 20 seconds 49cksk2=`$KEYGEN -q -a rsasha1 -fk $czone` 50# $SETTIME moved after other $KEYGENs 51 52echo_i "revoking key" 53# revoking key changes its ID 54cksk3=`$KEYGEN -q -a rsasha1 -fk $czone` 55cksk4=`$REVOKE $cksk3` 56 57echo_i "setting up sync key" 58cksk5=`$KEYGEN -q -a rsasha1 -fk -P now+1mo -A now+1mo -Psync now $czone` 59 60echo_i "and future sync key" 61cksk6=`$KEYGEN -q -a rsasha1 -fk -P now+1mo -A now+1mo -Psync now+1mo $czone` 62 63echo_i "generating parent keys" 64pzsk=`$KEYGEN -q -a rsasha1 $pzone` 65pksk=`$KEYGEN -q -a rsasha1 -fk $pzone` 66 67echo_i "setting child's activation time" 68# using now+30s to fix RT 24561 69$SETTIME -A now+30s $cksk2 > /dev/null 70 71echo_i "signing child zone" 72czoneout=`$SIGNER -Sg -e now+1d -X now+2d -o $czone $cfile` 73 74echo_i "signing parent zone" 75pzoneout=`$SIGNER -Sg -o $pzone $pfile` 76 77czactive=$(keyfile_to_key_id $czsk1) 78czgenerated=$(keyfile_to_key_id $czsk2) 79czpublished=$(keyfile_to_key_id $czsk3) 80czinactive=$(keyfile_to_key_id $czsk4) 81czpredecessor=$(keyfile_to_key_id $czsk5) 82czsuccessor=$(keyfile_to_key_id $czsk6) 83ckactive=$(keyfile_to_key_id $cksk1) 84ckpublished=$(keyfile_to_key_id $cksk2) 85ckprerevoke=$(keyfile_to_key_id $cksk3) 86ckrevoked=$(keyfile_to_key_id $cksk4) 87 88pzid=$(keyfile_to_key_id $pzsk) 89pkid=$(keyfile_to_key_id $pksk) 90 91echo_i "checking dnssec-signzone output matches expectations" 92ret=0 93echo "$pzoneout" | grep 'KSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1 94echo "$pzoneout" | grep 'ZSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1 95echo "$czoneout" | grep 'KSKs: 1 active, 1 stand-by, 1 revoked' > /dev/null || ret=1 96echo "$czoneout" | grep 'ZSKs: 1 active, 2 stand-by, 0 revoked' > /dev/null || ret=1 97if [ $ret != 0 ]; then 98 echo_i "parent $pzoneout" 99 echo_i "child $czoneout" 100 echo_i "failed"; 101fi 102status=`expr $status + $ret` 103 104echo_i "rechecking dnssec-signzone output with -x" 105ret=0 106# use an alternate output file so -x doesn't interfere with later checks 107pzoneout=`$SIGNER -Sxg -o $pzone -f ${pfile}2.signed $pfile` 108czoneout=`$SIGNER -Sxg -e now+1d -X now+2d -o $czone -f ${cfile}2.signed $cfile` 109echo "$pzoneout" | grep 'KSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1 110echo "$pzoneout" | grep 'ZSKs: 1 active, 0 present, 0 revoked' > /dev/null || ret=1 111echo "$czoneout" | grep 'KSKs: 1 active, 1 stand-by, 1 revoked' > /dev/null || ret=1 112echo "$czoneout" | grep 'ZSKs: 1 active, 2 present, 0 revoked' > /dev/null || ret=1 113if [ $ret != 0 ]; then 114 echo_i "parent $pzoneout" 115 echo_i "child $czoneout" 116 echo_i "failed"; 117fi 118status=`expr $status + $ret` 119 120echo_i "checking parent zone DNSKEY set" 121ret=0 122grep "key id = $pzid" $pfile.signed > /dev/null || { 123 ret=1 124 echo_i "missing expected parent ZSK id = $pzid" 125} 126grep "key id = $pkid" $pfile.signed > /dev/null || { 127 ret=1 128 echo_i "missing expected parent KSK id = $pkid" 129} 130if [ $ret != 0 ]; then echo_i "failed"; fi 131status=`expr $status + $ret` 132 133echo_i "checking parent zone DS records" 134ret=0 135awk '$2 == "DS" {print $3}' $pfile.signed > dsset.out 136grep -w "$ckactive" dsset.out > /dev/null || ret=1 137grep -w "$ckpublished" dsset.out > /dev/null || ret=1 138# revoked key should not be there, hence the && 139grep -w "$ckprerevoke" dsset.out > /dev/null && ret=1 140grep -w "$ckrevoked" dsset.out > /dev/null && ret=1 141if [ $ret != 0 ]; then echo_i "failed"; fi 142status=`expr $status + $ret` 143 144echo_i "checking child zone DNSKEY set" 145ret=0 146grep "key id = $ckactive\$" $cfile.signed > /dev/null || { 147 ret=1 148 echo_i "missing expected child KSK id = $ckactive" 149} 150grep "key id = $ckpublished\$" $cfile.signed > /dev/null || { 151 ret=1 152 echo_i "missing expected child prepublished KSK id = $ckpublished" 153} 154grep "key id = $ckrevoked\$" $cfile.signed > /dev/null || { 155 ret=1 156 echo_i "missing expected child revoked KSK id = $ckrevoked" 157} 158grep "key id = $czactive\$" $cfile.signed > /dev/null || { 159 ret=1 160 echo_i "missing expected child ZSK id = $czactive" 161} 162grep "key id = $czpublished\$" $cfile.signed > /dev/null || { 163 ret=1 164 echo_i "missing expected child prepublished ZSK id = $czpublished" 165} 166grep "key id = $czinactive\$" $cfile.signed > /dev/null || { 167 ret=1 168 echo_i "missing expected child inactive ZSK id = $czinactive" 169} 170# should not be there, hence the && 171grep "key id = $ckprerevoke\$" $cfile.signed > /dev/null && { 172 ret=1 173 echo_i "found unexpected child pre-revoke ZSK id = $ckprerevoke" 174} 175grep "key id = $czgenerated\$" $cfile.signed > /dev/null && { 176 ret=1 177 echo_i "found unexpected child generated ZSK id = $czgenerated" 178} 179grep "key id = $czpredecessor\$" $cfile.signed > /dev/null && { 180 echo_i "found unexpected ZSK predecessor id = $czpredecessor (ignored)" 181} 182grep "key id = $czsuccessor\$" $cfile.signed > /dev/null && { 183 echo_i "found unexpected ZSK successor id = $czsuccessor (ignored)" 184} 185#grep "key id = $czpredecessor\$" $cfile.signed > /dev/null && ret=1 186#grep "key id = $czsuccessor\$" $cfile.signed > /dev/null && ret=1 187if [ $ret != 0 ]; then echo_i "failed"; fi 188status=`expr $status + $ret` 189 190echo_i "checking key TTLs are correct" 191ret=0 192grep "${czone}. 30 IN" ${czsk1}.key > /dev/null 2>&1 || ret=1 193grep "${czone}. 30 IN" ${cksk1}.key > /dev/null 2>&1 || ret=1 194grep "${czone}. IN" ${czsk2}.key > /dev/null 2>&1 || ret=1 195$SETTIME -L 45 ${czsk2} > /dev/null 196grep "${czone}. 45 IN" ${czsk2}.key > /dev/null 2>&1 || ret=1 197$SETTIME -L 0 ${czsk2} > /dev/null 198grep "${czone}. IN" ${czsk2}.key > /dev/null 2>&1 || ret=1 199if [ $ret != 0 ]; then echo_i "failed"; fi 200status=`expr $status + $ret` 201 202echo_i "checking key TTLs were imported correctly" 203ret=0 204awk 'BEGIN {r = 0} $2 == "DNSKEY" && $1 != 30 {r = 1} END {exit r}' \ 205 ${cfile}.signed || ret=1 206if [ $ret != 0 ]; then echo_i "failed"; fi 207status=`expr $status + $ret` 208 209echo_i "re-signing and checking imported TTLs again" 210ret=0 211$SETTIME -L 15 ${czsk2} > /dev/null 212czoneout=`$SIGNER -Sg -e now+1d -X now+2d -o $czone $cfile` 213awk 'BEGIN {r = 0} $2 == "DNSKEY" && $1 != 15 {r = 1} END {exit r}' \ 214 ${cfile}.signed || ret=1 215if [ $ret != 0 ]; then echo_i "failed"; fi 216status=`expr $status + $ret` 217 218# There is some weirdness in Solaris 10 (Generic_120011-14), which 219# is why the next section has all those echo $ret > /dev/null;sync 220# commands 221echo_i "checking child zone signatures" 222ret=0 223# check DNSKEY signatures first 224awk '$2 == "RRSIG" && $3 == "DNSKEY" { getline; print $3 }' $cfile.signed > dnskey.sigs 225sub=0 226grep -w "$ckactive" dnskey.sigs > /dev/null || sub=1 227if [ $sub != 0 ]; then echo_i "missing ckactive $ckactive (dnskey)"; ret=1; fi 228echo $ret > /dev/null 229sync 230sub=0 231grep -w "$ckrevoked" dnskey.sigs > /dev/null || sub=1 232if [ $sub != 0 ]; then echo_i "missing ckrevoke $ckrevoke (dnskey)"; ret=1; fi 233echo $ret > /dev/null 234sync 235sub=0 236grep -w "$czactive" dnskey.sigs > /dev/null || sub=1 237if [ $sub != 0 ]; then echo_i "missing czactive $czactive (dnskey)"; ret=1; fi 238# should not be there: 239echo $ret > /dev/null 240sync 241sub=0 242grep -w "$ckprerevoke" dnskey.sigs > /dev/null && sub=1 243if [ $sub != 0 ]; then echo_i "found ckprerevoke $ckprerevoke (dnskey)"; ret=1; fi 244echo $ret > /dev/null 245sync 246sub=0 247grep -w "$ckpublished" dnskey.sigs > /dev/null && sub=1 248if [ $sub != 0 ]; then echo_i "found ckpublished $ckpublished (dnskey)"; ret=1; fi 249echo $ret > /dev/null 250sync 251sub=0 252grep -w "$czpublished" dnskey.sigs > /dev/null && sub=1 253if [ $sub != 0 ]; then echo_i "found czpublished $czpublished (dnskey)"; ret=1; fi 254echo $ret > /dev/null 255sync 256sub=0 257grep -w "$czinactive" dnskey.sigs > /dev/null && sub=1 258if [ $sub != 0 ]; then echo_i "found czinactive $czinactive (dnskey)"; ret=1; fi 259echo $ret > /dev/null 260sync 261sub=0 262grep -w "$czgenerated" dnskey.sigs > /dev/null && sub=1 263if [ $sub != 0 ]; then echo_i "found czgenerated $czgenerated (dnskey)"; ret=1; fi 264# now check other signatures first 265awk '$2 == "RRSIG" && $3 != "DNSKEY" && $3 != "CDNSKEY" && $3 != "CDS" { getline; print $3 }' $cfile.signed | sort -un > other.sigs 266# should not be there: 267echo $ret > /dev/null 268sync 269sub=0 270grep -w "$ckactive" other.sigs > /dev/null && sub=1 271if [ $sub != 0 ]; then echo_i "found ckactive $ckactive (other)"; ret=1; fi 272echo $ret > /dev/null 273sync 274sub=0 275grep -w "$ckpublished" other.sigs > /dev/null && sub=1 276if [ $sub != 0 ]; then echo_i "found ckpublished $ckpublished (other)"; ret=1; fi 277echo $ret > /dev/null 278sync 279sub=0 280grep -w "$ckprerevoke" other.sigs > /dev/null && sub=1 281if [ $sub != 0 ]; then echo_i "found ckprerevoke $ckprerevoke (other)"; ret=1; fi 282echo $ret > /dev/null 283sync 284sub=0 285grep -w "$ckrevoked" other.sigs > /dev/null && sub=1 286if [ $sub != 0 ]; then echo_i "found ckrevoked $ckrevoked (other)"; ret=1; fi 287echo $ret > /dev/null 288sync 289sub=0 290grep -w "$czpublished" other.sigs > /dev/null && sub=1 291if [ $sub != 0 ]; then echo_i "found czpublished $czpublished (other)"; ret=1; fi 292echo $ret > /dev/null 293sync 294sub=0 295grep -w "$czinactive" other.sigs > /dev/null && sub=1 296if [ $sub != 0 ]; then echo_i "found czinactive $czinactive (other)"; ret=1; fi 297echo $ret > /dev/null 298sync 299sub=0 300grep -w "$czgenerated" other.sigs > /dev/null && sub=1 301if [ $sub != 0 ]; then echo_i "found czgenerated $czgenerated (other)"; ret=1; fi 302echo $ret > /dev/null 303sync 304sub=0 305grep -w "$czpredecessor" other.sigs > /dev/null && sub=1 306if [ $sub != 0 ]; then echo_i "found czpredecessor $czpredecessor (other)"; ret=1; fi 307echo $ret > /dev/null 308sync 309sub=0 310grep -w "$czsuccessor" other.sigs > /dev/null && sub=1 311if [ $sub != 0 ]; then echo_i "found czsuccessor $czsuccessor (other)"; ret=1; fi 312if [ $ret != 0 ]; then 313 sed 's/^/I:dnskey sigs: /' < dnskey.sigs 314 sed 's/^/I:other sigs: /' < other.sigs 315 echo_i "failed"; 316fi 317status=`expr $status + $ret` 318 319echo_i "checking RRSIG expiry date correctness" 320dnskey_expiry=`$CHECKZONE -o - $czone $cfile.signed 2> /dev/null | 321 awk '$4 == "RRSIG" && $5 == "DNSKEY" {print $9; exit}' | 322 cut -c1-10` 323soa_expiry=`$CHECKZONE -o - $czone $cfile.signed 2> /dev/null | 324 awk '$4 == "RRSIG" && $5 == "SOA" {print $9; exit}' | 325 cut -c1-10` 326[ $dnskey_expiry -gt $soa_expiry ] || ret=1 327if [ $ret != 0 ]; then echo_i "failed"; fi 328status=`expr $status + $ret` 329 330echo_i "waiting 30 seconds for key activation" 331sleep 30 332echo_i "re-signing child zone" 333czoneout2=`$SIGNER -Sg -o $czone -f $cfile.new $cfile.signed` 334mv $cfile.new $cfile.signed 335 336echo_i "checking dnssec-signzone output matches expectations" 337ret=0 338echo "$czoneout2" | grep 'KSKs: 2 active, 0 stand-by, 1 revoked' > /dev/null || ret=1 339if [ $ret != 0 ]; then echo_i "failed"; fi 340status=`expr $status + $ret` 341 342echo_i "checking child zone signatures again" 343ret=0 344awk '$2 == "RRSIG" && $3 == "DNSKEY" { getline; print $3 }' $cfile.signed > dnskey.sigs 345grep -w "$ckpublished" dnskey.sigs > /dev/null || ret=1 346if [ $ret != 0 ]; then echo_i "failed"; fi 347status=`expr $status + $ret` 348 349echo_i "checking sync record publication" 350ret=0 351awk 'BEGIN { r=1 } $2 == "CDNSKEY" { r=0 } END { exit r }' $cfile.signed || ret=1 352awk 'BEGIN { r=1 } $2 == "CDS" { r=0 } END { exit r }' $cfile.signed || ret=1 353if [ $ret != 0 ]; then echo_i "failed"; fi 354status=`expr $status + $ret` 355 356# this also checks that the future sync record is not yet published 357echo_i "checking sync record deletion" 358ret=0 359$SETTIME -P now -A now -Dsync now ${cksk5} > /dev/null 360$SIGNER -Sg -o $czone -f $cfile.new $cfile.signed > /dev/null 361mv $cfile.new $cfile.signed 362awk 'BEGIN { r=1 } $2 == "CDNSKEY" { r=0 } END { exit r }' $cfile.signed && ret=1 363awk 'BEGIN { r=1 } $2 == "CDS" { r=0 } END { exit r }' $cfile.signed && ret=1 364if [ $ret != 0 ]; then echo_i "failed"; fi 365status=`expr $status + $ret` 366 367echo_i "exit status: $status" 368[ $status -eq 0 ] || exit 1 369