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 14# shellcheck source=conf.sh 15. ../conf.sh 16# shellcheck source=kasp.sh 17. ../kasp.sh 18 19# Log errors and increment $ret. 20log_error() { 21 echo_i "error: $1" 22 ret=$((ret+1)) 23} 24 25# Call dig with default options. 26dig_with_opts() { 27 $DIG +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@" 28} 29 30# Call rndc. 31rndccmd() { 32 "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@" 33} 34 35# Set zone name ($1) and policy ($2) for testing nsec3. 36set_zone_policy() { 37 ZONE=$1 38 POLICY=$2 39} 40# Set expected NSEC3 parameters: flags ($1), iterations ($2), and 41# salt length ($3). 42set_nsec3param() { 43 FLAGS=$1 44 ITERATIONS=$2 45 SALTLEN=$3 46 # Reset salt. 47 SALT="" 48} 49 50# The apex NSEC3PARAM record indicates that it is signed. 51_wait_for_nsec3param() { 52 dig_with_opts +noquestion "@${SERVER}" "$ZONE" NSEC3PARAM > "dig.out.test$n.wait" || return 1 53 grep "${ZONE}\..*IN.*NSEC3PARAM.*1.*0.*${ITERATIONS}.*${SALT}" "dig.out.test$n.wait" > /dev/null || return 1 54 grep "${ZONE}\..*IN.*RRSIG" "dig.out.test$n.wait" > /dev/null || return 1 55 return 0 56} 57# The apex NSEC record indicates that it is signed. 58_wait_for_nsec() { 59 dig_with_opts +noquestion "@${SERVER}" "$ZONE" NSEC > "dig.out.test$n.wait" || return 1 60 grep "NS SOA" "dig.out.test$n.wait" > /dev/null || return 1 61 grep "${ZONE}\..*IN.*RRSIG" "dig.out.test$n.wait" > /dev/null || return 1 62 grep "${ZONE}\..*IN.*NSEC3PARAM" "dig.out.test$n.wait" > /dev/null && return 1 63 return 0 64} 65 66# Wait for the zone to be signed. 67wait_for_zone_is_signed() { 68 n=$((n+1)) 69 ret=0 70 echo_i "wait for ${ZONE} to be signed ($n)" 71 72 if [ "$1" = "nsec3" ]; then 73 retry_quiet 10 _wait_for_nsec3param || log_error "wait for ${ZONE} to be signed failed" 74 else 75 retry_quiet 10 _wait_for_nsec || log_error "wait for ${ZONE} to be signed failed" 76 fi 77 78 test "$ret" -eq 0 || echo_i "failed" 79 status=$((status+ret)) 80} 81 82# Test: check NSEC in answers 83_check_nsec_nsec3param() 84{ 85 dig_with_opts +noquestion @$SERVER "${ZONE}" NSEC3PARAM > "dig.out.test$n.nsec3param.$ZONE" || return 1 86 grep "NSEC3PARAM" "dig.out.test$n.nsec3param.$ZONE" > /dev/null && return 1 87 return 0 88} 89 90_check_nsec_nxdomain() 91{ 92 dig_with_opts @$SERVER "nosuchname.${ZONE}" > "dig.out.test$n.nxdomain.$ZONE" || return 1 93 grep "${ZONE}.*IN.*NSEC.*NS.*SOA.*RRSIG.*NSEC.*DNSKEY" "dig.out.test$n.nxdomain.$ZONE" > /dev/null || return 1 94 grep "NSEC3" "dig.out.test$n.nxdomain.$ZONE" > /dev/null && return 1 95 return 0 96} 97 98check_nsec() 99{ 100 n=$((n+1)) 101 echo_i "check NSEC3PARAM response for zone ${ZONE} ($n)" 102 ret=0 103 retry_quiet 10 _check_nsec_nsec3param || log_error "unexpected NSEC3PARAM in response for zone ${ZONE}" 104 test "$ret" -eq 0 || echo_i "failed" 105 status=$((status+ret)) 106 107 n=$((n+1)) 108 echo_i "check NXDOMAIN response for zone ${ZONE} ($n)" 109 ret=0 110 retry_quiet 10 _check_nsec_nxdomain || log_error "bad NXDOMAIN response for zone ${ZONE}" 111 test "$ret" -eq 0 || echo_i "failed" 112 status=$((status+ret)) 113} 114 115# Test: check NSEC3 parameters in answers 116_check_nsec3_nsec3param() 117{ 118 dig_with_opts +noquestion @$SERVER "${ZONE}" NSEC3PARAM > "dig.out.test$n.nsec3param.$ZONE" || return 1 119 grep "${ZONE}.*0.*IN.*NSEC3PARAM.*1.*0.*${ITERATIONS}.*${SALT}" "dig.out.test$n.nsec3param.$ZONE" > /dev/null || return 1 120 121 if [ -z "$SALT" ]; then 122 SALT=`awk '$4 == "NSEC3PARAM" { print $8 }' dig.out.test$n.nsec3param.$ZONE` 123 fi 124 return 0 125} 126 127_check_nsec3_nxdomain() 128{ 129 dig_with_opts @$SERVER "nosuchname.${ZONE}" > "dig.out.test$n.nxdomain.$ZONE" || return 1 130 grep ".*\.${ZONE}.*IN.*NSEC3.*1.${FLAGS}.*${ITERATIONS}.*${SALT}" "dig.out.test$n.nxdomain.$ZONE" > /dev/null || return 1 131 return 0 132} 133 134check_nsec3() 135{ 136 n=$((n+1)) 137 echo_i "check that NSEC3PARAM 1 0 ${ITERATIONS} is published zone ${ZONE} ($n)" 138 ret=0 139 retry_quiet 10 _check_nsec3_nsec3param || log_error "bad NSEC3PARAM response for ${ZONE}" 140 test "$ret" -eq 0 || echo_i "failed" 141 status=$((status+ret)) 142 143 n=$((n+1)) 144 echo_i "check NXDOMAIN response has correct NSEC3 1 ${FLAGS} ${ITERATIONS} ${SALT} for zone ${ZONE} ($n)" 145 ret=0 146 retry_quiet 10 _check_nsec3_nxdomain || log_error "bad NXDOMAIN response for zone ${ZONE}" 147 test "$ret" -eq 0 || echo_i "failed" 148 status=$((status+ret)) 149} 150 151start_time="$(TZ=UTC date +%s)" 152status=0 153n=0 154 155# Zone: nsec-to-nsec3.kasp. 156set_zone_policy "nsec-to-nsec3.kasp" "nsec" 157set_server "ns3" "10.53.0.3" 158echo_i "initial check zone ${ZONE}" 159check_nsec 160dnssec_verify 161 162# Zone: nsec3.kasp. 163set_zone_policy "nsec3.kasp" "nsec3" 164set_nsec3param "0" "5" "8" 165echo_i "initial check zone ${ZONE}" 166check_nsec3 167dnssec_verify 168 169# Zone: nsec3-dynamic.kasp. 170set_zone_policy "nsec3-dynamic.kasp" "nsec3" 171set_nsec3param "0" "5" "8" 172echo_i "initial check zone ${ZONE}" 173check_nsec3 174dnssec_verify 175 176# Zone: nsec3-change.kasp. 177set_zone_policy "nsec3-change.kasp" "nsec3" 178set_nsec3param "0" "5" "8" 179echo_i "initial check zone ${ZONE}" 180check_nsec3 181dnssec_verify 182 183# Zone: nsec3-dynamic-change.kasp. 184set_zone_policy "nsec3-dynamic-change.kasp" "nsec3" 185set_nsec3param "0" "5" "8" 186echo_i "initial check zone ${ZONE}" 187check_nsec3 188dnssec_verify 189 190# Zone: nsec3-to-nsec.kasp. 191set_zone_policy "nsec3-to-nsec.kasp" "nsec3" 192set_nsec3param "0" "5" "8" 193echo_i "initial check zone ${ZONE}" 194check_nsec3 195dnssec_verify 196 197# Zone: nsec3-to-optout.kasp. 198set_zone_policy "nsec3-to-optout.kasp" "nsec3" 199set_nsec3param "0" "5" "8" 200echo_i "initial check zone ${ZONE}" 201check_nsec3 202dnssec_verify 203 204# Zone: nsec3-from-optout.kasp. 205set_zone_policy "nsec3-from-optout.kasp" "optout" 206set_nsec3param "1" "5" "8" 207echo_i "initial check zone ${ZONE}" 208check_nsec3 209dnssec_verify 210 211# Zone: nsec3-other.kasp. 212set_zone_policy "nsec3-other.kasp" "nsec3-other" 213set_nsec3param "1" "11" "0" 214echo_i "initial check zone ${ZONE}" 215check_nsec3 216dnssec_verify 217 218# Reconfig named. 219echo_i "reconfig dnssec-policy to trigger nsec3 rollovers" 220copy_setports ns3/named2.conf.in ns3/named.conf 221rndc_reconfig ns3 10.53.0.3 222 223# Zone: nsec-to-nsec3.kasp. (reconfigured) 224set_zone_policy "nsec-to-nsec3.kasp" "nsec3" 225set_nsec3param "0" "5" "8" 226echo_i "check zone ${ZONE} after reconfig" 227check_nsec3 228dnssec_verify 229 230# Zone: nsec3.kasp. (same) 231set_zone_policy "nsec3.kasp" "nsec3" 232set_nsec3param "0" "5" "8" 233echo_i "check zone ${ZONE} after reconfig" 234check_nsec3 235dnssec_verify 236 237# Zone: nsec3-dyamic.kasp. (same) 238set_zone_policy "nsec3-dynamic.kasp" "nsec3" 239set_nsec3param "0" "5" "8" 240echo_i "check zone ${ZONE} after reconfig" 241check_nsec3 242dnssec_verify 243 244# Zone: nsec3-change.kasp. (reconfigured) 245set_zone_policy "nsec3-change.kasp" "nsec3-other" 246set_nsec3param "1" "11" "0" 247echo_i "check zone ${ZONE} after reconfig" 248check_nsec3 249dnssec_verify 250 251# Zone: nsec3-dynamic-change.kasp. (reconfigured) 252set_zone_policy "nsec3-dynamic-change.kasp" "nsec3-other" 253set_nsec3param "1" "11" "0" 254echo_i "check zone ${ZONE} after reconfig" 255check_nsec3 256dnssec_verify 257 258# Zone: nsec3-to-nsec.kasp. (reconfigured) 259set_zone_policy "nsec3-to-nsec.kasp" "nsec" 260set_nsec3param "1" "11" "0" 261echo_i "check zone ${ZONE} after reconfig" 262check_nsec 263dnssec_verify 264 265# Zone: nsec3-to-optout.kasp. (reconfigured) 266# DISABLED: 267# There is a bug in the nsec3param building code that thinks when the 268# optout bit is changed, the chain already exists. [GL #2216] 269#set_zone_policy "nsec3-to-optout.kasp" "optout" 270#set_nsec3param "1" "5" "8" 271#echo_i "check zone ${ZONE} after reconfig" 272#check_nsec3 273#dnssec_verify 274 275# Zone: nsec3-from-optout.kasp. (reconfigured) 276# DISABLED: 277# There is a bug in the nsec3param building code that thinks when the 278# optout bit is changed, the chain already exists. [GL #2216] 279#set_zone_policy "nsec3-from-optout.kasp" "nsec3" 280#set_nsec3param "0" "5" "8" 281#echo_i "check zone ${ZONE} after reconfig" 282#check_nsec3 283#dnssec_verify 284 285# Zone: nsec3-other.kasp. (same) 286set_zone_policy "nsec3-other.kasp" "nsec3-other" 287set_nsec3param "1" "11" "0" 288echo_i "check zone ${ZONE} after reconfig" 289check_nsec3 290dnssec_verify 291 292# Using rndc signing -nsec3param (should fail) 293set_zone_policy "nsec3-change.kasp" "nsec3-other" 294echo_i "use rndc signing -nsec3param ${ZONE} to change NSEC3 settings" 295rndccmd $SERVER signing -nsec3param 1 1 12 ffff $ZONE > rndc.signing.test$n.$ZONE || log_error "failed to call rndc signing -nsec3param $ZONE" 296grep "zone uses dnssec-policy, use rndc dnssec command instead" rndc.signing.test$n.$ZONE > /dev/null || log_error "rndc signing -nsec3param should fail" 297check_nsec3 298dnssec_verify 299 300# Test NSEC3 and NSEC3PARAM is the same after restart 301set_zone_policy "nsec3.kasp" "nsec3" 302set_nsec3param "0" "5" "8" 303echo_i "check zone ${ZONE} before restart" 304check_nsec3 305dnssec_verify 306 307# Restart named, NSEC3 should stay the same. 308ret=0 309echo "stop ns3" 310$PERL ../stop.pl --use-rndc --port ${CONTROLPORT} nsec3 ${DIR} || ret=1 311test "$ret" -eq 0 || echo_i "failed" 312status=$((status+ret)) 313 314ret=0 315echo "start ns3" 316start_server --noclean --restart --port ${PORT} nsec3 ${DIR} 317test "$ret" -eq 0 || echo_i "failed" 318status=$((status+ret)) 319 320prevsalt="${SALT}" 321set_zone_policy "nsec3.kasp" "nsec3" 322set_nsec3param "0" "5" "8" 323SALT="${prevsalt}" 324echo_i "check zone ${ZONE} after restart has salt ${SALT}" 325check_nsec3 326dnssec_verify 327 328# Zone: nsec3-fails-to-load.kasp. (should be fixed after reload) 329cp ns3/template.db.in ns3/nsec3-fails-to-load.kasp.db 330rndc_reload ns3 10.53.0.3 331 332set_zone_policy "nsec3-fails-to-load.kasp" "nsec3" 333set_nsec3param "0" "5" "8" 334echo_i "check zone ${ZONE} after reload" 335check_nsec3 336dnssec_verify 337 338echo_i "exit status: $status" 339[ $status -eq 0 ] || exit 1 340