Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3878c145c9 | ||
|
|
4acbfbc2d1 | ||
|
|
1ef9a32de7 | ||
|
|
6c738fe323 |
+86
-121
@@ -56,16 +56,6 @@ variables:
|
||||
# Some jobs may clean up the build artifacts unless this is set to 0.
|
||||
CLEAN_BUILD_ARTIFACTS_ON_SUCCESS: 1
|
||||
|
||||
# DNS Shotgun performance testing defaults
|
||||
SHOTGUN_ROUNDS: 1
|
||||
SHOTGUN_DURATION: 120
|
||||
# allow unlimited improvements against baseline
|
||||
SHOTGUN_EVAL_THRESHOLD_CPU_MIN: '-inf'
|
||||
SHOTGUN_EVAL_THRESHOLD_MEMORY_MIN: '-inf'
|
||||
SHOTGUN_EVAL_THRESHOLD_RCODE_MAX: '+inf'
|
||||
SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_MIN: '-inf'
|
||||
SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MIN: '-inf'
|
||||
|
||||
default:
|
||||
# Allow all running CI jobs to be automatically canceled when a new
|
||||
# version of a branch is pushed.
|
||||
@@ -117,55 +107,16 @@ stages:
|
||||
- runner-manager
|
||||
- aarch64
|
||||
|
||||
.freebsd-autoscaler-13-amd64-tags: &freebsd_autoscaler_13_amd64_tags
|
||||
# Autoscaling GitLab Runner on AWS EC2 (FreeBSD)
|
||||
|
||||
.freebsd-stress-amd64: &freebsd_stress_amd64
|
||||
tags:
|
||||
- amd64
|
||||
- autoscaler
|
||||
- bsd-stress-test
|
||||
- aws
|
||||
- bsd-stress-test-1
|
||||
- autoscaler
|
||||
- shell
|
||||
- stress-test
|
||||
|
||||
.freebsd-autoscaler-14-amd64-tags: &freebsd_autoscaler_14_amd64_tags
|
||||
tags:
|
||||
- amd64
|
||||
- autoscaler
|
||||
- aws
|
||||
- bsd-stress-test-2
|
||||
- shell
|
||||
- stress-test
|
||||
|
||||
.freebsd-autoscaler-amd64: &freebsd_autoscaler_amd64
|
||||
variables:
|
||||
CC: clang
|
||||
CFLAGS: "${CFLAGS_COMMON} -Og"
|
||||
# Even though there's only one job per runtime environment, the GitLab
|
||||
# "instance" executor insists on cloning the Git repository to a path that
|
||||
# contains a variable number from zero to the "maximum concurrent instances
|
||||
# count" allowed on the GitLab Runner. See the "0" directory in this
|
||||
# example path: /home/ec2-user/builds/t1_4FZzvz/0/isc-projects/bind9/.git/.
|
||||
#
|
||||
# This is not a problem for isolated jobs like "stress" tests that depend
|
||||
# on no other jobs. However, it is a problem for jobs that need other jobs'
|
||||
# artifacts. For example, a system test job that has its Git repo cloned to
|
||||
# the "/1/" sub-path will fail if it downloads build job artifacts that
|
||||
# have ./configure output files with "/0/" in its sub-path recorded.
|
||||
GIT_CLONE_PATH: "/home/ec2-user/builds/${CI_PROJECT_PATH}/"
|
||||
# Use MIT Kerberos5 for BIND 9 GSS-API support because of FreeBSD Heimdal
|
||||
# incompatibility; see https://bugs.freebsd.org/275241.
|
||||
EXTRA_CONFIGURE: "${WITH_READLINE_EDITLINE} --with-gssapi=/usr/local/bin/krb5-config"
|
||||
|
||||
# Autoscaling GitLab Runner on AWS EC2 (FreeBSD 13)
|
||||
|
||||
.freebsd-autoscaler-13-amd64: &freebsd_autoscaler_13_amd64
|
||||
<<: *freebsd_autoscaler_amd64
|
||||
<<: *freebsd_autoscaler_13_amd64_tags
|
||||
|
||||
# Autoscaling GitLab Runner on AWS EC2 (FreeBSD 14)
|
||||
|
||||
.freebsd-autoscaler-14-amd64: &freebsd_autoscaler_14_amd64
|
||||
<<: *freebsd_autoscaler_amd64
|
||||
<<: *freebsd_autoscaler_14_amd64_tags
|
||||
|
||||
### Docker Image Templates
|
||||
|
||||
@@ -253,6 +204,14 @@ stages:
|
||||
|
||||
### QCOW2 Image Templates
|
||||
|
||||
.freebsd-13-amd64: &freebsd_13_amd64_image
|
||||
image: "freebsd-13.4-x86_64"
|
||||
<<: *libvirt_amd64
|
||||
|
||||
.freebsd-14-amd64: &freebsd_14_amd64_image
|
||||
image: "freebsd-14.2-x86_64"
|
||||
<<: *libvirt_amd64
|
||||
|
||||
.openbsd-amd64: &openbsd_amd64_image
|
||||
image: "openbsd-7.6-x86_64"
|
||||
<<: *libvirt_amd64
|
||||
@@ -260,18 +219,31 @@ stages:
|
||||
### Job Templates
|
||||
|
||||
.api-pipelines-schedules-tags-triggers-web-triggering-rules: &api_pipelines_schedules_tags_triggers_web_triggering_rules
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE =~ /^(api|pipeline|schedule|trigger|web)$/'
|
||||
- if: '$CI_COMMIT_TAG != null'
|
||||
only:
|
||||
- api
|
||||
- pipelines
|
||||
- schedules
|
||||
- tags
|
||||
- triggers
|
||||
- web
|
||||
|
||||
.api-pipelines-schedules-triggers-web-triggering-rules: &api_pipelines_schedules_triggers_web_triggering_rules
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE =~ /^(api|pipeline|schedule|trigger|web)$/'
|
||||
only:
|
||||
- api
|
||||
- pipelines
|
||||
- schedules
|
||||
- triggers
|
||||
- web
|
||||
|
||||
.default-triggering-rules: &default_triggering_rules
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE =~ /^(api|merge_request_event|pipeline|schedule|trigger|web)$/'
|
||||
- if: '$CI_COMMIT_TAG != null'
|
||||
only:
|
||||
- api
|
||||
- merge_requests
|
||||
- pipelines
|
||||
- schedules
|
||||
- tags
|
||||
- triggers
|
||||
- web
|
||||
|
||||
.precheck: &precheck_job
|
||||
<<: *default_triggering_rules
|
||||
@@ -371,38 +343,18 @@ stages:
|
||||
|
||||
.shotgun: &shotgun_job
|
||||
<<: *base_image
|
||||
<<: *api_pipelines_schedules_tags_triggers_web_triggering_rules
|
||||
stage: performance
|
||||
rules:
|
||||
- &shotgun_rule_mr
|
||||
if: '$CI_MERGE_REQUEST_DIFF_BASE_SHA != null'
|
||||
variables:
|
||||
BASELINE: '$CI_MERGE_REQUEST_DIFF_BASE_SHA'
|
||||
- &shotgun_rule_tag
|
||||
if: '$CI_COMMIT_TAG != null'
|
||||
variables:
|
||||
SHOTGUN_ROUNDS: 3
|
||||
- &shotgun_rule_other
|
||||
if: '$CI_PIPELINE_SOURCE =~ /^(api|pipeline|schedule|trigger|web)$/'
|
||||
script:
|
||||
- if [ -z "$BASELINE" ]; then export BASELINE=$BIND_BASELINE_VERSION; fi # this dotenv variable can't be set in the rules section, because rules are evaluated before any jobs run
|
||||
- if [ -z "$CI_COMMIT_TAG" ]; then export SHOTGUN_ROUNDS=1; else export SHOTGUN_ROUNDS=3; fi
|
||||
- PIPELINE_ID=$(curl -s -X POST --fail
|
||||
-F "token=$CI_JOB_TOKEN"
|
||||
-F ref=main
|
||||
-F "variables[SHOTGUN_TEST_VERSION]=['$CI_COMMIT_REF_NAME', '$BASELINE']"
|
||||
-F "variables[SHOTGUN_TEST_VERSION]=['$CI_COMMIT_REF_NAME', '$BIND_BASELINE_VERSION']"
|
||||
-F "variables[SHOTGUN_DURATION]=300"
|
||||
-F "variables[SHOTGUN_ROUNDS]=$SHOTGUN_ROUNDS"
|
||||
-F "variables[SHOTGUN_TRAFFIC_MULTIPLIER]=$SHOTGUN_TRAFFIC_MULTIPLIER"
|
||||
-F "variables[SHOTGUN_SCENARIO]=$SHOTGUN_SCENARIO"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_CPU_MIN]=$SHOTGUN_EVAL_THRESHOLD_CPU_MIN"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_CPU_MAX]=$SHOTGUN_EVAL_THRESHOLD_CPU_MAX"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_MEMORY_MIN]=$SHOTGUN_EVAL_THRESHOLD_MEMORY_MIN"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_MEMORY_MAX]=$SHOTGUN_EVAL_THRESHOLD_MEMORY_MAX"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_RCODE_MIN]=$SHOTGUN_EVAL_THRESHOLD_RCODE_MIN"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_RCODE_MAX]=$SHOTGUN_EVAL_THRESHOLD_RCODE_MAX"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_MIN]=$SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_MIN"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_MAX]=$SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_MAX"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MIN]=$SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MIN"
|
||||
-F "variables[SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MAX]=$SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MAX"
|
||||
https://gitlab.isc.org/api/v4/projects/188/trigger/pipeline | jq .id)
|
||||
- util/ci-wait-shotgun.py $PIPELINE_ID
|
||||
needs:
|
||||
@@ -559,8 +511,6 @@ misc:
|
||||
- if git grep SYSTEMTESTTOP -- ':!.gitlab-ci.yml'; then echo 'Please use relative paths instead of $SYSTEMTESTTOP.'; exit 1; fi
|
||||
- bash util/unused-headers.sh
|
||||
- bash util/xmllint-html.sh
|
||||
# Check dangling symlinks in the repository
|
||||
- if find . -xtype l | grep .; then exit 1; fi
|
||||
needs: []
|
||||
artifacts:
|
||||
paths:
|
||||
@@ -669,8 +619,9 @@ danger:
|
||||
script:
|
||||
- pip install git+https://gitlab.isc.org/isc-projects/hazard.git
|
||||
- hazard
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
only:
|
||||
refs:
|
||||
- merge_requests
|
||||
|
||||
checkbashisms:
|
||||
<<: *precheck_job
|
||||
@@ -1338,7 +1289,7 @@ gcc:tsan:
|
||||
variables:
|
||||
CC: gcc
|
||||
CFLAGS: "${CFLAGS_COMMON} -Wno-stringop-overread -ggdb -O2 -fsanitize=thread"
|
||||
LDFLAGS: "-fsanitize=thread -Wl,--disable-new-dtags"
|
||||
LDFLAGS: "-fsanitize=thread"
|
||||
EXTRA_CONFIGURE: "--with-libidn2 --enable-pthread-rwlock --without-jemalloc PKG_CONFIG_PATH=/opt/tsan/lib/pkgconfig"
|
||||
<<: *tsan_fedora_41_amd64_image
|
||||
<<: *build_job
|
||||
@@ -1367,8 +1318,7 @@ clang:tsan:
|
||||
variables:
|
||||
CC: "${CLANG}"
|
||||
CFLAGS: "${CFLAGS_COMMON} -ggdb -O2 -fsanitize=thread"
|
||||
# -Wl,--disable-new-dtags ensures that Clang creates valid TSAN reports
|
||||
LDFLAGS: "-fsanitize=thread -Wl,--disable-new-dtags"
|
||||
LDFLAGS: "-fsanitize=thread"
|
||||
EXTRA_CONFIGURE: "--with-libidn2 --enable-pthread-rwlock --without-jemalloc PKG_CONFIG_PATH=/opt/tsan/lib/pkgconfig"
|
||||
|
||||
system:clang:tsan:
|
||||
@@ -1447,19 +1397,27 @@ unit:clang:bookworm:amd64:
|
||||
# Jobs for Clang builds on FreeBSD 13 (amd64)
|
||||
|
||||
clang:freebsd13:amd64:
|
||||
variables:
|
||||
CFLAGS: "${CFLAGS_COMMON}"
|
||||
# Use MIT Kerberos5 for BIND 9 GSS-API support because of FreeBSD Heimdal
|
||||
# incompatibility; see https://bugs.freebsd.org/275241.
|
||||
EXTRA_CONFIGURE: "${WITH_READLINE_LIBEDIT} --with-gssapi=/usr/local/bin/krb5-config"
|
||||
USER: gitlab-runner
|
||||
<<: *freebsd_13_amd64_image
|
||||
<<: *build_job
|
||||
<<: *freebsd_autoscaler_13_amd64
|
||||
|
||||
system:clang:freebsd13:amd64:
|
||||
<<: *freebsd_13_amd64_image
|
||||
<<: *system_test_job
|
||||
<<: *freebsd_autoscaler_13_amd64
|
||||
variables:
|
||||
USER: gitlab-runner
|
||||
needs:
|
||||
- job: clang:freebsd13:amd64
|
||||
artifacts: true
|
||||
|
||||
unit:clang:freebsd13:amd64:
|
||||
<<: *freebsd_13_amd64_image
|
||||
<<: *unit_test_job
|
||||
<<: *freebsd_autoscaler_13_amd64
|
||||
needs:
|
||||
- job: clang:freebsd13:amd64
|
||||
artifacts: true
|
||||
@@ -1467,19 +1425,27 @@ unit:clang:freebsd13:amd64:
|
||||
# Jobs for Clang builds on FreeBSD 14 (amd64)
|
||||
|
||||
clang:freebsd14:amd64:
|
||||
variables:
|
||||
CFLAGS: "${CFLAGS_COMMON}"
|
||||
# Use MIT Kerberos5 for BIND 9 GSS-API support because of FreeBSD Heimdal
|
||||
# incompatibility; see https://bugs.freebsd.org/275241.
|
||||
EXTRA_CONFIGURE: "${WITH_READLINE_EDITLINE} --with-gssapi=/usr/local/bin/krb5-config"
|
||||
USER: gitlab-runner
|
||||
<<: *freebsd_14_amd64_image
|
||||
<<: *build_job
|
||||
<<: *freebsd_autoscaler_14_amd64
|
||||
|
||||
system:clang:freebsd14:amd64:
|
||||
<<: *freebsd_14_amd64_image
|
||||
<<: *system_test_job
|
||||
<<: *freebsd_autoscaler_14_amd64
|
||||
variables:
|
||||
USER: gitlab-runner
|
||||
needs:
|
||||
- job: clang:freebsd14:amd64
|
||||
artifacts: true
|
||||
|
||||
unit:clang:freebsd14:amd64:
|
||||
<<: *freebsd_14_amd64_image
|
||||
<<: *unit_test_job
|
||||
<<: *freebsd_autoscaler_14_amd64
|
||||
needs:
|
||||
- job: clang:freebsd14:amd64
|
||||
artifacts: true
|
||||
@@ -1528,8 +1494,8 @@ release:
|
||||
artifacts: true
|
||||
- job: docs
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG != null'
|
||||
only:
|
||||
- tags
|
||||
artifacts:
|
||||
paths:
|
||||
- "*-release"
|
||||
@@ -1572,8 +1538,8 @@ sign:
|
||||
needs:
|
||||
- job: release
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG != null'
|
||||
only:
|
||||
- tags
|
||||
when: manual
|
||||
allow_failure: false
|
||||
|
||||
@@ -1625,8 +1591,10 @@ coverity:
|
||||
- cov-int.tar.gz
|
||||
expire_in: "1 week"
|
||||
when: on_failure
|
||||
rules:
|
||||
- if: '$COVERITY_SCAN_PROJECT_NAME != null && $COVERITY_SCAN_TOKEN != null'
|
||||
only:
|
||||
variables:
|
||||
- $COVERITY_SCAN_PROJECT_NAME
|
||||
- $COVERITY_SCAN_TOKEN
|
||||
|
||||
# Respdiff tests
|
||||
|
||||
@@ -1661,9 +1629,9 @@ respdiff:tsan:
|
||||
<<: *default_triggering_rules
|
||||
<<: *tsan_debian_bookworm_amd64_image
|
||||
variables:
|
||||
CC: "${CLANG}"
|
||||
CFLAGS: "${CFLAGS_COMMON} -ggdb -O2 -fsanitize=thread"
|
||||
LDFLAGS: "-fsanitize=thread -Wl,--disable-new-dtags"
|
||||
CC: gcc
|
||||
CFLAGS: "${CFLAGS_COMMON} -Og -fsanitize=thread"
|
||||
LDFLAGS: "-fsanitize=thread"
|
||||
EXTRA_CONFIGURE: "--enable-pthread-rwlock --without-jemalloc PKG_CONFIG_PATH=/opt/tsan/lib/pkgconfig"
|
||||
MAX_DISAGREEMENTS_PERCENTAGE: "0.15"
|
||||
TSAN_OPTIONS: "${TSAN_OPTIONS_DEBIAN}"
|
||||
@@ -1702,28 +1670,24 @@ shotgun:tcp:
|
||||
variables:
|
||||
SHOTGUN_SCENARIO: tcp
|
||||
SHOTGUN_TRAFFIC_MULTIPLIER: 13
|
||||
when: delayed
|
||||
start_in: 5 minutes
|
||||
|
||||
shotgun:dot:
|
||||
<<: *shotgun_job
|
||||
variables:
|
||||
SHOTGUN_SCENARIO: dot
|
||||
SHOTGUN_TRAFFIC_MULTIPLIER: 6
|
||||
rules: &shotgun_rules_manual_mr
|
||||
- if: '$CI_MERGE_REQUEST_DIFF_BASE_SHA != null'
|
||||
variables:
|
||||
BASELINE: '$CI_MERGE_REQUEST_DIFF_BASE_SHA'
|
||||
when: manual # don't run on each MR unless requested
|
||||
allow_failure: true
|
||||
- *shotgun_rule_tag
|
||||
- *shotgun_rule_other
|
||||
when: delayed
|
||||
start_in: 5 minutes
|
||||
|
||||
shotgun:doh-get:
|
||||
<<: *shotgun_job
|
||||
variables:
|
||||
SHOTGUN_SCENARIO: doh-get
|
||||
SHOTGUN_TRAFFIC_MULTIPLIER: 3
|
||||
SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_MAX: 0.3 # bump from the default due to increased tail-end jitter
|
||||
rules: *shotgun_rules_manual_mr
|
||||
when: delayed
|
||||
start_in: 5 minutes
|
||||
|
||||
.stress-test: &stress_test
|
||||
stage: performance
|
||||
@@ -1762,8 +1726,8 @@ fsck:
|
||||
- git clone https://gitlab.isc.org/isc-projects/bind9.git bind9-full-clone
|
||||
- cd bind9-full-clone/
|
||||
- git fsck
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
only:
|
||||
- schedules
|
||||
needs: []
|
||||
|
||||
gcov:
|
||||
@@ -1815,8 +1779,9 @@ pairwise:
|
||||
- pairwise-model.txt
|
||||
- pairwise-output.*.txt
|
||||
when: on_failure
|
||||
rules:
|
||||
- if: '$PAIRWISE_TESTING != null'
|
||||
only:
|
||||
variables:
|
||||
- $PAIRWISE_TESTING
|
||||
|
||||
.post_merge_template: &post_merge
|
||||
<<: *base_image
|
||||
|
||||
@@ -761,7 +761,7 @@ cleanup:
|
||||
}
|
||||
|
||||
if (mctx != NULL) {
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
}
|
||||
|
||||
return result == ISC_R_SUCCESS ? 0 : 1;
|
||||
|
||||
@@ -577,7 +577,7 @@ main(int argc, char **argv) {
|
||||
fprintf(errout, "OK\n");
|
||||
}
|
||||
destroy();
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
return (result == ISC_R_SUCCESS) ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ options {\n\
|
||||
isc_mem_stats(mctx, stderr);
|
||||
}
|
||||
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ nsupdate -k <keyfile>\n");
|
||||
isc_mem_stats(mctx, stderr);
|
||||
}
|
||||
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+36
-2
@@ -26,12 +26,16 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
|
||||
#include <isc/async.h>
|
||||
#include <isc/attributes.h>
|
||||
#include <isc/base64.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/lib.h>
|
||||
#include <isc/log.h>
|
||||
@@ -163,6 +167,10 @@ static dns_fixedname_t qfn;
|
||||
/* Default trust anchors */
|
||||
static char anchortext[] = TRUST_ANCHORS;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
static OSSL_PROVIDER *fips = NULL, *base = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Static function prototypes
|
||||
*/
|
||||
@@ -1611,7 +1619,24 @@ preparse_args(int argc, char **argv) {
|
||||
while (strpbrk(option, single_dash_opts) == &option[0]) {
|
||||
switch (option[0]) {
|
||||
case 'F':
|
||||
if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
fips = OSSL_PROVIDER_load(NULL, "fips");
|
||||
if (fips == NULL) {
|
||||
ERR_clear_error();
|
||||
fatal("Failed to load FIPS provider");
|
||||
}
|
||||
base = OSSL_PROVIDER_load(NULL, "base");
|
||||
if (base == NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
ERR_clear_error();
|
||||
fatal("Failed to load base provider");
|
||||
}
|
||||
#endif
|
||||
/* Already in FIPS mode? */
|
||||
if (isc_fips_mode()) {
|
||||
break;
|
||||
}
|
||||
if (isc_fips_set_mode(1) != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
}
|
||||
break;
|
||||
@@ -2284,5 +2309,14 @@ cleanup:
|
||||
|
||||
isc_managers_destroy(&mctx, &loopmgr, &netmgr);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (base != NULL) {
|
||||
OSSL_PROVIDER_unload(base);
|
||||
}
|
||||
if (fips != NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+36
-2
@@ -20,8 +20,8 @@
|
||||
#include <time.h>
|
||||
|
||||
#include <isc/attributes.h>
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/dir.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/lib.h>
|
||||
#include <isc/loop.h>
|
||||
#include <isc/netaddr.h>
|
||||
@@ -73,6 +73,14 @@ static bool short_form = false, printcmd = true, plusquest = false,
|
||||
static uint32_t splitwidth = 0xffffffff;
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
static OSSL_PROVIDER *fips = NULL, *base = NULL;
|
||||
#endif
|
||||
|
||||
/*% opcode text */
|
||||
static const char *const opcodetext[] = {
|
||||
@@ -2923,7 +2931,24 @@ preparse_args(int argc, char **argv) {
|
||||
debugging = true;
|
||||
break;
|
||||
case 'F':
|
||||
if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
fips = OSSL_PROVIDER_load(NULL, "fips");
|
||||
if (fips == NULL) {
|
||||
ERR_clear_error();
|
||||
fatal("Failed to load FIPS provider");
|
||||
}
|
||||
base = OSSL_PROVIDER_load(NULL, "base");
|
||||
if (base == NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
ERR_clear_error();
|
||||
fatal("Failed to load base provider");
|
||||
}
|
||||
#endif
|
||||
/* Already in FIPS mode? */
|
||||
if (isc_fips_mode()) {
|
||||
break;
|
||||
}
|
||||
if (isc_fips_set_mode(1) != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
}
|
||||
break;
|
||||
@@ -3451,5 +3476,14 @@ main(int argc, char **argv) {
|
||||
dig_startup();
|
||||
dig_shutdown();
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (base != NULL) {
|
||||
OSSL_PROVIDER_unload(base);
|
||||
}
|
||||
if (fips != NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
}
|
||||
#endif
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <isc/attributes.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/commandline.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/lib.h>
|
||||
#include <isc/loop.h>
|
||||
#include <isc/netaddr.h>
|
||||
|
||||
@@ -41,14 +41,6 @@ dnssec_keygen_LDADD = \
|
||||
$(LDADD) \
|
||||
$(OPENSSL_LIBS)
|
||||
|
||||
dnssec_ksr_CPPFLAGS= \
|
||||
$(AM_CPPFLAGS) \
|
||||
$(OPENSSL_CFLAGS)
|
||||
|
||||
dnssec_ksr_LDADD = \
|
||||
$(LDADD) \
|
||||
$(OPENSSL_LIBS)
|
||||
|
||||
dnssec_signzone_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
$(OPENSSL_CFLAGS)
|
||||
|
||||
@@ -1075,7 +1075,7 @@ cleanup(void) {
|
||||
if (print_mem_stats && verbose > 10) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -543,7 +543,7 @@ main(int argc, char **argv) {
|
||||
if (verbose > 10) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
fflush(stdout);
|
||||
if (ferror(stdout)) {
|
||||
|
||||
@@ -456,7 +456,7 @@ main(int argc, char **argv) {
|
||||
if (verbose > 10) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
fflush(stdout);
|
||||
if (ferror(stdout)) {
|
||||
|
||||
@@ -746,7 +746,7 @@ main(int argc, char **argv) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
isc_mem_free(mctx, label);
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
if (freeit != NULL) {
|
||||
free(freeit);
|
||||
|
||||
+47
-11
@@ -38,7 +38,7 @@
|
||||
#include <isc/attributes.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/commandline.h>
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/lib.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
@@ -58,6 +58,11 @@
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
|
||||
#include "dnssectool.h"
|
||||
|
||||
const char *program = "dnssec-keygen";
|
||||
@@ -146,7 +151,7 @@ usage(void) {
|
||||
fprintf(stderr, " -l <file>: configuration file with dnssec-policy "
|
||||
"statement\n");
|
||||
fprintf(stderr, " -a <algorithm>:\n");
|
||||
if (!isc_crypto_fips_mode()) {
|
||||
if (!isc_fips_mode()) {
|
||||
fprintf(stderr, " RSASHA1 | NSEC3RSASHA1 |\n");
|
||||
}
|
||||
fprintf(stderr, " RSASHA256 | RSASHA512 |\n");
|
||||
@@ -154,7 +159,7 @@ usage(void) {
|
||||
fprintf(stderr, " ED25519 | ED448\n");
|
||||
fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
|
||||
fprintf(stderr, " -b <key size in bits>:\n");
|
||||
if (!isc_crypto_fips_mode()) {
|
||||
if (!isc_fips_mode()) {
|
||||
fprintf(stderr, " RSASHA1:\t[%d..%d]\n", min_rsa,
|
||||
MAX_RSA);
|
||||
fprintf(stderr, " NSEC3RSASHA1:\t[%d..%d]\n", min_rsa,
|
||||
@@ -283,7 +288,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
||||
fatal("unsupported algorithm: %s", algstr);
|
||||
}
|
||||
|
||||
if (isc_crypto_fips_mode()) {
|
||||
if (isc_fips_mode()) {
|
||||
/* verify only in FIPS mode */
|
||||
switch (ctx->alg) {
|
||||
case DST_ALG_RSASHA1:
|
||||
@@ -336,7 +341,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
||||
switch (ctx->alg) {
|
||||
case DST_ALG_RSASHA1:
|
||||
case DST_ALG_NSEC3RSASHA1:
|
||||
if (isc_crypto_fips_mode()) {
|
||||
if (isc_fips_mode()) {
|
||||
fatal("key size not specified (-b "
|
||||
"option)");
|
||||
}
|
||||
@@ -496,7 +501,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
||||
switch (ctx->alg) {
|
||||
case DNS_KEYALG_RSASHA1:
|
||||
case DNS_KEYALG_NSEC3RSASHA1:
|
||||
if (isc_crypto_fips_mode()) {
|
||||
if (isc_fips_mode()) {
|
||||
fatal("SHA1 based keys not supported in FIPS mode");
|
||||
}
|
||||
FALLTHROUGH;
|
||||
@@ -842,6 +847,10 @@ main(int argc, char **argv) {
|
||||
isc_textregion_t r;
|
||||
unsigned char c;
|
||||
int ch;
|
||||
bool set_fips_mode = false;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
OSSL_PROVIDER *fips = NULL, *base = NULL;
|
||||
#endif
|
||||
|
||||
keygen_ctx_t ctx = {
|
||||
.options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC,
|
||||
@@ -1100,9 +1109,7 @@ main(int argc, char **argv) {
|
||||
ctx.prepub = strtottl(isc_commandline_argument);
|
||||
break;
|
||||
case 'F':
|
||||
if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
}
|
||||
set_fips_mode = true;
|
||||
break;
|
||||
case '?':
|
||||
if (isc_commandline_option != '?') {
|
||||
@@ -1129,11 +1136,32 @@ main(int argc, char **argv) {
|
||||
ctx.quiet = true;
|
||||
}
|
||||
|
||||
if (set_fips_mode) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
fips = OSSL_PROVIDER_load(NULL, "fips");
|
||||
if (fips == NULL) {
|
||||
ERR_clear_error();
|
||||
fatal("Failed to load FIPS provider");
|
||||
}
|
||||
base = OSSL_PROVIDER_load(NULL, "base");
|
||||
if (base == NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
ERR_clear_error();
|
||||
fatal("Failed to load base provider");
|
||||
}
|
||||
#endif
|
||||
if (!isc_fips_mode()) {
|
||||
if (isc_fips_set_mode(1) != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The DST subsystem will set FIPS mode if requested at build time.
|
||||
* The minimum sizes are both raised to 2048.
|
||||
*/
|
||||
if (isc_crypto_fips_mode()) {
|
||||
if (isc_fips_mode()) {
|
||||
min_rsa = min_dh = 2048;
|
||||
}
|
||||
|
||||
@@ -1280,8 +1308,16 @@ main(int argc, char **argv) {
|
||||
if (verbose > 10) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (base != NULL) {
|
||||
OSSL_PROVIDER_unload(base);
|
||||
}
|
||||
if (fips != NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
}
|
||||
#endif
|
||||
if (freeit != NULL) {
|
||||
free(freeit);
|
||||
}
|
||||
|
||||
+27
-6
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/commandline.h>
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/lex.h>
|
||||
#include <isc/lib.h>
|
||||
#include <isc/mem.h>
|
||||
@@ -362,7 +362,7 @@ create_key(ksr_ctx_t *ksr, dns_kasp_t *kasp, dns_kasp_key_t *kaspkey,
|
||||
switch (ksr->alg) {
|
||||
case DST_ALG_RSASHA1:
|
||||
case DST_ALG_NSEC3RSASHA1:
|
||||
if (isc_crypto_fips_mode()) {
|
||||
if (isc_fips_mode()) {
|
||||
/* verify-only in FIPS mode */
|
||||
fatal("unsupported algorithm: %s", algstr);
|
||||
}
|
||||
@@ -1348,6 +1348,10 @@ main(int argc, char *argv[]) {
|
||||
isc_buffer_t buf;
|
||||
int ch;
|
||||
char *endp;
|
||||
bool set_fips_mode = false;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
OSSL_PROVIDER *fips = NULL, *base = NULL;
|
||||
#endif
|
||||
ksr_ctx_t ksr = {
|
||||
.now = isc_stdtime_now(),
|
||||
};
|
||||
@@ -1367,9 +1371,7 @@ main(int argc, char *argv[]) {
|
||||
ksr.now, &ksr.setend);
|
||||
break;
|
||||
case 'F':
|
||||
if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
}
|
||||
set_fips_mode = true;
|
||||
break;
|
||||
case 'f':
|
||||
ksr.file = isc_commandline_argument;
|
||||
@@ -1423,12 +1425,31 @@ main(int argc, char *argv[]) {
|
||||
* The DST subsystem will set FIPS mode if requested at build time.
|
||||
* The minimum sizes are both raised to 2048.
|
||||
*/
|
||||
if (isc_crypto_fips_mode()) {
|
||||
if (isc_fips_mode()) {
|
||||
min_rsa = min_dh = 2048;
|
||||
}
|
||||
|
||||
setup_logging();
|
||||
|
||||
if (set_fips_mode) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
fips = OSSL_PROVIDER_load(NULL, "fips");
|
||||
if (fips == NULL) {
|
||||
fatal("Failed to load FIPS provider");
|
||||
}
|
||||
base = OSSL_PROVIDER_load(NULL, "base");
|
||||
if (base == NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
fatal("Failed to load base provider");
|
||||
}
|
||||
#endif
|
||||
if (!isc_fips_mode()) {
|
||||
if (isc_fips_set_mode(1) != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* zone */
|
||||
namestr = argv[1];
|
||||
name = dns_fixedname_initname(&fname);
|
||||
|
||||
@@ -248,7 +248,7 @@ cleanup:
|
||||
if (dir != NULL) {
|
||||
isc_mem_free(mctx, dir);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -949,7 +949,7 @@ main(int argc, char **argv) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
isc_mem_free(mctx, directory);
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <isc/commandline.h>
|
||||
#include <isc/dir.h>
|
||||
#include <isc/file.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/lib.h>
|
||||
@@ -89,6 +90,10 @@
|
||||
#include <dns/zoneverify.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
|
||||
#include "dnssectool.h"
|
||||
|
||||
@@ -3375,6 +3380,10 @@ main(int argc, char *argv[]) {
|
||||
bool set_optout = false;
|
||||
bool set_iter = false;
|
||||
bool nonsecify = false;
|
||||
bool set_fips_mode = false;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
OSSL_PROVIDER *fips = NULL, *base = NULL;
|
||||
#endif
|
||||
|
||||
atomic_init(&shuttingdown, false);
|
||||
atomic_init(&finished, false);
|
||||
@@ -3663,9 +3672,7 @@ main(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
}
|
||||
set_fips_mode = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
@@ -3736,6 +3743,27 @@ main(int argc, char *argv[]) {
|
||||
|
||||
isc_managers_create(&mctx, nloops, &loopmgr, &netmgr);
|
||||
|
||||
if (set_fips_mode) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
fips = OSSL_PROVIDER_load(NULL, "fips");
|
||||
if (fips == NULL) {
|
||||
ERR_clear_error();
|
||||
fatal("Failed to load FIPS provider");
|
||||
}
|
||||
base = OSSL_PROVIDER_load(NULL, "base");
|
||||
if (base == NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
ERR_clear_error();
|
||||
fatal("Failed to load base provider");
|
||||
}
|
||||
#endif
|
||||
if (!isc_fips_mode()) {
|
||||
if (isc_fips_set_mode(1) != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setup_logging();
|
||||
|
||||
argc -= isc_commandline_index;
|
||||
@@ -4107,6 +4135,15 @@ main(int argc, char *argv[]) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (base != NULL) {
|
||||
OSSL_PROVIDER_unload(base);
|
||||
}
|
||||
if (fips != NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
}
|
||||
#endif
|
||||
|
||||
isc_managers_destroy(&mctx, &loopmgr, &netmgr);
|
||||
|
||||
if (printstats) {
|
||||
|
||||
@@ -330,7 +330,7 @@ main(int argc, char *argv[]) {
|
||||
if (verbose > 10) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
return result == ISC_R_SUCCESS ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/condition.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/loop.h>
|
||||
#include <isc/mutex.h>
|
||||
|
||||
@@ -86,6 +86,7 @@ EXTERN named_server_t *named_g_server INIT(NULL);
|
||||
/*
|
||||
* Logging.
|
||||
*/
|
||||
EXTERN bool named_g_logging INIT(false);
|
||||
EXTERN unsigned int named_g_debuglevel INIT(0);
|
||||
|
||||
/*
|
||||
|
||||
@@ -52,6 +52,8 @@ named_log_init(bool safe) {
|
||||
named_log_setdefaultsslkeylogfile(lcfg);
|
||||
rcu_read_unlock();
|
||||
|
||||
named_g_logging = true;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
|
||||
+110
-37
@@ -30,6 +30,7 @@
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/dir.h>
|
||||
#include <isc/file.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/httpd.h>
|
||||
#include <isc/lib.h>
|
||||
@@ -90,6 +91,10 @@
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBXML2
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xmlversion.h>
|
||||
@@ -150,13 +155,24 @@ static bool transferstuck = false;
|
||||
static bool disable6 = false;
|
||||
static bool disable4 = false;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
static OSSL_PROVIDER *fips = NULL, *base = NULL;
|
||||
#endif
|
||||
|
||||
void
|
||||
named_main_earlywarning(const char *format, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
isc_log_vwrite(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_WARNING, format, args);
|
||||
if (named_g_logging) {
|
||||
isc_log_vwrite(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_WARNING, format, args);
|
||||
} else {
|
||||
fprintf(stderr, "%s: ", program_name);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -165,10 +181,18 @@ named_main_earlyfatal(const char *format, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
isc_log_vwrite(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, format, args);
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, "exiting (due to early fatal error)");
|
||||
if (named_g_logging) {
|
||||
isc_log_vwrite(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, format, args);
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL,
|
||||
"exiting (due to early fatal error)");
|
||||
} else {
|
||||
fprintf(stderr, "%s: ", program_name);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
_exit(EXIT_FAILURE);
|
||||
@@ -185,19 +209,26 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type,
|
||||
* Handle assertion failures.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reset the assertion callback in case it is the log
|
||||
* routines causing the assertion.
|
||||
*/
|
||||
isc_assertion_setcallback(NULL);
|
||||
if (named_g_logging) {
|
||||
/*
|
||||
* Reset the assertion callback in case it is the log
|
||||
* routines causing the assertion.
|
||||
*/
|
||||
isc_assertion_setcallback(NULL);
|
||||
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, "%s:%d: %s(%s) failed", file, line,
|
||||
isc_assertion_typetotext(type), cond);
|
||||
isc_backtrace_log(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL);
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, "exiting (due to assertion failure)");
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, "%s:%d: %s(%s) failed", file,
|
||||
line, isc_assertion_typetotext(type), cond);
|
||||
isc_backtrace_log(NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL);
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL,
|
||||
"exiting (due to assertion failure)");
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d: %s(%s) failed\n", file, line,
|
||||
isc_assertion_typetotext(type), cond);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
if (named_g_coreok) {
|
||||
abort();
|
||||
@@ -216,20 +247,27 @@ library_fatal_error(const char *file, int line, const char *func,
|
||||
* Handle isc_error_fatal() calls from our libraries.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reset the error callback in case it is the log
|
||||
* routines causing the assertion.
|
||||
*/
|
||||
isc_error_setfatal(NULL);
|
||||
if (named_g_logging) {
|
||||
/*
|
||||
* Reset the error callback in case it is the log
|
||||
* routines causing the assertion.
|
||||
*/
|
||||
isc_error_setfatal(NULL);
|
||||
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, "%s:%d:%s(): fatal error: ", file, line,
|
||||
func);
|
||||
isc_log_vwrite(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, format, args);
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL,
|
||||
"exiting (due to fatal error in library)");
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL,
|
||||
"%s:%d:%s(): fatal error: ", file, line, func);
|
||||
isc_log_vwrite(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL, format, args);
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_CRITICAL,
|
||||
"exiting (due to fatal error in library)");
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d:%s(): fatal error: ", file, line, func);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
if (named_g_coreok) {
|
||||
abort();
|
||||
@@ -249,11 +287,19 @@ library_unexpected_error(const char *file, int line, const char *func,
|
||||
* Handle isc_error_unexpected() calls from our libraries.
|
||||
*/
|
||||
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_ERROR, "%s:%d:%s(): unexpected error: ", file,
|
||||
line, func);
|
||||
isc_log_vwrite(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_ERROR, format, args);
|
||||
if (named_g_logging) {
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_ERROR,
|
||||
"%s:%d:%s(): unexpected error: ", file, line,
|
||||
func);
|
||||
isc_log_vwrite(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN,
|
||||
ISC_LOG_ERROR, format, args);
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d:%s(): fatal error: ", file, line, func);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -906,7 +952,25 @@ parse_command_line(int argc, char *argv[]) {
|
||||
named_main_earlyfatal("option '-X' has been removed");
|
||||
break;
|
||||
case 'F':
|
||||
if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
fips = OSSL_PROVIDER_load(NULL, "fips");
|
||||
if (fips == NULL) {
|
||||
ERR_clear_error();
|
||||
named_main_earlyfatal(
|
||||
"Failed to load FIPS provider");
|
||||
}
|
||||
base = OSSL_PROVIDER_load(NULL, "base");
|
||||
if (base == NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
ERR_clear_error();
|
||||
named_main_earlyfatal(
|
||||
"Failed to load base provider");
|
||||
}
|
||||
#endif
|
||||
if (isc_fips_mode()) { /* Already in FIPS mode. */
|
||||
break;
|
||||
}
|
||||
if (isc_fips_set_mode(1) != ISC_R_SUCCESS) {
|
||||
named_main_earlyfatal(
|
||||
"setting FIPS mode failed");
|
||||
}
|
||||
@@ -1510,6 +1574,15 @@ main(int argc, char *argv[]) {
|
||||
|
||||
named_os_shutdown();
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (base != NULL) {
|
||||
OSSL_PROVIDER_unload(base);
|
||||
}
|
||||
if (fips != NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GPERFTOOLS_PROFILER
|
||||
ProfilerStop();
|
||||
#endif /* ifdef HAVE_GPERFTOOLS_PROFILER */
|
||||
|
||||
+2
-1
@@ -38,6 +38,7 @@
|
||||
#include <isc/commandline.h>
|
||||
#include <isc/dir.h>
|
||||
#include <isc/file.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/hmac.h>
|
||||
@@ -9376,7 +9377,7 @@ view_loaded(void *arg) {
|
||||
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
|
||||
ISC_LOG_NOTICE, "FIPS mode is %s",
|
||||
isc_crypto_fips_mode() ? "enabled" : "disabled");
|
||||
isc_fips_mode() ? "enabled" : "disabled");
|
||||
|
||||
#if HAVE_LIBSYSTEMD
|
||||
sd_notifyf(0,
|
||||
|
||||
@@ -1617,13 +1617,9 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) {
|
||||
isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf));
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf));
|
||||
} else if (is_presoa) {
|
||||
if (dns_zone_getprimaryaddr(zone, &addr) == ISC_R_SUCCESS) {
|
||||
isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf));
|
||||
TRY0(xmlTextWriterWriteString(writer,
|
||||
ISC_XMLCHAR addr_buf));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
addr = dns_zone_getprimaryaddr(zone);
|
||||
isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf));
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
@@ -2675,15 +2671,10 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) {
|
||||
json_object_object_add(xfrinobj, "remoteaddr",
|
||||
json_object_new_string(addr_buf));
|
||||
} else if (is_presoa) {
|
||||
if (dns_zone_getprimaryaddr(zone, &addr) == ISC_R_SUCCESS) {
|
||||
isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf));
|
||||
json_object_object_add(
|
||||
xfrinobj, "remoteaddr",
|
||||
json_object_new_string(addr_buf));
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "remoteaddr",
|
||||
json_object_new_string("-"));
|
||||
}
|
||||
addr = dns_zone_getprimaryaddr(zone);
|
||||
isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf));
|
||||
json_object_object_add(xfrinobj, "remoteaddr",
|
||||
json_object_new_string(addr_buf));
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "remoteaddr",
|
||||
json_object_new_string("-"));
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/lib.h>
|
||||
#include <isc/md.h>
|
||||
#include <isc/mem.h>
|
||||
@@ -134,7 +134,7 @@ main(int argc, char **argv) {
|
||||
return 1;
|
||||
#endif
|
||||
#else
|
||||
if (isc_crypto_fips_mode()) {
|
||||
if (isc_fips_mode()) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
return 0;
|
||||
#else
|
||||
@@ -149,7 +149,7 @@ main(int argc, char **argv) {
|
||||
#if defined(ENABLE_FIPS_MODE)
|
||||
return 0;
|
||||
#else
|
||||
return isc_crypto_fips_mode() ? 0 : 1;
|
||||
return isc_fips_mode() ? 0 : 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
import difflib
|
||||
import shutil
|
||||
from typing import Optional
|
||||
|
||||
@@ -98,28 +97,6 @@ def zones_equal(
|
||||
assert found_rdataset.ttl == rdataset.ttl
|
||||
|
||||
|
||||
def zone_contains(
|
||||
zone: dns.zone.Zone, rrset: dns.rrset.RRset, compare_ttl=False
|
||||
) -> bool:
|
||||
"""Check if a zone contains RRset"""
|
||||
|
||||
def compare_rrs(rr1, rrset):
|
||||
rr2 = next((other_rr for other_rr in rrset if rr1 == other_rr), None)
|
||||
if rr2 is None:
|
||||
return False
|
||||
if compare_ttl:
|
||||
return rr1.ttl == rr2.ttl
|
||||
return True
|
||||
|
||||
for _, node in zone.nodes.items():
|
||||
for rdataset in node:
|
||||
for rr in rdataset:
|
||||
if compare_rrs(rr, rrset):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def is_executable(cmd: str, errmsg: str) -> None:
|
||||
executable = shutil.which(cmd)
|
||||
assert executable is not None, errmsg
|
||||
@@ -151,32 +128,3 @@ def is_response_to(response: dns.message.Message, query: dns.message.Message) ->
|
||||
single_question(response)
|
||||
single_question(query)
|
||||
assert query.is_response(response), str(response)
|
||||
|
||||
|
||||
def file_contents_contain(file, substr):
|
||||
with open(file, "r", encoding="utf-8") as fp:
|
||||
for line in fp:
|
||||
if f"{substr}" in line:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def file_contents_equal(file1, file2):
|
||||
def normalize_line(line):
|
||||
# remove trailing&leading whitespace and replace multiple whitespaces
|
||||
return " ".join(line.split())
|
||||
|
||||
def read_lines(file_path):
|
||||
with open(file_path, "r", encoding="utf-8") as file:
|
||||
return [normalize_line(line) for line in file.readlines()]
|
||||
|
||||
lines1 = read_lines(file1)
|
||||
lines2 = read_lines(file2)
|
||||
|
||||
differ = difflib.Differ()
|
||||
diff = differ.compare(lines1, lines2)
|
||||
|
||||
for line in diff:
|
||||
assert not line.startswith("+ ") and not line.startswith(
|
||||
"- "
|
||||
), f'file contents of "{file1}" and "{file2}" differ'
|
||||
|
||||
@@ -10,34 +10,24 @@
|
||||
# information regarding copyright ownership.
|
||||
|
||||
from functools import total_ordering
|
||||
import glob
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
from typing import List, Optional, Union
|
||||
from typing import Optional, Union
|
||||
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import dns
|
||||
import dns.tsig
|
||||
import isctest.log
|
||||
import isctest.query
|
||||
|
||||
DEFAULT_TTL = 300
|
||||
|
||||
NEXT_KEY_EVENT_THRESHOLD = 100
|
||||
|
||||
|
||||
def _query(server, qname, qtype, tsig=None):
|
||||
def _query(server, qname, qtype):
|
||||
query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True)
|
||||
|
||||
if tsig is not None:
|
||||
tsigkey = tsig.split(":")
|
||||
keyring = dns.tsig.Key(tsigkey[1], tsigkey[2], tsigkey[0])
|
||||
query.use_tsig(keyring)
|
||||
|
||||
try:
|
||||
response = isctest.query.tcp(query, server.ip, server.ports.dns, timeout=3)
|
||||
except dns.exception.Timeout:
|
||||
@@ -47,158 +37,6 @@ def _query(server, qname, qtype, tsig=None):
|
||||
return response
|
||||
|
||||
|
||||
class KeyProperties:
|
||||
"""
|
||||
Represent the (expected) properties a key should have.
|
||||
"""
|
||||
|
||||
def __init__(self, name: str, properties: dict, metadata: dict, timing: dict):
|
||||
self.name = name
|
||||
self.key = None
|
||||
self.properties = properties
|
||||
self.metadata = metadata
|
||||
self.timing = timing
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
@staticmethod
|
||||
def default(with_state=True) -> "KeyProperties":
|
||||
result = KeyProperties.__new__(KeyProperties)
|
||||
result.name = "DEFAULT"
|
||||
result.key = None
|
||||
result.timing = {}
|
||||
result.properties = {
|
||||
"expect": True,
|
||||
"private": True,
|
||||
"legacy": False,
|
||||
"role": "csk",
|
||||
"role_full": "key-signing",
|
||||
"dnskey_ttl": 3600,
|
||||
"flags": 257,
|
||||
}
|
||||
result.metadata = {
|
||||
"Algorithm": 13, # ECDSAP256SHA256
|
||||
"Length": 256,
|
||||
"Lifetime": 0,
|
||||
"KSK": "yes",
|
||||
"ZSK": "yes",
|
||||
}
|
||||
if with_state:
|
||||
result.metadata["GoalState"] = "omnipresent"
|
||||
result.metadata["DNSKEYState"] = "rumoured"
|
||||
result.metadata["KRRSIGState"] = "rumoured"
|
||||
result.metadata["ZRRSIGState"] = "rumoured"
|
||||
result.metadata["DSState"] = "hidden"
|
||||
|
||||
return result
|
||||
|
||||
def Ipub(self, config):
|
||||
ipub = timedelta(0)
|
||||
|
||||
if self.key.get_metadata("Predecessor", must_exist=False) != "undefined":
|
||||
# Ipub = Dprp + TTLkey
|
||||
ipub = (
|
||||
config["dnskey-ttl"]
|
||||
+ config["zone-propagation-delay"]
|
||||
+ config["publish-safety"]
|
||||
)
|
||||
|
||||
self.timing["Active"] = self.timing["Published"] + ipub
|
||||
|
||||
def IpubC(self, config):
|
||||
if not self.key.is_ksk():
|
||||
return
|
||||
|
||||
ttl1 = config["dnskey-ttl"] + config["publish-safety"]
|
||||
ttl2 = timedelta(0)
|
||||
|
||||
if self.key.get_metadata("Predecessor", must_exist=False) == "undefined":
|
||||
# If this is the first key, we also need to wait until the zone
|
||||
# signatures are omnipresent. Use max-zone-ttl instead of
|
||||
# dnskey-ttl, and no publish-safety (because we are looking at
|
||||
# signatures here, not the public key).
|
||||
ttl2 = config["max-zone-ttl"]
|
||||
|
||||
# IpubC = DprpC + TTLkey
|
||||
ipubc = config["zone-propagation-delay"] + max(ttl1, ttl2)
|
||||
|
||||
self.timing["PublishCDS"] = self.timing["Published"] + ipubc
|
||||
|
||||
if self.metadata["Lifetime"] != 0:
|
||||
self.timing["DeleteCDS"] = self.timing["PublishCDS"] + int(
|
||||
self.metadata["Lifetime"]
|
||||
)
|
||||
|
||||
def Iret(self, config):
|
||||
if self.metadata["Lifetime"] == 0:
|
||||
return
|
||||
|
||||
sign_delay = config["signatures-validity"] - config["signatures-refresh"]
|
||||
safety_interval = config["retire-safety"]
|
||||
|
||||
iretKSK = timedelta(0)
|
||||
iretZSK = timedelta(0)
|
||||
if self.key.is_ksk():
|
||||
# Iret = DprpP + TTLds
|
||||
iretKSK = (
|
||||
config["parent-propagation-delay"] + config["ds-ttl"] + safety_interval
|
||||
)
|
||||
if self.key.is_zsk():
|
||||
# Iret = Dsgn + Dprp + TTLsig
|
||||
iretZSK = (
|
||||
sign_delay
|
||||
+ config["zone-propagation-delay"]
|
||||
+ config["max-zone-ttl"]
|
||||
+ safety_interval
|
||||
)
|
||||
|
||||
self.timing["Removed"] = self.timing["Retired"] + max(iretKSK, iretZSK)
|
||||
|
||||
def set_expected_keytimes(self, config, offset=None, pregenerated=False):
|
||||
if self.key is None:
|
||||
raise ValueError("KeyProperties must be attached to a Key")
|
||||
|
||||
if self.properties["legacy"]:
|
||||
return
|
||||
|
||||
if offset is None:
|
||||
offset = self.properties["offset"]
|
||||
|
||||
self.timing["Generated"] = self.key.get_timing("Created")
|
||||
|
||||
self.timing["Published"] = self.timing["Generated"]
|
||||
if pregenerated:
|
||||
self.timing["Published"] = self.key.get_timing("Publish")
|
||||
self.timing["Published"] = self.timing["Published"] + offset
|
||||
self.Ipub(config)
|
||||
|
||||
# Set Retired timing metadata if key has lifetime.
|
||||
if self.metadata["Lifetime"] != 0:
|
||||
self.timing["Retired"] = self.timing["Active"] + int(
|
||||
self.metadata["Lifetime"]
|
||||
)
|
||||
|
||||
self.IpubC(config)
|
||||
self.Iret(config)
|
||||
|
||||
# Key state change times must exist, but since we cannot reliably tell
|
||||
# when named made the actual state change, we don't care what the
|
||||
# value is. Set it to None will verify that the metadata exists, but
|
||||
# without actual checking the value.
|
||||
self.timing["DNSKEYChange"] = None
|
||||
|
||||
if self.key.is_ksk():
|
||||
self.timing["DSChange"] = None
|
||||
self.timing["KRRSIGChange"] = None
|
||||
|
||||
if self.key.is_zsk():
|
||||
self.timing["ZRRSIGChange"] = None
|
||||
|
||||
|
||||
@total_ordering
|
||||
class KeyTimingMetadata:
|
||||
"""
|
||||
@@ -279,7 +117,6 @@ class Key:
|
||||
else:
|
||||
self.keydir = Path(keydir)
|
||||
self.path = str(self.keydir / name)
|
||||
self.privatefile = f"{self.path}.private"
|
||||
self.keyfile = f"{self.path}.key"
|
||||
self.statefile = f"{self.path}.state"
|
||||
self.tag = int(self.name[-5:])
|
||||
@@ -302,43 +139,21 @@ class Key:
|
||||
)
|
||||
return None
|
||||
|
||||
def get_metadata(
|
||||
self, metadata: str, file=None, comment=False, must_exist=True
|
||||
) -> str:
|
||||
if file is None:
|
||||
file = self.statefile
|
||||
def get_metadata(self, metadata: str, must_exist=True) -> str:
|
||||
value = "undefined"
|
||||
regex = rf"{metadata}:\s+(\S+).*"
|
||||
if comment:
|
||||
# The expected metadata is prefixed with a ';'.
|
||||
regex = rf";\s+{metadata}:\s+(\S+).*"
|
||||
with open(file, "r", encoding="utf-8") as fp:
|
||||
for line in fp:
|
||||
regex = rf"{metadata}:\s+(.*)"
|
||||
with open(self.statefile, "r", encoding="utf-8") as file:
|
||||
for line in file:
|
||||
match = re.match(regex, line)
|
||||
if match is not None:
|
||||
value = match.group(1)
|
||||
break
|
||||
if must_exist and value == "undefined":
|
||||
raise ValueError(
|
||||
f'metadata "{metadata}" for key "{self.name}" in file "{file}" undefined'
|
||||
'state metadata "{metadata}" for key "{self.name}" undefined'
|
||||
)
|
||||
return value
|
||||
|
||||
def ttl(self) -> int:
|
||||
with open(self.keyfile, "r", encoding="utf-8") as file:
|
||||
for line in file:
|
||||
if line.startswith(";"):
|
||||
continue
|
||||
return int(line.split()[1])
|
||||
return 0
|
||||
|
||||
def dnskey(self):
|
||||
with open(self.keyfile, "r", encoding="utf-8") as file:
|
||||
for line in file:
|
||||
if "DNSKEY" in line:
|
||||
return line.strip()
|
||||
return "undefined"
|
||||
|
||||
def is_ksk(self) -> bool:
|
||||
return self.get_metadata("KSK") == "yes"
|
||||
|
||||
@@ -372,7 +187,7 @@ class Key:
|
||||
dsfromkey_command = [
|
||||
os.environ.get("DSFROMKEY"),
|
||||
"-T",
|
||||
str(self.ttl()),
|
||||
"3600",
|
||||
"-a",
|
||||
alg,
|
||||
"-C",
|
||||
@@ -401,152 +216,6 @@ class Key:
|
||||
|
||||
return digest_fromfile == digest_fromwire
|
||||
|
||||
def has_metadata(self, key, metadata):
|
||||
# If 'key' exists in 'metadata' then it must also exist in the state
|
||||
# meta data. Otherwise, it must not exist in the state meta data.
|
||||
if key in metadata:
|
||||
return self.get_metadata(key) != "undefined"
|
||||
|
||||
value = self.get_metadata(key, must_exist=False)
|
||||
if value != "undefined":
|
||||
isctest.log.debug(f"{self.name} {key} METADATA UNEXPECTED: {value}")
|
||||
return value == "undefined"
|
||||
|
||||
def match_metadata(self, key, metadata):
|
||||
# If 'key' exists in 'metadata' then it must match the value in the
|
||||
# state meta data. Otherwise, it must also not exist in the state meta
|
||||
# data.
|
||||
if key in metadata:
|
||||
value = self.get_metadata(key)
|
||||
if value != f"{metadata[key]}":
|
||||
isctest.log.debug(
|
||||
f"{self.name} {key} METADATA MISMATCH: {value} - {metadata[key]}"
|
||||
)
|
||||
return value == f"{metadata[key]}"
|
||||
|
||||
value = self.get_metadata(key, must_exist=False)
|
||||
if value != "undefined":
|
||||
isctest.log.debug(f"{self.name} {key} METADATA UNEXPECTED: {value}")
|
||||
return value == "undefined"
|
||||
|
||||
def match_timing(self, key, timing, file, comment=False):
|
||||
# If 'key' exists in 'timing' then it must match the value in the
|
||||
# state timing data. Otherwise, it must also not exist in the state timing
|
||||
# data.
|
||||
if key in timing:
|
||||
value = self.get_metadata(key, file=file, comment=comment)
|
||||
if value != str(timing[key]):
|
||||
isctest.log.debug(
|
||||
f"{self.name} {key} TIMING MISMATCH: {value} - {timing[key]}"
|
||||
)
|
||||
return value == str(timing[key])
|
||||
|
||||
value = self.get_metadata(key, file=file, comment=comment, must_exist=False)
|
||||
if value != "undefined":
|
||||
isctest.log.debug(f"{self.name} {key} TIMING UNEXPECTED: {value}")
|
||||
return value == "undefined"
|
||||
|
||||
def match_properties(self, zone, properties):
|
||||
# Check the key with given properties.
|
||||
if not properties.properties["expect"]:
|
||||
return False
|
||||
|
||||
# Check file existence.
|
||||
# Noop. If file is missing then the get_metadata calls will fail.
|
||||
|
||||
# Check the public key file.
|
||||
role = properties.properties["role_full"]
|
||||
comment = f"This is a {role} key, keyid {self.tag}, for {zone}."
|
||||
if not isctest.check.file_contents_contain(self.keyfile, comment):
|
||||
isctest.log.debug(f"{self.name} COMMENT MISMATCH: expected '{comment}'")
|
||||
return False
|
||||
|
||||
ttl = properties.properties["dnskey_ttl"]
|
||||
flags = properties.properties["flags"]
|
||||
alg = properties.metadata["Algorithm"]
|
||||
dnskey = f"{zone}. {ttl} IN DNSKEY {flags} 3 {alg}"
|
||||
if not isctest.check.file_contents_contain(self.keyfile, dnskey):
|
||||
isctest.log.debug(f"{self.name} DNSKEY MISMATCH: expected '{dnskey}'")
|
||||
return False
|
||||
|
||||
# Now check the private key file.
|
||||
if properties.properties["private"]:
|
||||
# Retrieve creation date.
|
||||
created = self.get_metadata("Generated")
|
||||
|
||||
pval = self.get_metadata("Created", file=self.privatefile)
|
||||
if pval != created:
|
||||
isctest.log.debug(
|
||||
f"{self.name} Created METADATA MISMATCH: {pval} - {created}"
|
||||
)
|
||||
return False
|
||||
pval = self.get_metadata("Private-key-format", file=self.privatefile)
|
||||
if pval != "v1.3":
|
||||
isctest.log.debug(
|
||||
f"{self.name} Private-key-format METADATA MISMATCH: {pval} - v1.3"
|
||||
)
|
||||
return False
|
||||
pval = self.get_metadata("Algorithm", file=self.privatefile)
|
||||
if pval != f"{alg}":
|
||||
isctest.log.debug(
|
||||
f"{self.name} Algorithm METADATA MISMATCH: {pval} - {alg}"
|
||||
)
|
||||
return False
|
||||
|
||||
# Now check the key state file.
|
||||
if properties.properties["legacy"]:
|
||||
return True
|
||||
|
||||
comment = f"This is the state of key {self.tag}, for {zone}."
|
||||
if not isctest.check.file_contents_contain(self.statefile, comment):
|
||||
isctest.log.debug(f"{self.name} COMMENT MISMATCH: expected '{comment}'")
|
||||
return False
|
||||
|
||||
attributes = [
|
||||
"Lifetime",
|
||||
"Algorithm",
|
||||
"Length",
|
||||
"KSK",
|
||||
"ZSK",
|
||||
"GoalState",
|
||||
"DNSKEYState",
|
||||
"KRRSIGState",
|
||||
"ZRRSIGState",
|
||||
"DSState",
|
||||
]
|
||||
for key in attributes:
|
||||
if not self.match_metadata(key, properties.metadata):
|
||||
return False
|
||||
|
||||
# A match is found.
|
||||
return True
|
||||
|
||||
def match_timingmetadata(self, timings, file=None, comment=False):
|
||||
if file is None:
|
||||
file = self.statefile
|
||||
|
||||
attributes = [
|
||||
"Generated",
|
||||
"Created",
|
||||
"Published",
|
||||
"Publish",
|
||||
"PublishCDS",
|
||||
"SyncPublish",
|
||||
"Active",
|
||||
"Activate",
|
||||
"Retired",
|
||||
"Inactive",
|
||||
"Revoked",
|
||||
"Removed",
|
||||
"Delete",
|
||||
]
|
||||
for key in attributes:
|
||||
if not self.match_timing(key, timings, file, comment=comment):
|
||||
isctest.log.debug(f"{self.name} TIMING METADATA MISMATCH: {key}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __lt__(self, other: "Key"):
|
||||
return self.name < other.name
|
||||
|
||||
@@ -557,14 +226,14 @@ class Key:
|
||||
return self.path
|
||||
|
||||
|
||||
def check_zone_is_signed(server, zone, tsig=None):
|
||||
def check_zone_is_signed(server, zone):
|
||||
addr = server.ip
|
||||
fqdn = f"{zone}."
|
||||
|
||||
# wait until zone is fully signed
|
||||
signed = False
|
||||
for _ in range(10):
|
||||
response = _query(server, fqdn, dns.rdatatype.NSEC, tsig=tsig)
|
||||
response = _query(server, fqdn, dns.rdatatype.NSEC)
|
||||
if not isinstance(response, dns.message.Message):
|
||||
isctest.log.debug(f"no response for {fqdn} NSEC from {addr}")
|
||||
elif response.rcode() != dns.rcode.NOERROR:
|
||||
@@ -608,111 +277,13 @@ def check_zone_is_signed(server, zone, tsig=None):
|
||||
assert signed
|
||||
|
||||
|
||||
def check_keys(zone, keys, expected):
|
||||
# Checks keys for a configured zone. This verifies:
|
||||
# 1. The expected number of keys exist in 'keys'.
|
||||
# 2. The keys match the expected properties.
|
||||
|
||||
def _check_keys():
|
||||
# check number of keys matches expected.
|
||||
if len(keys) != len(expected):
|
||||
return False
|
||||
|
||||
if len(keys) == 0:
|
||||
return True
|
||||
|
||||
for expect in expected:
|
||||
expect.key = None
|
||||
|
||||
for key in keys:
|
||||
found = False
|
||||
i = 0
|
||||
while not found and i < len(expected):
|
||||
if expected[i].key is None:
|
||||
found = key.match_properties(zone, expected[i])
|
||||
if found:
|
||||
key.external = expected[i].properties["legacy"]
|
||||
expected[i].key = key
|
||||
i += 1
|
||||
if not found:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
isctest.run.retry_with_timeout(_check_keys, timeout=10)
|
||||
|
||||
|
||||
def check_keytimes(keys, expected):
|
||||
# Check the key timing metadata for all keys in 'keys'.
|
||||
assert len(keys) == len(expected)
|
||||
|
||||
if len(keys) == 0:
|
||||
return
|
||||
|
||||
for key in keys:
|
||||
for expect in expected:
|
||||
if expect.properties["legacy"]:
|
||||
continue
|
||||
|
||||
if not key is expect.key:
|
||||
continue
|
||||
|
||||
synonyms = {}
|
||||
if "Generated" in expect.timing:
|
||||
synonyms["Created"] = expect.timing["Generated"]
|
||||
if "Published" in expect.timing:
|
||||
synonyms["Publish"] = expect.timing["Published"]
|
||||
if "PublishCDS" in expect.timing:
|
||||
synonyms["SyncPublish"] = expect.timing["PublishCDS"]
|
||||
if "Active" in expect.timing:
|
||||
synonyms["Activate"] = expect.timing["Active"]
|
||||
if "Retired" in expect.timing:
|
||||
synonyms["Inactive"] = expect.timing["Retired"]
|
||||
if "DeleteCDS" in expect.timing:
|
||||
synonyms["SyncDelete"] = expect.timing["DeleteCDS"]
|
||||
if "Revoked" in expect.timing:
|
||||
synonyms["Revoked"] = expect.timing["Revoked"]
|
||||
if "Removed" in expect.timing:
|
||||
synonyms["Delete"] = expect.timing["Removed"]
|
||||
|
||||
assert key.match_timingmetadata(synonyms, file=key.keyfile, comment=True)
|
||||
if expect.properties["private"]:
|
||||
assert key.match_timingmetadata(synonyms, file=key.privatefile)
|
||||
if not expect.properties["legacy"]:
|
||||
assert key.match_timingmetadata(expect.timing)
|
||||
|
||||
state_changes = [
|
||||
"DNSKEYChange",
|
||||
"KRRSIGChange",
|
||||
"ZRRSIGChange",
|
||||
"DSChange",
|
||||
]
|
||||
for change in state_changes:
|
||||
assert key.has_metadata(change, expect.timing)
|
||||
|
||||
|
||||
def check_keyrelationships(keys, expected):
|
||||
# Check the key relationships (Successor and Predecessor metadata).
|
||||
for key in keys:
|
||||
for expect in expected:
|
||||
if expect.properties["legacy"]:
|
||||
continue
|
||||
|
||||
if not key is expect.key:
|
||||
continue
|
||||
|
||||
relationship_status = ["Predecessor", "Successor"]
|
||||
for status in relationship_status:
|
||||
assert key.match_metadata(status, expect.metadata)
|
||||
|
||||
|
||||
def check_dnssec_verify(server, zone, tsig=None):
|
||||
def check_dnssec_verify(server, zone):
|
||||
# Check if zone if DNSSEC valid with dnssec-verify.
|
||||
fqdn = f"{zone}."
|
||||
|
||||
verified = False
|
||||
for _ in range(10):
|
||||
transfer = _query(server, fqdn, dns.rdatatype.AXFR, tsig=tsig)
|
||||
transfer = _query(server, fqdn, dns.rdatatype.AXFR)
|
||||
if not isinstance(transfer, dns.message.Message):
|
||||
isctest.log.debug(f"no response for {fqdn} AXFR from {server.ip}")
|
||||
elif transfer.rcode() != dns.rcode.NOERROR:
|
||||
@@ -844,9 +415,9 @@ def _check_dnskeys(dnskeys, keys, cdnskey=False):
|
||||
delete_md = f"Sync{delete_md}"
|
||||
|
||||
for key in keys:
|
||||
publish = key.get_timing(publish_md, must_exist=False)
|
||||
publish = key.get_timing(publish_md)
|
||||
delete = key.get_timing(delete_md, must_exist=False)
|
||||
published = publish is not None and now >= publish
|
||||
published = now >= publish
|
||||
removed = delete is not None and delete <= now
|
||||
|
||||
if not published or removed:
|
||||
@@ -931,8 +502,8 @@ def check_cds(rrset, keys):
|
||||
assert numcds == len(cdss)
|
||||
|
||||
|
||||
def _query_rrset(server, fqdn, qtype, tsig=None):
|
||||
response = _query(server, fqdn, qtype, tsig=tsig)
|
||||
def _query_rrset(server, fqdn, qtype):
|
||||
response = _query(server, fqdn, qtype)
|
||||
assert response.rcode() == dns.rcode.NOERROR
|
||||
|
||||
rrs = []
|
||||
@@ -952,43 +523,46 @@ def _query_rrset(server, fqdn, qtype, tsig=None):
|
||||
return rrs, rrsigs
|
||||
|
||||
|
||||
def check_apex(server, zone, ksks, zsks, tsig=None):
|
||||
def check_apex(server, zone, ksks, zsks):
|
||||
# Test the apex of a zone. This checks that the SOA and DNSKEY RRsets
|
||||
# are signed correctly and with the appropriate keys.
|
||||
fqdn = f"{zone}."
|
||||
|
||||
# test dnskey query
|
||||
dnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.DNSKEY, tsig=tsig)
|
||||
dnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.DNSKEY)
|
||||
assert len(dnskeys) > 0
|
||||
check_dnskeys(dnskeys, ksks, zsks)
|
||||
assert len(rrsigs) > 0
|
||||
check_signatures(rrsigs, dns.rdatatype.DNSKEY, fqdn, ksks, zsks)
|
||||
|
||||
# test soa query
|
||||
soa, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.SOA, tsig=tsig)
|
||||
soa, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.SOA)
|
||||
assert len(soa) == 1
|
||||
assert f"{zone}. {DEFAULT_TTL} IN SOA" in soa[0].to_text()
|
||||
assert len(rrsigs) > 0
|
||||
check_signatures(rrsigs, dns.rdatatype.SOA, fqdn, ksks, zsks)
|
||||
|
||||
# test cdnskey query
|
||||
cdnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDNSKEY, tsig=tsig)
|
||||
cdnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDNSKEY)
|
||||
check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True)
|
||||
if len(cdnskeys) > 0:
|
||||
assert len(rrsigs) > 0
|
||||
check_signatures(rrsigs, dns.rdatatype.CDNSKEY, fqdn, ksks, zsks)
|
||||
|
||||
# test cds query
|
||||
cds, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDS, tsig=tsig)
|
||||
cds, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDS)
|
||||
check_cds(cds, ksks)
|
||||
if len(cds) > 0:
|
||||
assert len(rrsigs) > 0
|
||||
check_signatures(rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks)
|
||||
|
||||
|
||||
def check_subdomain(server, zone, ksks, zsks, tsig=None):
|
||||
def check_subdomain(server, zone, ksks, zsks):
|
||||
# Test an RRset below the apex and verify it is signed correctly.
|
||||
fqdn = f"{zone}."
|
||||
qname = f"a.{zone}."
|
||||
qtype = dns.rdatatype.A
|
||||
response = _query(server, qname, qtype, tsig=tsig)
|
||||
response = _query(server, qname, qtype)
|
||||
assert response.rcode() == dns.rcode.NOERROR
|
||||
|
||||
match = f"{qname} {DEFAULT_TTL} IN A 10.0.0.1"
|
||||
@@ -1001,180 +575,5 @@ def check_subdomain(server, zone, ksks, zsks, tsig=None):
|
||||
else:
|
||||
assert match in rrset.to_text()
|
||||
|
||||
assert len(rrsigs) > 0
|
||||
check_signatures(rrsigs, qtype, fqdn, ksks, zsks)
|
||||
|
||||
|
||||
def check_update_is_signed(server, fqdn, qname, qtype, rdata, ksks, zsks, tsig=None):
|
||||
# Test an RRset below the apex and verify it is updated and signed correctly.
|
||||
response = _query(server, qname, qtype, tsig=tsig)
|
||||
|
||||
if response.rcode() != dns.rcode.NOERROR:
|
||||
return False
|
||||
|
||||
rrtype = dns.rdatatype.to_text(qtype)
|
||||
match = f"{qname} {DEFAULT_TTL} IN {rrtype} {rdata}"
|
||||
rrsigs = []
|
||||
for rrset in response.answer:
|
||||
if rrset.match(
|
||||
dns.name.from_text(qname), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype
|
||||
):
|
||||
rrsigs.append(rrset)
|
||||
elif not match in rrset.to_text():
|
||||
return False
|
||||
|
||||
if len(rrsigs) == 0:
|
||||
return False
|
||||
|
||||
# Zone is updated, ready to verify the signatures.
|
||||
check_signatures(rrsigs, qtype, fqdn, ksks, zsks)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def check_next_key_event(server, zone, next_event):
|
||||
if next_event is None:
|
||||
# No next key event check.
|
||||
return True
|
||||
|
||||
val = int(next_event.total_seconds())
|
||||
if val == 3600:
|
||||
waitfor = rf".*zone {zone}.*: next key event in (.*) seconds"
|
||||
else:
|
||||
# Don't want default loadkeys interval.
|
||||
waitfor = rf".*zone {zone}.*: next key event in (?!3600$)(.*) seconds"
|
||||
|
||||
with server.watch_log_from_start() as watcher:
|
||||
watcher.wait_for_line(re.compile(waitfor))
|
||||
|
||||
next_found = False
|
||||
minval = val - NEXT_KEY_EVENT_THRESHOLD
|
||||
maxval = val + NEXT_KEY_EVENT_THRESHOLD
|
||||
with open(f"{server.identifier}/named.run", "r", encoding="utf-8") as fp:
|
||||
for line in fp:
|
||||
match = re.match(waitfor, line)
|
||||
if match is not None:
|
||||
nextval = int(match.group(1))
|
||||
if minval <= nextval <= maxval:
|
||||
next_found = True
|
||||
break
|
||||
|
||||
isctest.log.debug(
|
||||
f"check next key event: expected {val} in: {line.strip()}"
|
||||
)
|
||||
|
||||
return next_found
|
||||
|
||||
|
||||
def keydir_to_keylist(
|
||||
zone: str, keydir: Optional[str] = None, in_use: Optional[bool] = False
|
||||
) -> List[Key]:
|
||||
# Retrieve all keys from the key files in a directory. If 'zone' is None,
|
||||
# retrieve all keys in the directory, otherwise only those matching the
|
||||
# zone name. If 'keydir' is None, search the current directory.
|
||||
if zone is None:
|
||||
zone = ""
|
||||
|
||||
all_keys = []
|
||||
if keydir is None:
|
||||
regex = rf"(K{zone}\.\+.*\+.*)\.key"
|
||||
for filename in glob.glob(f"K{zone}.+*+*.key"):
|
||||
match = re.match(regex, filename)
|
||||
if match is not None:
|
||||
all_keys.append(Key(match.group(1)))
|
||||
else:
|
||||
regex = rf"{keydir}/(K{zone}\.\+.*\+.*)\.key"
|
||||
for filename in glob.glob(f"{keydir}/K{zone}.+*+*.key"):
|
||||
match = re.match(regex, filename)
|
||||
if match is not None:
|
||||
all_keys.append(Key(match.group(1), keydir))
|
||||
|
||||
states = ["GoalState", "DNSKEYState", "KRRSIGState", "ZRRSIGState", "DSState"]
|
||||
|
||||
def used(kk):
|
||||
if not in_use:
|
||||
return True
|
||||
|
||||
for state in states:
|
||||
val = kk.get_metadata(state, must_exist=False)
|
||||
if val not in ["undefined", "hidden"]:
|
||||
isctest.log.debug(f"key {kk} in use")
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
return [k for k in all_keys if used(k)]
|
||||
|
||||
|
||||
def keystr_to_keylist(keystr: str, keydir: Optional[str] = None) -> List[Key]:
|
||||
return [Key(name, keydir) for name in keystr.split()]
|
||||
|
||||
|
||||
def policy_to_properties(ttl, keys: List[str]) -> List[KeyProperties]:
|
||||
# Get the policies from a list of specially formatted strings.
|
||||
# The splitted line should result in the following items:
|
||||
# line[0]: Role
|
||||
# line[1]: Lifetime
|
||||
# line[2]: Algorithm
|
||||
# line[3]: Length
|
||||
# Then, optional data for specific tests may follow:
|
||||
# - "goal", "dnskey", "krrsig", "zrrsig", "ds", followed by a value,
|
||||
# sets the given state to the specific value
|
||||
# - "offset", an offset for testing key rollover timings
|
||||
proplist = []
|
||||
count = 0
|
||||
for key in keys:
|
||||
count += 1
|
||||
line = key.split()
|
||||
keyprop = KeyProperties(f"KEY{count}", {}, {}, {})
|
||||
keyprop.properties["expect"] = True
|
||||
keyprop.properties["private"] = True
|
||||
keyprop.properties["legacy"] = False
|
||||
keyprop.properties["offset"] = timedelta(0)
|
||||
keyprop.properties["role"] = line[0]
|
||||
if line[0] == "zsk":
|
||||
keyprop.properties["role_full"] = "zone-signing"
|
||||
keyprop.properties["flags"] = 256
|
||||
keyprop.metadata["ZSK"] = "yes"
|
||||
keyprop.metadata["KSK"] = "no"
|
||||
else:
|
||||
keyprop.properties["role_full"] = "key-signing"
|
||||
keyprop.properties["flags"] = 257
|
||||
keyprop.metadata["ZSK"] = "yes" if line[0] == "csk" else "no"
|
||||
keyprop.metadata["KSK"] = "yes"
|
||||
|
||||
keyprop.properties["dnskey_ttl"] = ttl
|
||||
keyprop.metadata["Algorithm"] = line[2]
|
||||
keyprop.metadata["Length"] = line[3]
|
||||
keyprop.metadata["Lifetime"] = 0
|
||||
if line[1] != "unlimited":
|
||||
keyprop.metadata["Lifetime"] = int(line[1])
|
||||
|
||||
if len(line) > 4:
|
||||
i = 4
|
||||
while i < len(line):
|
||||
if line[i].startswith("goal:"):
|
||||
keyval = line[i].split(":")
|
||||
keyprop.metadata["GoalState"] = keyval[1]
|
||||
elif line[i].startswith("dnskey:"):
|
||||
keyval = line[i].split(":")
|
||||
keyprop.metadata["DNSKEYState"] = keyval[1]
|
||||
elif line[i].startswith("krrsig:"):
|
||||
keyval = line[i].split(":")
|
||||
keyprop.metadata["KRRSIGState"] = keyval[1]
|
||||
elif line[i].startswith("zrrsig:"):
|
||||
keyval = line[i].split(":")
|
||||
keyprop.metadata["ZRRSIGState"] = keyval[1]
|
||||
elif line[i].startswith("ds:"):
|
||||
keyval = line[i].split(":")
|
||||
keyprop.metadata["DSState"] = keyval[1]
|
||||
elif line[i].startswith("offset:"):
|
||||
keyval = line[i].split(":")
|
||||
keyprop.properties["offset"] = timedelta(seconds=int(keyval[1]))
|
||||
else:
|
||||
assert False, f"undefined optional data {line[i]}"
|
||||
|
||||
i += 1
|
||||
|
||||
proplist.append(keyprop)
|
||||
|
||||
return proplist
|
||||
|
||||
@@ -130,7 +130,7 @@ $KEYGEN -G -k rsasha256 -l policies/kasp.conf $zone >keygen.out.$zone.2 2>&1
|
||||
zone="multisigner-model2.kasp"
|
||||
echo_i "setting up zone: $zone"
|
||||
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.1)
|
||||
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.2)
|
||||
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zone -M 32768:65535 2>keygen.out.$zone.2)
|
||||
cat "${KSK}.key" | grep -v ";.*" >>"${zone}.db"
|
||||
cat "${ZSK}.key" | grep -v ";.*" >>"${zone}.db"
|
||||
# Import the ZSK sets of the other providers into their DNSKEY RRset.
|
||||
@@ -350,9 +350,10 @@ setup step2.enable-dnssec.autosign
|
||||
TpubN="now-900s"
|
||||
# RRSIG TTL: 12 hour (43200 seconds)
|
||||
# zone-propagation-delay: 5 minutes (300 seconds)
|
||||
# retire-safety: 20 minutes (1200 seconds)
|
||||
# Already passed time: -900 seconds
|
||||
# Total: 42600 seconds
|
||||
TsbmN="now+42600s"
|
||||
# Total: 43800 seconds
|
||||
TsbmN="now+43800s"
|
||||
keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}"
|
||||
CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1)
|
||||
$SETTIME -s -g $O -k $R $TpubN -r $R $TpubN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1
|
||||
@@ -364,10 +365,10 @@ $SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $i
|
||||
# Step 3:
|
||||
# The zone signatures have been published long enough to become OMNIPRESENT.
|
||||
setup step3.enable-dnssec.autosign
|
||||
# Passed time since publications: 42600 + 900 = 43500 seconds.
|
||||
TpubN="now-43500s"
|
||||
# Passed time since publications: 43800 + 900 = 44700 seconds.
|
||||
TpubN="now-44700s"
|
||||
# The key is secure for using in chain of trust when the DNSKEY is OMNIPRESENT.
|
||||
TcotN="now-42600s"
|
||||
TcotN="now-43800s"
|
||||
# We can submit the DS now.
|
||||
TsbmN="now"
|
||||
keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}"
|
||||
|
||||
@@ -127,9 +127,9 @@ setup step2.algorithm-roll.kasp
|
||||
# The time passed since the new algorithm keys have been introduced is 3 hours.
|
||||
TactN="now-3h"
|
||||
TpubN1="now-3h"
|
||||
# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp =
|
||||
# now - 3h + 6h + 1h = now + 4h
|
||||
TsbmN1="now+4h"
|
||||
# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp + publish-safety =
|
||||
# now - 3h + 6h + 1h + 1h = now + 5h
|
||||
TsbmN1="now+5h"
|
||||
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now"
|
||||
zsk1times="-P ${TactN} -A ${TactN} -I now"
|
||||
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
|
||||
@@ -156,11 +156,11 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil
|
||||
# Step 3:
|
||||
# The zone signatures are also OMNIPRESENT.
|
||||
setup step3.algorithm-roll.kasp
|
||||
# The time passed since the new algorithm keys have been introduced is 7 hours.
|
||||
TactN="now-7h"
|
||||
TretN="now-3h"
|
||||
TpubN1="now-7h"
|
||||
TsbmN1="now"
|
||||
# The time passed since the new algorithm keys have been introduced is 9 hours.
|
||||
TactN="now-9h"
|
||||
TretN="now-6h"
|
||||
TpubN1="now-9h"
|
||||
TsbmN1="now-1h"
|
||||
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
|
||||
zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
|
||||
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
|
||||
@@ -188,11 +188,11 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil
|
||||
# The DS is swapped and can become OMNIPRESENT.
|
||||
setup step4.algorithm-roll.kasp
|
||||
# The time passed since the DS has been swapped is 29 hours.
|
||||
TactN="now-36h"
|
||||
TretN="now-33h"
|
||||
TpubN1="now-36h"
|
||||
TsbmN1="now-29h"
|
||||
TactN1="now-27h"
|
||||
TactN="now-38h"
|
||||
TretN="now-35h"
|
||||
TpubN1="now-38h"
|
||||
TsbmN1="now-30h"
|
||||
TactN1="now-29h"
|
||||
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
|
||||
zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
|
||||
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
|
||||
@@ -220,12 +220,12 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil
|
||||
# The DNSKEY is removed long enough to be HIDDEN.
|
||||
setup step5.algorithm-roll.kasp
|
||||
# The time passed since the DNSKEY has been removed is 2 hours.
|
||||
TactN="now-38h"
|
||||
TretN="now-35h"
|
||||
TactN="now-40h"
|
||||
TretN="now-37h"
|
||||
TremN="now-2h"
|
||||
TpubN1="now-38h"
|
||||
TsbmN1="now-31h"
|
||||
TactN1="now-29h"
|
||||
TpubN1="now-40h"
|
||||
TsbmN1="now-32h"
|
||||
TactN1="now-31h"
|
||||
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
|
||||
zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
|
||||
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
|
||||
@@ -253,13 +253,13 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil
|
||||
# The RRSIGs have been removed long enough to be HIDDEN.
|
||||
setup step6.algorithm-roll.kasp
|
||||
# Additional time passed: 7h.
|
||||
TactN="now-45h"
|
||||
TretN="now-42h"
|
||||
TactN="now-47h"
|
||||
TretN="now-44h"
|
||||
TremN="now-7h"
|
||||
TpubN1="now-45h"
|
||||
TsbmN1="now-38h"
|
||||
TactN1="now-36h"
|
||||
TdeaN="now-7h"
|
||||
TpubN1="now-47h"
|
||||
TsbmN1="now-39h"
|
||||
TactN1="now-38h"
|
||||
TdeaN="now-9h"
|
||||
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
|
||||
zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
|
||||
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
|
||||
@@ -324,11 +324,11 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in
|
||||
# Step 3:
|
||||
# The zone signatures are also OMNIPRESENT.
|
||||
setup step3.csk-algorithm-roll.kasp
|
||||
# The time passed since the new algorithm keys have been introduced is 7 hours.
|
||||
TactN="now-7h"
|
||||
TretN="now-3h"
|
||||
TpubN1="now-7h"
|
||||
TactN1="now-3h"
|
||||
# The time passed since the new algorithm keys have been introduced is 9 hours.
|
||||
TactN="now-9h"
|
||||
TretN="now-6h"
|
||||
TpubN1="now-9h"
|
||||
TactN1="now-6h"
|
||||
csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
|
||||
newtimes="-P ${TpubN1} -A ${TpubN1}"
|
||||
CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1)
|
||||
@@ -347,10 +347,10 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in
|
||||
# The DS is swapped and can become OMNIPRESENT.
|
||||
setup step4.csk-algorithm-roll.kasp
|
||||
# The time passed since the DS has been swapped is 29 hours.
|
||||
TactN="now-36h"
|
||||
TretN="now-33h"
|
||||
TpubN1="now-36h"
|
||||
TactN1="now-33h"
|
||||
TactN="now-38h"
|
||||
TretN="now-35h"
|
||||
TpubN1="now-38h"
|
||||
TactN1="now-35h"
|
||||
TsubN1="now-29h"
|
||||
csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
|
||||
newtimes="-P ${TpubN1} -A ${TpubN1}"
|
||||
@@ -370,11 +370,11 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in
|
||||
# The DNSKEY is removed long enough to be HIDDEN.
|
||||
setup step5.csk-algorithm-roll.kasp
|
||||
# The time passed since the DNSKEY has been removed is 2 hours.
|
||||
TactN="now-38h"
|
||||
TretN="now-35h"
|
||||
TactN="now-40h"
|
||||
TretN="now-37h"
|
||||
TremN="now-2h"
|
||||
TpubN1="now-38h"
|
||||
TactN1="now-35h"
|
||||
TpubN1="now-40h"
|
||||
TactN1="now-37h"
|
||||
TsubN1="now-31h"
|
||||
csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
|
||||
newtimes="-P ${TpubN1} -A ${TpubN1}"
|
||||
@@ -394,12 +394,12 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in
|
||||
# The RRSIGs have been removed long enough to be HIDDEN.
|
||||
setup step6.csk-algorithm-roll.kasp
|
||||
# Additional time passed: 7h.
|
||||
TactN="now-45h"
|
||||
TretN="now-42h"
|
||||
TactN="now-47h"
|
||||
TretN="now-44h"
|
||||
TdeaN="now-9h"
|
||||
TremN="now-7h"
|
||||
TpubN1="now-45h"
|
||||
TactN1="now-42h"
|
||||
TpubN1="now-47h"
|
||||
TactN1="now-44h"
|
||||
TsubN1="now-38h"
|
||||
csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
|
||||
newtimes="-P ${TpubN1} -A ${TpubN1}"
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
. ../conf.sh
|
||||
|
||||
if test -n "$PYTHON"; then
|
||||
if $PYTHON -c "from dns.update import UpdateMessage" 2>/dev/null; then
|
||||
:
|
||||
else
|
||||
echo_i "This test requires the dnspython >= 2.0.0 module." >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo_i "This test requires Python and the dnspython module." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
+588
-125
@@ -54,6 +54,178 @@ next_key_event_threshold=100
|
||||
# Tests #
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# dnssec-keygen
|
||||
#
|
||||
set_zone "kasp"
|
||||
set_policy "kasp" "4" "200"
|
||||
set_server "keys" "10.53.0.1"
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "check that 'dnssec-keygen -k' (configured policy) creates valid files ($n)"
|
||||
ret=0
|
||||
$KEYGEN -K keys -k "$POLICY" -l kasp.conf "$ZONE" >"keygen.out.$POLICY.test$n" 2>/dev/null || ret=1
|
||||
lines=$(wc -l <"keygen.out.$POLICY.test$n")
|
||||
test "$lines" -eq $NUM_KEYS || log_error "wrong number of keys created for policy kasp: $lines"
|
||||
# Temporarily don't log errors because we are searching multiple files.
|
||||
disable_logerror
|
||||
|
||||
# Key properties.
|
||||
set_keyrole "KEY1" "csk"
|
||||
set_keylifetime "KEY1" "31536000"
|
||||
set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
|
||||
set_keysigning "KEY1" "yes"
|
||||
set_zonesigning "KEY1" "yes"
|
||||
|
||||
set_keyrole "KEY2" "ksk"
|
||||
set_keylifetime "KEY2" "31536000"
|
||||
set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
|
||||
set_keysigning "KEY2" "yes"
|
||||
set_zonesigning "KEY2" "no"
|
||||
|
||||
set_keyrole "KEY3" "zsk"
|
||||
set_keylifetime "KEY3" "2592000"
|
||||
set_keyalgorithm "KEY3" "8" "RSASHA256" "2048"
|
||||
set_keysigning "KEY3" "no"
|
||||
set_zonesigning "KEY3" "yes"
|
||||
|
||||
set_keyrole "KEY4" "zsk"
|
||||
set_keylifetime "KEY4" "16070400"
|
||||
set_keyalgorithm "KEY4" "8" "RSASHA256" "3072"
|
||||
set_keysigning "KEY4" "no"
|
||||
set_zonesigning "KEY4" "yes"
|
||||
|
||||
lines=$(get_keyids "$DIR" "$ZONE" | wc -l)
|
||||
test "$lines" -eq $NUM_KEYS || log_error "bad number of key ids"
|
||||
status=$((status + ret))
|
||||
|
||||
ids=$(get_keyids "$DIR" "$ZONE")
|
||||
for id in $ids; do
|
||||
# There are four key files with the same algorithm.
|
||||
# Check them until a match is found.
|
||||
ret=0 && check_key "KEY1" "$id"
|
||||
test "$ret" -eq 0 && continue
|
||||
|
||||
ret=0 && check_key "KEY2" "$id"
|
||||
test "$ret" -eq 0 && continue
|
||||
|
||||
ret=0 && check_key "KEY3" "$id"
|
||||
test "$ret" -eq 0 && continue
|
||||
|
||||
ret=0 && check_key "KEY4" "$id"
|
||||
|
||||
# If ret is still non-zero, non of the files matched.
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
done
|
||||
# Turn error logs on again.
|
||||
enable_logerror
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
|
||||
ret=0
|
||||
set_zone "kasp"
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "." "10.53.0.1"
|
||||
# Key properties.
|
||||
key_clear "KEY1"
|
||||
set_keyrole "KEY1" "csk"
|
||||
set_keylifetime "KEY1" "0"
|
||||
set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
|
||||
set_keysigning "KEY1" "yes"
|
||||
set_zonesigning "KEY1" "yes"
|
||||
|
||||
key_clear "KEY2"
|
||||
key_clear "KEY3"
|
||||
key_clear "KEY4"
|
||||
|
||||
$KEYGEN -G -k "$POLICY" "$ZONE" >"keygen.out.$POLICY.test$n" 2>/dev/null || ret=1
|
||||
lines=$(wc -l <"keygen.out.$POLICY.test$n")
|
||||
test "$lines" -eq $NUM_KEYS || log_error "wrong number of keys created for policy default: $lines"
|
||||
# Temporarily adjust max search depth for this test
|
||||
MAXDEPTH=1
|
||||
ids=$(get_keyids "$DIR" "$ZONE")
|
||||
MAXDEPTH=3
|
||||
echo_i "found in dir $DIR for zone $ZONE the following keytags: $ids"
|
||||
for id in $ids; do
|
||||
check_key "KEY1" "$id"
|
||||
test "$ret" -eq 0 && key_save KEY1
|
||||
check_keytimes
|
||||
done
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
#
|
||||
# dnssec-settime
|
||||
#
|
||||
|
||||
# These test builds upon the latest created key with dnssec-keygen and uses the
|
||||
# environment variables BASE_FILE, KEY_FILE, PRIVATE_FILE and STATE_FILE.
|
||||
CMP_FILE="${BASE_FILE}.cmp"
|
||||
n=$((n + 1))
|
||||
echo_i "check that 'dnssec-settime' by default does not edit key state file ($n)"
|
||||
ret=0
|
||||
cp "$STATE_FILE" "$CMP_FILE"
|
||||
$SETTIME -P +3600 "$BASE_FILE" >/dev/null || log_error "settime failed"
|
||||
grep "; Publish: " "$KEY_FILE" >/dev/null || log_error "mismatch published in $KEY_FILE"
|
||||
grep "Publish: " "$PRIVATE_FILE" >/dev/null || log_error "mismatch published in $PRIVATE_FILE"
|
||||
diff "$CMP_FILE" "$STATE_FILE" || log_error "unexpected file change in $STATE_FILE"
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "check that 'dnssec-settime -s' also sets publish time metadata and states in key state file ($n)"
|
||||
ret=0
|
||||
cp "$STATE_FILE" "$CMP_FILE"
|
||||
now=$(date +%Y%m%d%H%M%S)
|
||||
$SETTIME -s -P "$now" -g "omnipresent" -k "rumoured" "$now" -z "omnipresent" "$now" -r "rumoured" "$now" -d "hidden" "$now" "$BASE_FILE" >/dev/null || log_error "settime failed"
|
||||
set_keystate "KEY1" "GOAL" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
|
||||
set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
|
||||
set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_DS" "hidden"
|
||||
check_key "KEY1" "$id"
|
||||
test "$ret" -eq 0 && key_save KEY1
|
||||
set_keytime "KEY1" "PUBLISHED" "${now}"
|
||||
check_keytimes
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "check that 'dnssec-settime -s' also unsets publish time metadata and states in key state file ($n)"
|
||||
ret=0
|
||||
cp "$STATE_FILE" "$CMP_FILE"
|
||||
$SETTIME -s -P "none" -g "none" -k "none" "$now" -z "none" "$now" -r "none" "$now" -d "none" "$now" "$BASE_FILE" >/dev/null || log_error "settime failed"
|
||||
set_keystate "KEY1" "GOAL" "none"
|
||||
set_keystate "KEY1" "STATE_DNSKEY" "none"
|
||||
set_keystate "KEY1" "STATE_KRRSIG" "none"
|
||||
set_keystate "KEY1" "STATE_ZRRSIG" "none"
|
||||
set_keystate "KEY1" "STATE_DS" "none"
|
||||
check_key "KEY1" "$id"
|
||||
test "$ret" -eq 0 && key_save KEY1
|
||||
set_keytime "KEY1" "PUBLISHED" "none"
|
||||
check_keytimes
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "check that 'dnssec-settime -s' also sets active time metadata and states in key state file (uppercase) ($n)"
|
||||
ret=0
|
||||
cp "$STATE_FILE" "$CMP_FILE"
|
||||
now=$(date +%Y%m%d%H%M%S)
|
||||
$SETTIME -s -A "$now" -g "HIDDEN" -k "UNRETENTIVE" "$now" -z "UNRETENTIVE" "$now" -r "OMNIPRESENT" "$now" -d "OMNIPRESENT" "$now" "$BASE_FILE" >/dev/null || log_error "settime failed"
|
||||
set_keystate "KEY1" "GOAL" "hidden"
|
||||
set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
|
||||
set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_ZRRSIG" "unretentive"
|
||||
set_keystate "KEY1" "STATE_DS" "omnipresent"
|
||||
check_key "KEY1" "$id"
|
||||
test "$ret" -eq 0 && key_save KEY1
|
||||
set_keytime "KEY1" "ACTIVE" "${now}"
|
||||
check_keytimes
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
#
|
||||
# named
|
||||
#
|
||||
@@ -64,7 +236,6 @@ next_key_event_threshold=100
|
||||
# infinite loops if there is an error.
|
||||
n=$((n + 1))
|
||||
echo_i "waiting for kasp signing changes to take effect ($n)"
|
||||
ret=0
|
||||
|
||||
_wait_for_done_apexnsec() {
|
||||
while read -r zone; do
|
||||
@@ -85,6 +256,18 @@ retry_quiet 30 _wait_for_done_apexnsec || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
# Test max-zone-ttl rejects zones with too high TTL.
|
||||
n=$((n + 1))
|
||||
echo_i "check that max-zone-ttl rejects zones with too high TTL ($n)"
|
||||
ret=0
|
||||
set_zone "max-zone-ttl.kasp"
|
||||
grep "loading from master file ${ZONE}.db failed: out of range" "ns3/named.run" >/dev/null || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
#
|
||||
# Zone: default.kasp.
|
||||
#
|
||||
set_keytimes_csk_policy() {
|
||||
# The first key is immediately published and activated.
|
||||
created=$(key_get KEY1 CREATED)
|
||||
@@ -92,11 +275,16 @@ set_keytimes_csk_policy() {
|
||||
set_keytime "KEY1" "ACTIVE" "${created}"
|
||||
# The DS can be published if the DNSKEY and RRSIG records are
|
||||
# OMNIPRESENT. This happens after max-zone-ttl (1d) plus
|
||||
# zone-propagation-delay (300s) = 86400 + 300 = 86700.
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 86700
|
||||
# publish-safety (1h) plus zone-propagation-delay (300s) =
|
||||
# 86400 + 3600 + 300 = 90300.
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 90300
|
||||
# Key lifetime is unlimited, so not setting RETIRED and REMOVED.
|
||||
}
|
||||
|
||||
# Check the zone with default kasp policy has loaded and is signed.
|
||||
set_zone "default.kasp"
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# Key properties.
|
||||
set_keyrole "KEY1" "csk"
|
||||
set_keylifetime "KEY1" "0"
|
||||
@@ -110,6 +298,240 @@ set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
|
||||
set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
|
||||
set_keystate "KEY1" "STATE_DS" "hidden"
|
||||
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_csk_policy
|
||||
check_keytimes
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Trigger a keymgr run. Make sure the key files are not touched if there are
|
||||
# no modifications to the key metadata.
|
||||
n=$((n + 1))
|
||||
echo_i "make sure key files are untouched if metadata does not change ($n)"
|
||||
ret=0
|
||||
basefile=$(key_get KEY1 BASEFILE)
|
||||
privkey_stat=$(key_get KEY1 PRIVKEY_STAT)
|
||||
pubkey_stat=$(key_get KEY1 PUBKEY_STAT)
|
||||
state_stat=$(key_get KEY1 STATE_STAT)
|
||||
|
||||
nextpart $DIR/named.run >/dev/null
|
||||
rndccmd 10.53.0.3 loadkeys "$ZONE" >/dev/null || log_error "rndc loadkeys zone ${ZONE} failed"
|
||||
wait_for_log 3 "keymgr: $ZONE done" $DIR/named.run || ret=1
|
||||
privkey_stat2=$(key_stat "${basefile}.private")
|
||||
pubkey_stat2=$(key_stat "${basefile}.key")
|
||||
state_stat2=$(key_stat "${basefile}.state")
|
||||
test "$privkey_stat" = "$privkey_stat2" || log_error "wrong private key file stat (expected $privkey_stat got $privkey_stat2)"
|
||||
test "$pubkey_stat" = "$pubkey_stat2" || log_error "wrong public key file stat (expected $pubkey_stat got $pubkey_stat2)"
|
||||
test "$state_stat" = "$state_stat2" || log_error "wrong state file stat (expected $state_stat got $state_stat2)"
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "again ($n)"
|
||||
ret=0
|
||||
|
||||
nextpart $DIR/named.run >/dev/null
|
||||
rndccmd 10.53.0.3 loadkeys "$ZONE" >/dev/null || log_error "rndc loadkeys zone ${ZONE} failed"
|
||||
wait_for_log 3 "keymgr: $ZONE done" $DIR/named.run || ret=1
|
||||
privkey_stat2=$(key_stat "${basefile}.private")
|
||||
pubkey_stat2=$(key_stat "${basefile}.key")
|
||||
state_stat2=$(key_stat "${basefile}.state")
|
||||
test "$privkey_stat" = "$privkey_stat2" || log_error "wrong private key file stat (expected $privkey_stat got $privkey_stat2)"
|
||||
test "$pubkey_stat" = "$pubkey_stat2" || log_error "wrong public key file stat (expected $pubkey_stat got $pubkey_stat2)"
|
||||
test "$state_stat" = "$state_stat2" || log_error "wrong state file stat (expected $state_stat got $state_stat2)"
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
# Update zone.
|
||||
n=$((n + 1))
|
||||
echo_i "modify unsigned zone file and check that new record is signed for zone ${ZONE} ($n)"
|
||||
ret=0
|
||||
cp "${DIR}/template2.db.in" "${DIR}/${ZONE}.db"
|
||||
rndccmd 10.53.0.3 reload "$ZONE" >/dev/null || log_error "rndc reload zone ${ZONE} failed"
|
||||
|
||||
update_is_signed() {
|
||||
ip_a=$1
|
||||
ip_d=$2
|
||||
|
||||
if [ "$ip_a" != "-" ]; then
|
||||
dig_with_opts "a.${ZONE}" "@${SERVER}" A >"dig.out.$DIR.test$n.a" || return 1
|
||||
grep "status: NOERROR" "dig.out.$DIR.test$n.a" >/dev/null || return 1
|
||||
grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*${ip_a}" "dig.out.$DIR.test$n.a" >/dev/null || return 1
|
||||
lines=$(get_keys_which_signed A 0 "dig.out.$DIR.test$n.a" | wc -l)
|
||||
test "$lines" -eq 1 || return 1
|
||||
get_keys_which_signed A 0 "dig.out.$DIR.test$n.a" | grep "^${KEY_ID}$" >/dev/null || return 1
|
||||
fi
|
||||
|
||||
if [ "$ip_d" != "-" ]; then
|
||||
dig_with_opts "d.${ZONE}" "@${SERVER}" A >"dig.out.$DIR.test$n".d || return 1
|
||||
grep "status: NOERROR" "dig.out.$DIR.test$n".d >/dev/null || return 1
|
||||
grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*${ip_d}" "dig.out.$DIR.test$n".d >/dev/null || return 1
|
||||
lines=$(get_keys_which_signed A 0 "dig.out.$DIR.test$n".d | wc -l)
|
||||
test "$lines" -eq 1 || return 1
|
||||
get_keys_which_signed A 0 "dig.out.$DIR.test$n".d | grep "^${KEY_ID}$" >/dev/null || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
retry_quiet 10 update_is_signed "10.0.0.11" "10.0.0.44" || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
# Move the private key file, a rekey event should not introduce replacement
|
||||
# keys.
|
||||
ret=0
|
||||
echo_i "test that if private key files are inaccessible this doesn't trigger a rollover ($n)"
|
||||
basefile=$(key_get KEY1 BASEFILE)
|
||||
mv "${basefile}.private" "${basefile}.offline"
|
||||
rndccmd 10.53.0.3 loadkeys "$ZONE" >/dev/null || log_error "rndc loadkeys zone ${ZONE} failed"
|
||||
wait_for_log 3 "zone $ZONE/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing" $DIR/named.run || ret=1
|
||||
mv "${basefile}.offline" "${basefile}.private"
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
# Nothing has changed.
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_csk_policy
|
||||
check_keytimes
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
#
|
||||
# A zone with special characters.
|
||||
#
|
||||
set_zone "i-am.\":\;?&[]\@!\$*+,|=\.\(\)special.kasp."
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# It is non-trivial to adapt the tests to deal with all possible different
|
||||
# escaping characters, so we will just try to verify the zone.
|
||||
dnssec_verify
|
||||
|
||||
#
|
||||
# Zone: dynamic.kasp
|
||||
#
|
||||
set_zone "dynamic.kasp"
|
||||
set_dynamic
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# Key properties, timings and states same as above.
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_csk_policy
|
||||
check_keytimes
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Update zone with nsupdate.
|
||||
n=$((n + 1))
|
||||
echo_i "nsupdate zone and check that new record is signed for zone ${ZONE} ($n)"
|
||||
ret=0
|
||||
(
|
||||
echo zone ${ZONE}
|
||||
echo server 10.53.0.3 "$PORT"
|
||||
echo update del "a.${ZONE}" 300 A 10.0.0.1
|
||||
echo update add "a.${ZONE}" 300 A 10.0.0.101
|
||||
echo update add "d.${ZONE}" 300 A 10.0.0.4
|
||||
echo send
|
||||
) | $NSUPDATE
|
||||
|
||||
retry_quiet 10 update_is_signed "10.0.0.101" "10.0.0.4" || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
# Update zone with nsupdate (reverting the above change).
|
||||
n=$((n + 1))
|
||||
echo_i "nsupdate zone and check that new record is signed for zone ${ZONE} ($n)"
|
||||
ret=0
|
||||
(
|
||||
echo zone ${ZONE}
|
||||
echo server 10.53.0.3 "$PORT"
|
||||
echo update add "a.${ZONE}" 300 A 10.0.0.1
|
||||
echo update del "a.${ZONE}" 300 A 10.0.0.101
|
||||
echo update del "d.${ZONE}" 300 A 10.0.0.4
|
||||
echo send
|
||||
) | $NSUPDATE
|
||||
|
||||
retry_quiet 10 update_is_signed "10.0.0.1" "-" || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
# Update zone with freeze/thaw.
|
||||
n=$((n + 1))
|
||||
echo_i "modify zone file and check that new record is signed for zone ${ZONE} ($n)"
|
||||
ret=0
|
||||
rndccmd 10.53.0.3 freeze "$ZONE" >/dev/null || log_error "rndc freeze zone ${ZONE} failed"
|
||||
sleep 1
|
||||
echo "d.${ZONE}. 300 A 10.0.0.44" >>"${DIR}/${ZONE}.db"
|
||||
rndccmd 10.53.0.3 thaw "$ZONE" >/dev/null || log_error "rndc thaw zone ${ZONE} failed"
|
||||
|
||||
retry_quiet 10 update_is_signed "10.0.0.1" "10.0.0.44" || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
#
|
||||
# Zone: dynamic-inline-signing.kasp
|
||||
#
|
||||
set_zone "dynamic-inline-signing.kasp"
|
||||
set_dynamic
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# Key properties, timings and states same as above.
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_csk_policy
|
||||
check_keytimes
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Update zone with freeze/thaw.
|
||||
n=$((n + 1))
|
||||
echo_i "modify unsigned zone file and check that new record is signed for zone ${ZONE} ($n)"
|
||||
ret=0
|
||||
rndccmd 10.53.0.3 freeze "$ZONE" >/dev/null || log_error "rndc freeze zone ${ZONE} failed"
|
||||
sleep 1
|
||||
cp "${DIR}/template2.db.in" "${DIR}/${ZONE}.db"
|
||||
rndccmd 10.53.0.3 thaw "$ZONE" >/dev/null || log_error "rndc thaw zone ${ZONE} failed"
|
||||
|
||||
retry_quiet 10 update_is_signed || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
#
|
||||
# Zone: dynamic-signed-inline-signing.kasp
|
||||
#
|
||||
set_zone "dynamic-signed-inline-signing.kasp"
|
||||
set_dynamic
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
dnssec_verify
|
||||
# Ensure no zone_resigninc for the unsigned version of the zone is triggered.
|
||||
n=$((n + 1))
|
||||
echo_i "check if resigning the raw version of the zone is prevented for zone ${ZONE} ($n)"
|
||||
ret=0
|
||||
grep "zone_resigninc: zone $ZONE/IN (unsigned): enter" $DIR/named.run && ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
#
|
||||
# Zone: inline-signing.kasp
|
||||
#
|
||||
set_zone "inline-signing.kasp"
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# Key properties, timings and states same as above.
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_csk_policy
|
||||
check_keytimes
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
#
|
||||
# Zone: checkds-ksk.kasp.
|
||||
#
|
||||
@@ -347,8 +769,9 @@ set_keytimes_algorithm_policy() {
|
||||
|
||||
# The DS can be published if the DNSKEY and RRSIG records are
|
||||
# OMNIPRESENT. This happens after max-zone-ttl (1d) plus
|
||||
# zone-propagation-delay (300s) = 86400 + 300 = 86700.
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 86700
|
||||
# publish-safety (1h) plus zone-propagation-delay (300s) =
|
||||
# 86400 + 3600 + 300 = 90300.
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 90300
|
||||
# Key lifetime is 10 years, 315360000 seconds.
|
||||
set_addkeytime "KEY1" "RETIRED" "${published}" 315360000
|
||||
# The key is removed after the retire time plus DS TTL (1d),
|
||||
@@ -455,16 +878,53 @@ if [ $RSASHA1_SUPPORTED = 1 ]; then
|
||||
dnssec_verify
|
||||
fi
|
||||
|
||||
#
|
||||
# Zone: unsigned.kasp.
|
||||
#
|
||||
set_zone "unsigned.kasp"
|
||||
set_policy "none" "0" "0"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
|
||||
key_clear "KEY1"
|
||||
key_clear "KEY2"
|
||||
key_clear "KEY3"
|
||||
key_clear "KEY4"
|
||||
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_apex
|
||||
check_subdomain
|
||||
# Make sure the zone file is untouched.
|
||||
n=$((n + 1))
|
||||
echo_i "Make sure the zonefile for zone ${ZONE} is not edited ($n)"
|
||||
ret=0
|
||||
diff "${DIR}/${ZONE}.db.infile" "${DIR}/${ZONE}.db" || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
#
|
||||
# Zone: insecure.kasp.
|
||||
#
|
||||
set_zone "insecure.kasp"
|
||||
set_policy "insecure" "0" "0"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
|
||||
key_clear "KEY1"
|
||||
key_clear "KEY2"
|
||||
key_clear "KEY3"
|
||||
key_clear "KEY4"
|
||||
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_apex
|
||||
check_subdomain
|
||||
|
||||
#
|
||||
# Zone: unlimited.kasp.
|
||||
#
|
||||
set_zone "unlimited.kasp"
|
||||
set_policy "unlimited" "1" "1234"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
key_clear "KEY1"
|
||||
key_clear "KEY2"
|
||||
key_clear "KEY3"
|
||||
key_clear "KEY4"
|
||||
# Key properties.
|
||||
set_keyrole "KEY1" "csk"
|
||||
set_keylifetime "KEY1" "0"
|
||||
@@ -1260,10 +1720,10 @@ published=$(awk '{print $3}' <published.test${n}.key1)
|
||||
set_keytime "KEY1" "PUBLISHED" "${published}"
|
||||
set_keytime "KEY1" "ACTIVE" "${published}"
|
||||
published=$(key_get KEY1 PUBLISHED)
|
||||
# The DS can be published if the zone is fully signed.
|
||||
# This happens after max-zone-ttl (1d) plus
|
||||
# zone-propagation-delay (300s) = 86400 + 300 = 86700.
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 86700
|
||||
# The DS can be published if the DNSKEY and RRSIG records are OMNIPRESENT.
|
||||
# This happens after max-zone-ttl (1d) plus publish-safety (1h) plus
|
||||
# zone-propagation-delay (300s) = 86400 + 3600 + 300 = 90300.
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 90300
|
||||
# Key lifetime is 6 months, 315360000 seconds.
|
||||
set_addkeytime "KEY1" "RETIRED" "${published}" 16070400
|
||||
# The key is removed after the retire time plus DS TTL (1d), parent
|
||||
@@ -2026,9 +2486,9 @@ set_keytime "KEY1" "PUBLISHED" "${created}"
|
||||
set_keytime "KEY1" "ACTIVE" "${created}"
|
||||
# - The DS can be published if the DNSKEY and RRSIG records are
|
||||
# OMNIPRESENT. This happens after max-zone-ttl (12h) plus
|
||||
# plus zone-propagation-delay (5m) =
|
||||
# 43200 + 300 = 43500.
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43500
|
||||
# publish-safety (5m) plus zone-propagation-delay (5m) =
|
||||
# 43200 + 300 + 300 = 43800.
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43800
|
||||
# - Key lifetime is unlimited, so not setting RETIRED and REMOVED.
|
||||
|
||||
# Various signing policy checks.
|
||||
@@ -2096,7 +2556,7 @@ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "PUBLISHED" "${created}" -900
|
||||
set_addkeytime "KEY1" "ACTIVE" "${created}" -900
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 42600
|
||||
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43800
|
||||
|
||||
# Continue signing policy checks.
|
||||
check_keytimes
|
||||
@@ -2106,8 +2566,8 @@ dnssec_verify
|
||||
|
||||
# Next key event is when the zone signatures become OMNIPRESENT: max-zone-ttl
|
||||
# plus zone propagation delay plus retire safety minus the already elapsed
|
||||
# 900 seconds: 12h + 300s + 20m - 900 = 43500 - 900 = 42600 seconds
|
||||
check_next_key_event 42600
|
||||
# 900 seconds: 12h + 300s + 20m - 900 = 44700 - 900 = 43800 seconds
|
||||
check_next_key_event 43800
|
||||
|
||||
#
|
||||
# Zone: step3.enable-dnssec.autosign.
|
||||
@@ -2124,10 +2584,10 @@ check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# Set expected key times:
|
||||
# - The key was published and activated 43500 seconds ago (with settime).
|
||||
# - The key was published and activated 44700 seconds ago (with settime).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "PUBLISHED" "${created}" -43500
|
||||
set_addkeytime "KEY1" "ACTIVE" "${created}" -43500
|
||||
set_addkeytime "KEY1" "PUBLISHED" "${created}" -44700
|
||||
set_addkeytime "KEY1" "ACTIVE" "${created}" -44700
|
||||
set_keytime "KEY1" "SYNCPUBLISH" "${created}"
|
||||
|
||||
# Continue signing policy checks.
|
||||
@@ -2143,8 +2603,8 @@ check_cdslog "$DIR" "$ZONE" KEY1
|
||||
rndc_checkds "$SERVER" "$DIR" KEY1 "now" "published" "$ZONE"
|
||||
# Next key event is when the DS can move to the OMNIPRESENT state. This occurs
|
||||
# when the parent propagation delay have passed, plus the DS TTL and retire
|
||||
# safety delay: 1h + 2h = 3h = 10800 seconds
|
||||
check_next_key_event 10800
|
||||
# safety delay: 1h + 2h + 20m = 3h20m = 12000 seconds
|
||||
check_next_key_event 12000
|
||||
|
||||
#
|
||||
# Zone: step4.enable-dnssec.autosign.
|
||||
@@ -3928,9 +4388,9 @@ check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Next key event is when the DS becomes HIDDEN. This happens after the
|
||||
# parent propagation delay, and DS TTL:
|
||||
# 1h + 1d = 25h = 90000 seconds.
|
||||
check_next_key_event 90000
|
||||
# parent propagation delay, retire safety delay, and DS TTL:
|
||||
# 1h + 1h + 1d = 26h = 93600 seconds.
|
||||
check_next_key_event 93600
|
||||
|
||||
#
|
||||
# Zone: step2.going-insecure.kasp
|
||||
@@ -3996,8 +4456,8 @@ dnssec_verify
|
||||
|
||||
# Next key event is when the DS becomes HIDDEN. This happens after the
|
||||
# parent propagation delay, retire safety delay, and DS TTL:
|
||||
# 1h + 1d = 25h = 90000 seconds.
|
||||
check_next_key_event 90000
|
||||
# 1h + 1h + 1d = 26h = 93600 seconds.
|
||||
check_next_key_event 93600
|
||||
|
||||
#
|
||||
# Zone: step2.going-insecure-dynamic.kasp
|
||||
@@ -4191,11 +4651,12 @@ set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
|
||||
created=$(key_get KEY3 CREATED)
|
||||
set_keytime "KEY3" "PUBLISHED" "${created}"
|
||||
set_keytime "KEY3" "ACTIVE" "${created}"
|
||||
# - It takes TTLsig + Dprp to propagate the zone.
|
||||
# - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
|
||||
# TTLsig: 6h (39600 seconds)
|
||||
# Dprp: 1h (3600 seconds)
|
||||
# Ipub: 7h (25200 seconds)
|
||||
Ipub=25200
|
||||
# publish-safety: 1h (3600 seconds)
|
||||
# Ipub: 8h (28800 seconds)
|
||||
Ipub=28800
|
||||
set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${Ipub}"
|
||||
# - The new ZSK is published and activated.
|
||||
created=$(key_get KEY4 CREATED)
|
||||
@@ -4264,12 +4725,12 @@ dnssec_verify
|
||||
|
||||
# Next key event is when all zone signatures are signed with the new
|
||||
# algorithm. This is the max-zone-ttl plus zone propagation delay
|
||||
# 6h + 1h. But three hours have already passed (the time it took to
|
||||
# make the DNSKEY omnipresent), so the next event should be scheduled
|
||||
# in 4 hour: 14400 seconds. Prevent intermittent
|
||||
# plus retire safety: 6h + 1h + 2h. But three hours have already passed
|
||||
# (the time it took to make the DNSKEY omnipresent), so the next event
|
||||
# should be scheduled in 6 hour: 21600 seconds. Prevent intermittent
|
||||
# false positives on slow platforms by subtracting the number of seconds
|
||||
# which passed between key creation and invoking 'rndc reconfig'.
|
||||
next_time=$((14400 - time_passed))
|
||||
next_time=$((21600 - time_passed))
|
||||
check_next_key_event $next_time
|
||||
|
||||
#
|
||||
@@ -4292,28 +4753,28 @@ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_cdslog "$DIR" "$ZONE" KEY3
|
||||
|
||||
# Set expected key times:
|
||||
# - The old keys were activated 7 hours ago (25200 seconds).
|
||||
rollover_predecessor_keytimes -25200
|
||||
# - And retired 3 hours ago (10800 seconds).
|
||||
# - The old keys were activated 9 hours ago (32400 seconds).
|
||||
rollover_predecessor_keytimes -32400
|
||||
# - And retired 6 hours ago (21600 seconds).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -10800
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -21600
|
||||
retired=$(key_get KEY1 RETIRED)
|
||||
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
|
||||
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_addkeytime "KEY2" "RETIRED" "${created}" -10800
|
||||
set_addkeytime "KEY2" "RETIRED" "${created}" -21600
|
||||
retired=$(key_get KEY2 RETIRED)
|
||||
set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
|
||||
# - The new keys are published 7 hours ago.
|
||||
# - The new keys are published 9 hours ago.
|
||||
created=$(key_get KEY3 CREATED)
|
||||
set_addkeytime "KEY3" "PUBLISHED" "${created}" -25200
|
||||
set_addkeytime "KEY3" "ACTIVE" "${created}" -25200
|
||||
set_addkeytime "KEY3" "PUBLISHED" "${created}" -32400
|
||||
set_addkeytime "KEY3" "ACTIVE" "${created}" -32400
|
||||
published=$(key_get KEY3 PUBLISHED)
|
||||
set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
|
||||
|
||||
created=$(key_get KEY4 CREATED)
|
||||
set_addkeytime "KEY4" "PUBLISHED" "${created}" -25200
|
||||
set_addkeytime "KEY4" "ACTIVE" "${created}" -25200
|
||||
set_addkeytime "KEY4" "PUBLISHED" "${created}" -32400
|
||||
set_addkeytime "KEY4" "ACTIVE" "${created}" -32400
|
||||
|
||||
# Continue signing policy checks.
|
||||
check_keytimes
|
||||
@@ -4326,9 +4787,9 @@ dnssec_verify
|
||||
rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
|
||||
rndc_checkds "$SERVER" "$DIR" KEY3 "now" "published" "$ZONE"
|
||||
# Next key event is when the DS becomes OMNIPRESENT. This happens after the
|
||||
# parent propagation delay, and DS TTL:
|
||||
# 1h + 2h = 3h = 10800 seconds.
|
||||
check_next_key_event 10800
|
||||
# parent propagation delay, retire safety delay, and DS TTL:
|
||||
# 1h + 2h + 2h = 5h = 18000 seconds.
|
||||
check_next_key_event 18000
|
||||
|
||||
#
|
||||
# Zone: step4.algorithm-roll.kasp
|
||||
@@ -4355,29 +4816,29 @@ wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# Set expected key times:
|
||||
# - The old keys were activated 36 hours ago (129600 seconds).
|
||||
rollover_predecessor_keytimes -129600
|
||||
# - And retired 33 hours ago (118800 seconds).
|
||||
# - The old keys were activated 38 hours ago (136800 seconds).
|
||||
rollover_predecessor_keytimes -136800
|
||||
# - And retired 35 hours ago (126000 seconds).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -118800
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -126000
|
||||
retired=$(key_get KEY1 RETIRED)
|
||||
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
|
||||
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_addkeytime "KEY2" "RETIRED" "${created}" -118800
|
||||
set_addkeytime "KEY2" "RETIRED" "${created}" -126000
|
||||
retired=$(key_get KEY2 RETIRED)
|
||||
set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
|
||||
|
||||
# - The new keys are published 36 hours ago.
|
||||
# - The new keys are published 38 hours ago.
|
||||
created=$(key_get KEY3 CREATED)
|
||||
set_addkeytime "KEY3" "PUBLISHED" "${created}" -129600
|
||||
set_addkeytime "KEY3" "ACTIVE" "${created}" -129600
|
||||
set_addkeytime "KEY3" "PUBLISHED" "${created}" -136800
|
||||
set_addkeytime "KEY3" "ACTIVE" "${created}" -136800
|
||||
published=$(key_get KEY3 PUBLISHED)
|
||||
set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
|
||||
|
||||
created=$(key_get KEY4 CREATED)
|
||||
set_addkeytime "KEY4" "PUBLISHED" "${created}" -129600
|
||||
set_addkeytime "KEY4" "ACTIVE" "${created}" -129600
|
||||
set_addkeytime "KEY4" "PUBLISHED" "${created}" -136800
|
||||
set_addkeytime "KEY4" "ACTIVE" "${created}" -136800
|
||||
|
||||
# Continue signing policy checks.
|
||||
check_keytimes
|
||||
@@ -4406,29 +4867,29 @@ wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# Set expected key times:
|
||||
# - The old keys were activated 38 hours ago (136800 seconds)
|
||||
rollover_predecessor_keytimes -136800
|
||||
# - And retired 35 hours ago (126000 seconds).
|
||||
# - The old keys were activated 40 hours ago (144000 seconds)
|
||||
rollover_predecessor_keytimes -144000
|
||||
# - And retired 37 hours ago (133200 seconds).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -126000
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -133200
|
||||
retired=$(key_get KEY1 RETIRED)
|
||||
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
|
||||
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_addkeytime "KEY2" "RETIRED" "${created}" -126000
|
||||
set_addkeytime "KEY2" "RETIRED" "${created}" -133200
|
||||
retired=$(key_get KEY2 RETIRED)
|
||||
set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
|
||||
|
||||
# The new keys are published 40 hours ago.
|
||||
created=$(key_get KEY3 CREATED)
|
||||
set_addkeytime "KEY3" "PUBLISHED" "${created}" -136800
|
||||
set_addkeytime "KEY3" "ACTIVE" "${created}" -136800
|
||||
set_addkeytime "KEY3" "PUBLISHED" "${created}" -144000
|
||||
set_addkeytime "KEY3" "ACTIVE" "${created}" -144000
|
||||
published=$(key_get KEY3 PUBLISHED)
|
||||
set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
|
||||
|
||||
created=$(key_get KEY4 CREATED)
|
||||
set_addkeytime "KEY4" "PUBLISHED" "${created}" -136800
|
||||
set_addkeytime "KEY4" "ACTIVE" "${created}" -136800
|
||||
set_addkeytime "KEY4" "PUBLISHED" "${created}" -144000
|
||||
set_addkeytime "KEY4" "ACTIVE" "${created}" -144000
|
||||
|
||||
# Continue signing policy checks.
|
||||
check_keytimes
|
||||
@@ -4437,12 +4898,12 @@ check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Next key event is when the RSASHA1 signatures become HIDDEN. This happens
|
||||
# after the max-zone-ttl plus zone propagation delay (6h + 1h)
|
||||
# minus the time already passed since the UNRETENTIVE state has
|
||||
# been reached (2h): 7h - 2h = 5h = 18000 seconds. Prevent intermittent
|
||||
# after the max-zone-ttl plus zone propagation delay plus retire safety
|
||||
# (6h + 1h + 2h) minus the time already passed since the UNRETENTIVE state has
|
||||
# been reached (2h): 9h - 2h = 7h = 25200 seconds. Prevent intermittent
|
||||
# false positives on slow platforms by subtracting the number of seconds
|
||||
# which passed between key creation and invoking 'rndc reconfig'.
|
||||
next_time=$((18000 - time_passed))
|
||||
next_time=$((25200 - time_passed))
|
||||
check_next_key_event $next_time
|
||||
|
||||
#
|
||||
@@ -4460,29 +4921,29 @@ wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# Set expected key times:
|
||||
# - The old keys were activated 45 hours ago (162000 seconds)
|
||||
rollover_predecessor_keytimes -162000
|
||||
# - And retired 42 hours ago (151200 seconds).
|
||||
# - The old keys were activated 47 hours ago (169200 seconds)
|
||||
rollover_predecessor_keytimes -169200
|
||||
# - And retired 44 hours ago (158400 seconds).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -151200
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -158400
|
||||
retired=$(key_get KEY1 RETIRED)
|
||||
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
|
||||
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_addkeytime "KEY2" "RETIRED" "${created}" -151200
|
||||
set_addkeytime "KEY2" "RETIRED" "${created}" -158400
|
||||
retired=$(key_get KEY2 RETIRED)
|
||||
set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
|
||||
|
||||
# The new keys are published 47 hours ago.
|
||||
created=$(key_get KEY3 CREATED)
|
||||
set_addkeytime "KEY3" "PUBLISHED" "${created}" -162000
|
||||
set_addkeytime "KEY3" "ACTIVE" "${created}" -162000
|
||||
set_addkeytime "KEY3" "PUBLISHED" "${created}" -169200
|
||||
set_addkeytime "KEY3" "ACTIVE" "${created}" -169200
|
||||
published=$(key_get KEY3 PUBLISHED)
|
||||
set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
|
||||
|
||||
created=$(key_get KEY4 CREATED)
|
||||
set_addkeytime "KEY4" "PUBLISHED" "${created}" -162000
|
||||
set_addkeytime "KEY4" "ACTIVE" "${created}" -162000
|
||||
set_addkeytime "KEY4" "PUBLISHED" "${created}" -169200
|
||||
set_addkeytime "KEY4" "ACTIVE" "${created}" -169200
|
||||
|
||||
# Continue signing policy checks.
|
||||
check_keytimes
|
||||
@@ -4565,8 +5026,9 @@ set_keytime "KEY2" "ACTIVE" "${created}"
|
||||
# - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
|
||||
# TTLsig: 6h (39600 seconds)
|
||||
# Dprp: 1h (3600 seconds)
|
||||
# Ipub: 7h (25200 seconds)
|
||||
Ipub=25200
|
||||
# publish-safety: 1h (3600 seconds)
|
||||
# Ipub: 8h (28800 seconds)
|
||||
Ipub=28800
|
||||
set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" "${Ipub}"
|
||||
|
||||
# Continue signing policy checks.
|
||||
@@ -4620,13 +5082,14 @@ check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Next key event is when all zone signatures are signed with the new algorithm.
|
||||
# This is the max-zone-ttl plus zone propagation delay: 6h + 1h. But three
|
||||
# hours have already passed (the time it took to make the DNSKEY omnipresent),
|
||||
# so the next event should be scheduled in 4 hour: 14400 seconds. Prevent
|
||||
# intermittent false positives on slow platforms by subtracting the number of
|
||||
# seconds which passed between key creation and invoking 'rndc reconfig'.
|
||||
next_time=$((14400 - time_passed))
|
||||
# Next key event is when all zone signatures are signed with the new
|
||||
# algorithm. This is the max-zone-ttl plus zone propagation delay
|
||||
# plus retire safety: 6h + 1h + 2h. But three hours have already passed
|
||||
# (the time it took to make the DNSKEY omnipresent), so the next event
|
||||
# should be scheduled in 6 hour: 21600 seconds. Prevent intermittent
|
||||
# false positives on slow platforms by subtracting the number of seconds
|
||||
# which passed between key creation and invoking 'rndc reconfig'.
|
||||
next_time=$((21600 - time_passed))
|
||||
check_next_key_event $next_time
|
||||
|
||||
#
|
||||
@@ -4651,17 +5114,17 @@ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_cdslog "$DIR" "$ZONE" KEY2
|
||||
|
||||
# Set expected key times:
|
||||
# - The old key was activated 7 hours ago (25200 seconds).
|
||||
csk_rollover_predecessor_keytimes -25200
|
||||
# - And was retired 3 hours ago (10800 seconds).
|
||||
# - The old key was activated 9 hours ago (32400 seconds).
|
||||
csk_rollover_predecessor_keytimes -32400
|
||||
# - And was retired 6 hours ago (21600 seconds).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -10800
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -21600
|
||||
retired=$(key_get KEY1 RETIRED)
|
||||
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
|
||||
# - The new key was published 9 hours ago.
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_addkeytime "KEY2" "PUBLISHED" "${created}" -25200
|
||||
set_addkeytime "KEY2" "ACTIVE" "${created}" -25200
|
||||
set_addkeytime "KEY2" "PUBLISHED" "${created}" -32400
|
||||
set_addkeytime "KEY2" "ACTIVE" "${created}" -32400
|
||||
published=$(key_get KEY2 PUBLISHED)
|
||||
set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}"
|
||||
|
||||
@@ -4675,9 +5138,9 @@ dnssec_verify
|
||||
rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
|
||||
rndc_checkds "$SERVER" "$DIR" KEY2 "now" "published" "$ZONE"
|
||||
# Next key event is when the DS becomes OMNIPRESENT. This happens after the
|
||||
# parent propagation delay, and DS TTL:
|
||||
# 1h + 2h = 3h = 10800 seconds.
|
||||
check_next_key_event 10800
|
||||
# parent propagation delay, retire safety delay, and DS TTL:
|
||||
# 1h + 2h + 2h = 5h = 18000 seconds.
|
||||
check_next_key_event 18000
|
||||
|
||||
#
|
||||
# Zone: step4.csk-algorithm-roll.kasp
|
||||
@@ -4701,17 +5164,17 @@ wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# Set expected key times:
|
||||
# - The old keys were activated 36 hours ago (129600 seconds).
|
||||
csk_rollover_predecessor_keytimes -129600
|
||||
# - And retired 33 hours ago (118800 seconds).
|
||||
# - The old key was activated 38 hours ago (136800 seconds)
|
||||
csk_rollover_predecessor_keytimes -136800
|
||||
# - And retired 35 hours ago (126000 seconds).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -118800
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -126000
|
||||
retired=$(key_get KEY1 RETIRED)
|
||||
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
|
||||
# - The new key was published 36 hours ago.
|
||||
# - The new key was published 38 hours ago.
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_addkeytime "KEY2" "PUBLISHED" "${created}" -129600
|
||||
set_addkeytime "KEY2" "ACTIVE" "${created}" -129600
|
||||
set_addkeytime "KEY2" "PUBLISHED" "${created}" -136800
|
||||
set_addkeytime "KEY2" "ACTIVE" "${created}" -136800
|
||||
published=$(key_get KEY2 PUBLISHED)
|
||||
set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
|
||||
|
||||
@@ -4741,17 +5204,17 @@ wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# Set expected key times:
|
||||
# - The old key was activated 38 hours ago (136800 seconds)
|
||||
csk_rollover_predecessor_keytimes -136800
|
||||
# - And retired 35 hours ago (126000 seconds).
|
||||
# - The old key was activated 40 hours ago (144000 seconds)
|
||||
csk_rollover_predecessor_keytimes -144000
|
||||
# - And retired 37 hours ago (133200 seconds).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -126000
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -133200
|
||||
retired=$(key_get KEY1 RETIRED)
|
||||
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
|
||||
# - The new key was published 38 hours ago.
|
||||
# - The new key was published 40 hours ago.
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_addkeytime "KEY2" "PUBLISHED" "${created}" -136800
|
||||
set_addkeytime "KEY2" "ACTIVE" "${created}" -136800
|
||||
set_addkeytime "KEY2" "PUBLISHED" "${created}" -144000
|
||||
set_addkeytime "KEY2" "ACTIVE" "${created}" -144000
|
||||
published=$(key_get KEY2 PUBLISHED)
|
||||
set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
|
||||
|
||||
@@ -4762,12 +5225,12 @@ check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Next key event is when the RSASHA1 signatures become HIDDEN. This happens
|
||||
# after the max-zone-ttl plus zone propagation delay (6h + 1h) minus the
|
||||
# time already passed since the UNRETENTIVE state has been reached (2h):
|
||||
# 7h - 2h = 5h = 18000 seconds. Prevent intermittent false positives on slow
|
||||
# platforms by subtracting the number of seconds which passed between key
|
||||
# creation and invoking 'rndc reconfig'.
|
||||
next_time=$((18000 - time_passed))
|
||||
# after the max-zone-ttl plus zone propagation delay plus retire safety
|
||||
# (6h + 1h + 2h) minus the time already passed since the UNRETENTIVE state has
|
||||
# been reached (2h): 9h - 2h = 7h = 25200 seconds. Prevent intermittent
|
||||
# false positives on slow platforms by subtracting the number of seconds
|
||||
# which passed between key creation and invoking 'rndc reconfig'.
|
||||
next_time=$((25200 - time_passed))
|
||||
check_next_key_event $next_time
|
||||
|
||||
#
|
||||
@@ -4785,17 +5248,17 @@ wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# Set expected key times:
|
||||
# - The old keys were activated 45 hours ago (162000 seconds)
|
||||
csk_rollover_predecessor_keytimes -162000
|
||||
# - And retired 42 hours ago (151200 seconds).
|
||||
# - The old keys were activated 47 hours ago (169200 seconds)
|
||||
csk_rollover_predecessor_keytimes -169200
|
||||
# - And retired 44 hours ago (158400 seconds).
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -151200
|
||||
set_addkeytime "KEY1" "RETIRED" "${created}" -158400
|
||||
retired=$(key_get KEY1 RETIRED)
|
||||
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
|
||||
# - The new key was published 47 hours ago.
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_addkeytime "KEY2" "PUBLISHED" "${created}" -162000
|
||||
set_addkeytime "KEY2" "ACTIVE" "${created}" -162000
|
||||
set_addkeytime "KEY2" "PUBLISHED" "${created}" -169200
|
||||
set_addkeytime "KEY2" "ACTIVE" "${created}" -169200
|
||||
published=$(key_get KEY2 PUBLISHED)
|
||||
set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
|
||||
|
||||
|
||||
@@ -1,569 +0,0 @@
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
import dns
|
||||
import dns.update
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
from isctest.kasp import (
|
||||
KeyProperties,
|
||||
KeyTimingMetadata,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"K*.private",
|
||||
"K*.backup",
|
||||
"K*.cmp",
|
||||
"K*.key",
|
||||
"K*.state",
|
||||
"*.axfr",
|
||||
"*.created",
|
||||
"dig.out*",
|
||||
"keyevent.out.*",
|
||||
"keygen.out.*",
|
||||
"keys",
|
||||
"published.test*",
|
||||
"python.out.*",
|
||||
"retired.test*",
|
||||
"rndc.dnssec.*.out.*",
|
||||
"rndc.zonestatus.out.*",
|
||||
"rrsig.out.*",
|
||||
"created.key-*",
|
||||
"unused.key-*",
|
||||
"verify.out.*",
|
||||
"zone.out.*",
|
||||
"ns*/K*.key",
|
||||
"ns*/K*.offline",
|
||||
"ns*/K*.private",
|
||||
"ns*/K*.state",
|
||||
"ns*/*.db",
|
||||
"ns*/*.db.infile",
|
||||
"ns*/*.db.signed",
|
||||
"ns*/*.db.signed.tmp",
|
||||
"ns*/*.jbk",
|
||||
"ns*/*.jnl",
|
||||
"ns*/*.zsk1",
|
||||
"ns*/*.zsk2",
|
||||
"ns*/dsset-*",
|
||||
"ns*/keygen.out.*",
|
||||
"ns*/keys",
|
||||
"ns*/ksk",
|
||||
"ns*/ksk/K*",
|
||||
"ns*/zsk",
|
||||
"ns*/zsk",
|
||||
"ns*/zsk/K*",
|
||||
"ns*/named-fips.conf",
|
||||
"ns*/settime.out.*",
|
||||
"ns*/signer.out.*",
|
||||
"ns*/zones",
|
||||
"ns*/policies/*.conf",
|
||||
"ns3/legacy-keys.*",
|
||||
"ns3/dynamic-signed-inline-signing.kasp.db.signed.signed",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def check_all(server, zone, policy, ksks, zsks, tsig=None):
|
||||
isctest.kasp.check_dnssecstatus(server, zone, ksks + zsks, policy=policy)
|
||||
isctest.kasp.check_apex(server, zone, ksks, zsks, tsig=tsig)
|
||||
isctest.kasp.check_subdomain(server, zone, ksks, zsks, tsig=tsig)
|
||||
isctest.kasp.check_dnssec_verify(server, zone)
|
||||
|
||||
|
||||
def set_keytimes_default_policy(kp):
|
||||
# The first key is immediately published and activated.
|
||||
kp.timing["Generated"] = kp.key.get_timing("Created")
|
||||
kp.timing["Published"] = kp.timing["Generated"]
|
||||
kp.timing["Active"] = kp.timing["Generated"]
|
||||
# The DS can be published if the DNSKEY and RRSIG records are
|
||||
# OMNIPRESENT. This happens after max-zone-ttl (1d) plus
|
||||
# plus zone-propagation-delay (300s).
|
||||
kp.timing["PublishCDS"] = kp.timing["Published"] + timedelta(days=1, seconds=300)
|
||||
# Key lifetime is unlimited, so not setting 'Retired' nor 'Removed'.
|
||||
kp.timing["DNSKEYChange"] = kp.timing["Published"]
|
||||
kp.timing["DSChange"] = kp.timing["Published"]
|
||||
kp.timing["KRRSIGChange"] = kp.timing["Active"]
|
||||
kp.timing["ZRRSIGChange"] = kp.timing["Active"]
|
||||
|
||||
|
||||
def test_kasp_default(servers):
|
||||
server = servers["ns3"]
|
||||
|
||||
# check the zone with default kasp policy has loaded and is signed.
|
||||
isctest.log.info("check a zone with the default policy is signed")
|
||||
zone = "default.kasp"
|
||||
policy = "default"
|
||||
|
||||
# Key properties.
|
||||
# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
|
||||
keyprops = [
|
||||
"csk 0 13 256 goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden",
|
||||
]
|
||||
expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops)
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3")
|
||||
isctest.kasp.check_zone_is_signed(server, zone)
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
set_keytimes_default_policy(expected[0])
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
check_all(server, zone, policy, keys, [])
|
||||
|
||||
# Trigger a keymgr run. Make sure the key files are not touched if there
|
||||
# are no modifications to the key metadata.
|
||||
isctest.log.info(
|
||||
"check that key files are untouched if there are no metadata changes"
|
||||
)
|
||||
key = keys[0]
|
||||
privkey_stat = os.stat(key.privatefile)
|
||||
pubkey_stat = os.stat(key.keyfile)
|
||||
state_stat = os.stat(key.statefile)
|
||||
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
assert privkey_stat.st_mtime == os.stat(key.privatefile).st_mtime
|
||||
assert pubkey_stat.st_mtime == os.stat(key.keyfile).st_mtime
|
||||
assert state_stat.st_mtime == os.stat(key.statefile).st_mtime
|
||||
|
||||
# again
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
assert privkey_stat.st_mtime == os.stat(key.privatefile).st_mtime
|
||||
assert pubkey_stat.st_mtime == os.stat(key.keyfile).st_mtime
|
||||
assert state_stat.st_mtime == os.stat(key.statefile).st_mtime
|
||||
|
||||
# modify unsigned zone file and check that new record is signed.
|
||||
isctest.log.info("check that an updated zone signs the new record")
|
||||
shutil.copyfile("ns3/template2.db.in", f"ns3/{zone}.db")
|
||||
server.rndc(f"reload {zone}", log=False)
|
||||
|
||||
def update_is_signed():
|
||||
parts = update.split()
|
||||
qname = parts[0]
|
||||
qtype = dns.rdatatype.from_text(parts[1])
|
||||
rdata = parts[2]
|
||||
return isctest.kasp.check_update_is_signed(
|
||||
server, zone, qname, qtype, rdata, keys, []
|
||||
)
|
||||
|
||||
expected_updates = [f"a.{zone}. A 10.0.0.11", f"d.{zone}. A 10.0.0.44"]
|
||||
for update in expected_updates:
|
||||
isctest.run.retry_with_timeout(update_is_signed, timeout=5)
|
||||
|
||||
# Move the private key file, a rekey event should not introduce
|
||||
# replacement keys.
|
||||
isctest.log.info("check that missing private key doesn't trigger rollover")
|
||||
shutil.move(f"{key.privatefile}", f"{key.path}.offline")
|
||||
expectmsg = "zone_rekey:zone_verifykeys failed: some key files are missing"
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"zone {zone}/IN (signed): {expectmsg}")
|
||||
# Nothing has changed.
|
||||
expected[0].properties["private"] = False
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
check_all(server, zone, policy, keys, [])
|
||||
|
||||
# A zone that uses inline-signing.
|
||||
isctest.log.info("check an inline-signed zone with the default policy is signed")
|
||||
zone = "inline-signing.kasp"
|
||||
# Key properties.
|
||||
key1 = KeyProperties.default()
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3")
|
||||
expected = [key1]
|
||||
isctest.kasp.check_zone_is_signed(server, zone)
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
set_keytimes_default_policy(key1)
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
check_all(server, zone, policy, keys, [])
|
||||
|
||||
|
||||
def test_kasp_dynamic(servers):
|
||||
# Dynamic update test cases.
|
||||
server = servers["ns3"]
|
||||
|
||||
# Standard dynamic zone.
|
||||
isctest.log.info("check dynamic zone is updated and signed after update")
|
||||
zone = "dynamic.kasp"
|
||||
policy = "default"
|
||||
# Key properties.
|
||||
key1 = KeyProperties.default()
|
||||
expected = [key1]
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3")
|
||||
isctest.kasp.check_zone_is_signed(server, zone)
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
set_keytimes_default_policy(key1)
|
||||
expected = [key1]
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
check_all(server, zone, policy, keys, [])
|
||||
|
||||
# Update zone with nsupdate.
|
||||
def nsupdate():
|
||||
message = dns.update.UpdateMessage(zone)
|
||||
for update in updates:
|
||||
if update[0] == 0:
|
||||
message.delete(update[1], update[2], update[3])
|
||||
else:
|
||||
message.add(update[1], update[2], update[3], update[4])
|
||||
|
||||
try:
|
||||
response = isctest.query.udp(
|
||||
message, server.ip, server.ports.dns, timeout=3
|
||||
)
|
||||
assert response.rcode() == dns.rcode.NOERROR
|
||||
except dns.exception.Timeout:
|
||||
isctest.log.info(f"error: update timeout for {zone}")
|
||||
|
||||
isctest.log.debug(f"update of zone {zone} to server {server.ip} successful")
|
||||
|
||||
def update_is_signed():
|
||||
parts = update.split()
|
||||
qname = parts[0]
|
||||
qtype = dns.rdatatype.from_text(parts[1])
|
||||
rdata = parts[2]
|
||||
return isctest.kasp.check_update_is_signed(
|
||||
server, zone, qname, qtype, rdata, keys, []
|
||||
)
|
||||
|
||||
updates = [
|
||||
[0, f"a.{zone}.", "A", "10.0.0.1"],
|
||||
[1, f"a.{zone}.", 300, "A", "10.0.0.101"],
|
||||
[1, f"d.{zone}.", 300, "A", "10.0.0.4"],
|
||||
]
|
||||
nsupdate()
|
||||
|
||||
expected_updates = [f"a.{zone}. A 10.0.0.101", f"d.{zone}. A 10.0.0.4"]
|
||||
for update in expected_updates:
|
||||
isctest.run.retry_with_timeout(update_is_signed, timeout=5)
|
||||
|
||||
# Update zone with nsupdate (reverting the above change).
|
||||
updates = [
|
||||
[1, f"a.{zone}.", 300, "A", "10.0.0.1"],
|
||||
[0, f"a.{zone}.", "A", "10.0.0.101"],
|
||||
[0, f"d.{zone}.", "A", "10.0.0.4"],
|
||||
]
|
||||
nsupdate()
|
||||
|
||||
update = f"a.{zone}. A 10.0.0.1"
|
||||
isctest.run.retry_with_timeout(update_is_signed, timeout=5)
|
||||
|
||||
# Update zone with freeze/thaw.
|
||||
isctest.log.info("check dynamic zone is updated and signed after freeze and thaw")
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"freeze {zone}", log=False)
|
||||
watcher.wait_for_line(f"freezing zone '{zone}/IN': success")
|
||||
|
||||
time.sleep(1)
|
||||
with open(f"ns3/{zone}.db", "a", encoding="utf-8") as zonefile:
|
||||
zonefile.write(f"d.{zone}. 300 A 10.0.0.44\n")
|
||||
time.sleep(1)
|
||||
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"thaw {zone}", log=False)
|
||||
watcher.wait_for_line(f"thawing zone '{zone}/IN': success")
|
||||
|
||||
expected_updates = [f"a.{zone}. A 10.0.0.1", f"d.{zone}. A 10.0.0.44"]
|
||||
|
||||
for update in expected_updates:
|
||||
isctest.run.retry_with_timeout(update_is_signed, timeout=5)
|
||||
|
||||
# Dynamic, and inline-signing.
|
||||
zone = "dynamic-inline-signing.kasp"
|
||||
# Key properties.
|
||||
key1 = KeyProperties.default()
|
||||
expected = [key1]
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3")
|
||||
isctest.kasp.check_zone_is_signed(server, zone)
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
set_keytimes_default_policy(key1)
|
||||
expected = [key1]
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
check_all(server, zone, policy, keys, [])
|
||||
|
||||
# Update zone with freeze/thaw.
|
||||
isctest.log.info(
|
||||
"check dynamic inline-signed zone is updated and signed after freeze and thaw"
|
||||
)
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"freeze {zone}", log=False)
|
||||
watcher.wait_for_line(f"freezing zone '{zone}/IN': success")
|
||||
|
||||
time.sleep(1)
|
||||
shutil.copyfile("ns3/template2.db.in", f"ns3/{zone}.db")
|
||||
time.sleep(1)
|
||||
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"thaw {zone}", log=False)
|
||||
watcher.wait_for_line(f"thawing zone '{zone}/IN': success")
|
||||
|
||||
expected_updates = [f"a.{zone}. A 10.0.0.11", f"d.{zone}. A 10.0.0.44"]
|
||||
for update in expected_updates:
|
||||
isctest.run.retry_with_timeout(update_is_signed, timeout=5)
|
||||
|
||||
# Dynamic, signed, and inline-signing.
|
||||
isctest.log.info("check dynamic signed, and inline-signed zone")
|
||||
zone = "dynamic-signed-inline-signing.kasp"
|
||||
# Key properties.
|
||||
key1 = KeyProperties.default()
|
||||
# The ns3/setup.sh script sets all states to omnipresent.
|
||||
key1.metadata["DNSKEYState"] = "omnipresent"
|
||||
key1.metadata["KRRSIGState"] = "omnipresent"
|
||||
key1.metadata["ZRRSIGState"] = "omnipresent"
|
||||
key1.metadata["DSState"] = "omnipresent"
|
||||
expected = [key1]
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3/keys")
|
||||
isctest.kasp.check_zone_is_signed(server, zone)
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
check_all(server, zone, policy, keys, [])
|
||||
# Ensure no zone_resigninc for the unsigned version of the zone is triggered.
|
||||
assert f"zone_resigninc: zone {zone}/IN (unsigned): enter" not in "ns3/named.run"
|
||||
|
||||
|
||||
def test_kasp_special_cases(servers):
|
||||
server = servers["ns3"]
|
||||
|
||||
# Insecure zones.
|
||||
isctest.log.info("check insecure zones")
|
||||
|
||||
zone = "insecure.kasp"
|
||||
expected = []
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3")
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
isctest.kasp.check_dnssecstatus(server, zone, keys, policy="insecure")
|
||||
isctest.kasp.check_apex(server, zone, keys, [])
|
||||
isctest.kasp.check_subdomain(server, zone, keys, [])
|
||||
|
||||
zone = "unsigned.kasp"
|
||||
expected = []
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3")
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
isctest.kasp.check_dnssecstatus(server, zone, keys, policy=None)
|
||||
isctest.kasp.check_apex(server, zone, keys, [])
|
||||
isctest.kasp.check_subdomain(server, zone, keys, [])
|
||||
# Make sure the zone file is untouched.
|
||||
isctest.check.file_contents_equal(f"ns3/{zone}.db.infile", f"ns3/{zone}.db")
|
||||
|
||||
# A zone with special characters.
|
||||
isctest.log.info("check special characters")
|
||||
|
||||
zone = r'i-am.":\;?&[]\@!\$*+,|=\.\(\)special.kasp'
|
||||
# It is non-trivial to adapt the tests to deal with all possible different
|
||||
# escaping characters, so we will just try to verify the zone.
|
||||
isctest.kasp.check_dnssec_verify(server, zone)
|
||||
|
||||
# check that max-zone-ttl rejects zones with too high TTL.
|
||||
isctest.log.info("check max-zone-ttl rejects zones with too high TTL")
|
||||
zone = "max-zone-ttl.kasp"
|
||||
assert f"loading from master file {zone}.db failed: out of range" in server.log
|
||||
|
||||
|
||||
def test_kasp_dnssec_keygen():
|
||||
def keygen(zone, policy, keydir=None):
|
||||
if keydir is None:
|
||||
keydir = "."
|
||||
|
||||
keygen_command = [
|
||||
os.environ.get("KEYGEN"),
|
||||
"-K",
|
||||
keydir,
|
||||
"-k",
|
||||
policy,
|
||||
"-l",
|
||||
"kasp.conf",
|
||||
zone,
|
||||
]
|
||||
|
||||
return isctest.run.cmd(keygen_command, log_stdout=True).stdout.decode("utf-8")
|
||||
|
||||
# check that 'dnssec-keygen -k' (configured policy) creates valid files.
|
||||
lifetime = {
|
||||
"P1Y": int(timedelta(days=365).total_seconds()),
|
||||
"P30D": int(timedelta(days=30).total_seconds()),
|
||||
"P6M": int(timedelta(days=31 * 6).total_seconds()),
|
||||
}
|
||||
keyprops = [
|
||||
f"csk {lifetime['P1Y']} 13 256",
|
||||
f"ksk {lifetime['P1Y']} 8 2048",
|
||||
f"zsk {lifetime['P30D']} 8 2048",
|
||||
f"zsk {lifetime['P6M']} 8 3072",
|
||||
]
|
||||
keydir = "keys"
|
||||
out = keygen("kasp", "kasp", keydir)
|
||||
keys = isctest.kasp.keystr_to_keylist(out, keydir)
|
||||
expected = isctest.kasp.policy_to_properties(ttl=200, keys=keyprops)
|
||||
isctest.kasp.check_keys("kasp", keys, expected)
|
||||
|
||||
# check that 'dnssec-keygen -k' (default policy) creates valid files.
|
||||
keyprops = ["csk 0 13 256"]
|
||||
out = keygen("kasp", "default")
|
||||
keys = isctest.kasp.keystr_to_keylist(out)
|
||||
expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops)
|
||||
isctest.kasp.check_keys("kasp", keys, expected)
|
||||
|
||||
# check that 'dnssec-settime' by default does not edit key state file.
|
||||
key = keys[0]
|
||||
privatefile = f"{key.path}.private"
|
||||
keyfile = f"{key.path}.key"
|
||||
statefile = f"{key.path}.state"
|
||||
shutil.copyfile(privatefile, f"{privatefile}.backup")
|
||||
shutil.copyfile(keyfile, f"{keyfile}.backup")
|
||||
shutil.copyfile(statefile, f"{statefile}.backup")
|
||||
|
||||
created = key.get_timing("Created")
|
||||
publish = key.get_timing("Publish") + timedelta(hours=1)
|
||||
settime = [
|
||||
os.environ.get("SETTIME"),
|
||||
"-P",
|
||||
str(publish),
|
||||
key.path,
|
||||
]
|
||||
out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8")
|
||||
|
||||
isctest.check.file_contents_equal(f"{key.path}.state", f"{key.path}.state.backup")
|
||||
assert key.get_metadata("Publish", file=key.privatefile) == str(publish)
|
||||
assert key.get_metadata("Publish", file=key.keyfile, comment=True) == str(publish)
|
||||
|
||||
# check that 'dnssec-settime -s' also sets publish time metadata and
|
||||
# states in key state file.
|
||||
now = KeyTimingMetadata.now()
|
||||
goal = "omnipresent"
|
||||
dnskey = "rumoured"
|
||||
krrsig = "rumoured"
|
||||
zrrsig = "omnipresent"
|
||||
ds = "hidden"
|
||||
keyprops = [
|
||||
f"csk 0 13 256 goal:{goal} dnskey:{dnskey} krrsig:{krrsig} zrrsig:{zrrsig} ds:{ds}",
|
||||
]
|
||||
expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops)
|
||||
expected[0].timing = {
|
||||
"Generated": created,
|
||||
"Published": now,
|
||||
"Active": created,
|
||||
"DNSKEYChange": now,
|
||||
"KRRSIGChange": now,
|
||||
"ZRRSIGChange": now,
|
||||
"DSChange": now,
|
||||
}
|
||||
|
||||
settime = [
|
||||
os.environ.get("SETTIME"),
|
||||
"-s",
|
||||
"-P",
|
||||
str(now),
|
||||
"-g",
|
||||
goal,
|
||||
"-k",
|
||||
dnskey,
|
||||
str(now),
|
||||
"-r",
|
||||
krrsig,
|
||||
str(now),
|
||||
"-z",
|
||||
zrrsig,
|
||||
str(now),
|
||||
"-d",
|
||||
ds,
|
||||
str(now),
|
||||
key.path,
|
||||
]
|
||||
out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8")
|
||||
isctest.kasp.check_keys("kasp", keys, expected)
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
|
||||
# check that 'dnssec-settime -s' also unsets publish time metadata and
|
||||
# states in key state file.
|
||||
now = KeyTimingMetadata.now()
|
||||
keyprops = ["csk 0 13 256"]
|
||||
expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops)
|
||||
expected[0].timing = {
|
||||
"Generated": created,
|
||||
"Active": created,
|
||||
}
|
||||
|
||||
settime = [
|
||||
os.environ.get("SETTIME"),
|
||||
"-s",
|
||||
"-P",
|
||||
"none",
|
||||
"-g",
|
||||
"none",
|
||||
"-k",
|
||||
"none",
|
||||
str(now),
|
||||
"-z",
|
||||
"none",
|
||||
str(now),
|
||||
"-r",
|
||||
"none",
|
||||
str(now),
|
||||
"-d",
|
||||
"none",
|
||||
str(now),
|
||||
key.path,
|
||||
]
|
||||
out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8")
|
||||
isctest.kasp.check_keys("kasp", keys, expected)
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
|
||||
# check that 'dnssec-settime -s' also sets active time metadata and states in key state file (uppercase)
|
||||
soon = now + timedelta(hours=2)
|
||||
goal = "hidden"
|
||||
dnskey = "unretentive"
|
||||
krrsig = "omnipresent"
|
||||
zrrsig = "unretentive"
|
||||
ds = "omnipresent"
|
||||
keyprops = [
|
||||
f"csk 0 13 256 goal:{goal} dnskey:{dnskey} krrsig:{krrsig} zrrsig:{zrrsig} ds:{ds}",
|
||||
]
|
||||
expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops)
|
||||
expected[0].timing = {
|
||||
"Generated": created,
|
||||
"Active": soon,
|
||||
"DNSKEYChange": soon,
|
||||
"KRRSIGChange": soon,
|
||||
"ZRRSIGChange": soon,
|
||||
"DSChange": soon,
|
||||
}
|
||||
|
||||
settime = [
|
||||
os.environ.get("SETTIME"),
|
||||
"-s",
|
||||
"-A",
|
||||
str(soon),
|
||||
"-g",
|
||||
"HIDDEN",
|
||||
"-k",
|
||||
"UNRETENTIVE",
|
||||
str(soon),
|
||||
"-z",
|
||||
"UNRETENTIVE",
|
||||
str(soon),
|
||||
"-r",
|
||||
"OMNIPRESENT",
|
||||
str(soon),
|
||||
"-d",
|
||||
"OMNIPRESENT",
|
||||
str(soon),
|
||||
key.path,
|
||||
]
|
||||
out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8")
|
||||
isctest.kasp.check_keys("kasp", keys, expected)
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
@@ -10,14 +10,19 @@
|
||||
# information regarding copyright ownership.
|
||||
|
||||
from datetime import timedelta
|
||||
import difflib
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
from typing import List, Optional
|
||||
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
from isctest.kasp import KeyTimingMetadata
|
||||
from isctest.kasp import (
|
||||
Key,
|
||||
KeyTimingMetadata,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
@@ -84,6 +89,31 @@ def between(value, start, end):
|
||||
return start < value < end
|
||||
|
||||
|
||||
def check_file_contents_equal(file1, file2):
|
||||
def normalize_line(line):
|
||||
# remove trailing&leading whitespace and replace multiple whitespaces
|
||||
return " ".join(line.split())
|
||||
|
||||
def read_lines(file_path):
|
||||
with open(file_path, "r", encoding="utf-8") as file:
|
||||
return [normalize_line(line) for line in file.readlines()]
|
||||
|
||||
lines1 = read_lines(file1)
|
||||
lines2 = read_lines(file2)
|
||||
|
||||
differ = difflib.Differ()
|
||||
diff = differ.compare(lines1, lines2)
|
||||
|
||||
for line in diff:
|
||||
assert not line.startswith("+ ") and not line.startswith(
|
||||
"- "
|
||||
), f'file contents of "{file1}" and "{file2}" differ'
|
||||
|
||||
|
||||
def keystr_to_keylist(keystr: str, keydir: Optional[str] = None) -> List[Key]:
|
||||
return [Key(name, keydir) for name in keystr.split()]
|
||||
|
||||
|
||||
def ksr(zone, policy, action, options="", raise_on_exception=True):
|
||||
ksr_command = [
|
||||
os.environ.get("KSR"),
|
||||
@@ -485,14 +515,14 @@ def test_ksr_common(servers):
|
||||
# create ksk
|
||||
kskdir = "ns1/offline"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +1y -o")
|
||||
ksks = isctest.kasp.keystr_to_keylist(out, kskdir)
|
||||
ksks = keystr_to_keylist(out, kskdir)
|
||||
assert len(ksks) == 1
|
||||
|
||||
check_keys(ksks, None)
|
||||
|
||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||
out, _ = ksr(zone, policy, "keygen", options="-i now -e +1y")
|
||||
zsks = isctest.kasp.keystr_to_keylist(out)
|
||||
zsks = keystr_to_keylist(out)
|
||||
assert len(zsks) == 2
|
||||
|
||||
lifetime = timedelta(days=31 * 6)
|
||||
@@ -502,7 +532,7 @@ def test_ksr_common(servers):
|
||||
# in the given key directory
|
||||
zskdir = "ns1"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +1y")
|
||||
zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
zsks = keystr_to_keylist(out, zskdir)
|
||||
assert len(zsks) == 2
|
||||
|
||||
lifetime = timedelta(days=31 * 6)
|
||||
@@ -545,22 +575,18 @@ def test_ksr_common(servers):
|
||||
# check that 'dnssec-ksr keygen' selects pregenerated keys for
|
||||
# the same time bundle
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i {now} -e +1y")
|
||||
selected_zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
selected_zsks = keystr_to_keylist(out, zskdir)
|
||||
assert len(selected_zsks) == 2
|
||||
for index, key in enumerate(selected_zsks):
|
||||
assert zsks[index] == key
|
||||
isctest.check.file_contents_equal(
|
||||
f"{key.path}.private", f"{key.path}.private.backup"
|
||||
)
|
||||
isctest.check.file_contents_equal(f"{key.path}.key", f"{key.path}.key.backup")
|
||||
isctest.check.file_contents_equal(
|
||||
f"{key.path}.state", f"{key.path}.state.backup"
|
||||
)
|
||||
check_file_contents_equal(f"{key.path}.private", f"{key.path}.private.backup")
|
||||
check_file_contents_equal(f"{key.path}.key", f"{key.path}.key.backup")
|
||||
check_file_contents_equal(f"{key.path}.state", f"{key.path}.state.backup")
|
||||
|
||||
# check that 'dnssec-ksr keygen' generates only necessary keys for
|
||||
# overlapping time bundle
|
||||
out, err = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i {now} -e +2y -v 1")
|
||||
overlapping_zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
overlapping_zsks = keystr_to_keylist(out, zskdir)
|
||||
assert len(overlapping_zsks) == 4
|
||||
|
||||
verbose = err.split()
|
||||
@@ -576,19 +602,15 @@ def test_ksr_common(servers):
|
||||
for index, key in enumerate(overlapping_zsks):
|
||||
if index < 2:
|
||||
assert zsks[index] == key
|
||||
isctest.check.file_contents_equal(
|
||||
check_file_contents_equal(
|
||||
f"{key.path}.private", f"{key.path}.private.backup"
|
||||
)
|
||||
isctest.check.file_contents_equal(
|
||||
f"{key.path}.key", f"{key.path}.key.backup"
|
||||
)
|
||||
isctest.check.file_contents_equal(
|
||||
f"{key.path}.state", f"{key.path}.state.backup"
|
||||
)
|
||||
check_file_contents_equal(f"{key.path}.key", f"{key.path}.key.backup")
|
||||
check_file_contents_equal(f"{key.path}.state", f"{key.path}.state.backup")
|
||||
|
||||
# run 'dnssec-ksr keygen' again with verbosity 0
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i {now} -e +2y")
|
||||
overlapping_zsks2 = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
overlapping_zsks2 = keystr_to_keylist(out, zskdir)
|
||||
assert len(overlapping_zsks2) == 4
|
||||
check_keys(overlapping_zsks2, lifetime)
|
||||
for index, key in enumerate(overlapping_zsks2):
|
||||
@@ -683,7 +705,7 @@ def test_ksr_lastbundle(servers):
|
||||
kskdir = "ns1/offline"
|
||||
offset = -timedelta(days=365)
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i -1y -e +1d -o")
|
||||
ksks = isctest.kasp.keystr_to_keylist(out, kskdir)
|
||||
ksks = keystr_to_keylist(out, kskdir)
|
||||
assert len(ksks) == 1
|
||||
|
||||
check_keys(ksks, None, offset=offset)
|
||||
@@ -691,7 +713,7 @@ def test_ksr_lastbundle(servers):
|
||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||
zskdir = "ns1"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i -1y -e +1d")
|
||||
zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
zsks = keystr_to_keylist(out, zskdir)
|
||||
assert len(zsks) == 2
|
||||
|
||||
lifetime = timedelta(days=31 * 6)
|
||||
@@ -762,7 +784,7 @@ def test_ksr_inthemiddle(servers):
|
||||
kskdir = "ns1/offline"
|
||||
offset = -timedelta(days=365)
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i -1y -e +1y -o")
|
||||
ksks = isctest.kasp.keystr_to_keylist(out, kskdir)
|
||||
ksks = keystr_to_keylist(out, kskdir)
|
||||
assert len(ksks) == 1
|
||||
|
||||
check_keys(ksks, None, offset=offset)
|
||||
@@ -770,7 +792,7 @@ def test_ksr_inthemiddle(servers):
|
||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||
zskdir = "ns1"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i -1y -e +1y")
|
||||
zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
zsks = keystr_to_keylist(out, zskdir)
|
||||
assert len(zsks) == 4
|
||||
|
||||
lifetime = timedelta(days=31 * 6)
|
||||
@@ -842,13 +864,13 @@ def check_ksr_rekey_logs_error(server, zone, policy, offset, end):
|
||||
then = now + offset
|
||||
until = now + end
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i {then} -e {until} -o")
|
||||
ksks = isctest.kasp.keystr_to_keylist(out, kskdir)
|
||||
ksks = keystr_to_keylist(out, kskdir)
|
||||
assert len(ksks) == 1
|
||||
|
||||
# key generation
|
||||
zskdir = "ns1"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i {then} -e {until}")
|
||||
zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
zsks = keystr_to_keylist(out, zskdir)
|
||||
assert len(zsks) == 2
|
||||
|
||||
# create request
|
||||
@@ -915,7 +937,7 @@ def test_ksr_unlimited(servers):
|
||||
# create ksk
|
||||
kskdir = "ns1/offline"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +2y -o")
|
||||
ksks = isctest.kasp.keystr_to_keylist(out, kskdir)
|
||||
ksks = keystr_to_keylist(out, kskdir)
|
||||
assert len(ksks) == 1
|
||||
|
||||
check_keys(ksks, None)
|
||||
@@ -923,7 +945,7 @@ def test_ksr_unlimited(servers):
|
||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||
zskdir = "ns1"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +2y")
|
||||
zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
zsks = keystr_to_keylist(out, zskdir)
|
||||
assert len(zsks) == 1
|
||||
|
||||
lifetime = None
|
||||
@@ -1032,7 +1054,7 @@ def test_ksr_twotone(servers):
|
||||
# create ksk
|
||||
kskdir = "ns1/offline"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +1y -o")
|
||||
ksks = isctest.kasp.keystr_to_keylist(out, kskdir)
|
||||
ksks = keystr_to_keylist(out, kskdir)
|
||||
assert len(ksks) == 2
|
||||
|
||||
ksks_defalg = []
|
||||
@@ -1056,7 +1078,7 @@ def test_ksr_twotone(servers):
|
||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||
zskdir = "ns1"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +1y")
|
||||
zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
zsks = keystr_to_keylist(out, zskdir)
|
||||
# First algorithm keys have a lifetime of 3 months, so there should
|
||||
# be 4 created keys. Second algorithm keys have a lifetime of 5
|
||||
# months, so there should be 3 created keys. While only two time
|
||||
@@ -1150,7 +1172,7 @@ def test_ksr_kskroll(servers):
|
||||
# create ksk
|
||||
kskdir = "ns1/offline"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +1y -o")
|
||||
ksks = isctest.kasp.keystr_to_keylist(out, kskdir)
|
||||
ksks = keystr_to_keylist(out, kskdir)
|
||||
assert len(ksks) == 2
|
||||
|
||||
lifetime = timedelta(days=31 * 6)
|
||||
@@ -1159,7 +1181,7 @@ def test_ksr_kskroll(servers):
|
||||
# check that 'dnssec-ksr keygen' pregenerates right amount of keys
|
||||
zskdir = "ns1"
|
||||
out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +1y")
|
||||
zsks = isctest.kasp.keystr_to_keylist(out, zskdir)
|
||||
zsks = keystr_to_keylist(out, zskdir)
|
||||
assert len(zsks) == 1
|
||||
|
||||
check_keys(zsks, None)
|
||||
|
||||
@@ -111,7 +111,7 @@ cleanup:
|
||||
}
|
||||
|
||||
if (mctx != NULL) {
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
}
|
||||
|
||||
return result != ISC_R_SUCCESS ? 1 : 0;
|
||||
|
||||
@@ -102,23 +102,6 @@ def test_rpz_passthru_logging():
|
||||
dns.rrset.from_text("allowed.", 300, "IN", "A", "10.53.0.2")
|
||||
]
|
||||
|
||||
# Should also generate a log entry into rpz_passthru.txt
|
||||
msg_allowed_any = dns.message.make_query("allowed.", "ANY")
|
||||
res_allowed_any = isctest.query.udp(
|
||||
msg_allowed_any,
|
||||
resolver_ip,
|
||||
source="10.53.0.1",
|
||||
expected_rcode=dns.rcode.NOERROR,
|
||||
)
|
||||
assert res_allowed_any.answer == [
|
||||
dns.rrset.from_text("allowed.", 300, "IN", "NS", "ns1.allowed."),
|
||||
dns.rrset.from_text("allowed.", 300, "IN", "A", "10.53.0.2"),
|
||||
]
|
||||
# The comparison above doesn't compare the TTL values, and we want to
|
||||
# make sure that the "passthru" rpz doesn't cap the TTL with max-policy-ttl.
|
||||
assert res_allowed_any.answer[0].ttl > 200
|
||||
assert res_allowed_any.answer[1].ttl > 200
|
||||
|
||||
# baddomain.com isn't allowed (CNAME .), should return NXDOMAIN
|
||||
# Should generate a log entry into rpz.txt
|
||||
msg_not_allowed = dns.message.make_query("baddomain.", "A")
|
||||
|
||||
@@ -140,7 +140,7 @@ main(int argc, char **argv) {
|
||||
printf("%s\n", filename);
|
||||
dst_key_free(&key);
|
||||
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ sub construct_ns_command {
|
||||
$command = "taskset $taskset $NAMED ";
|
||||
} elsif ($ENV{'USE_RR'}) {
|
||||
$ENV{'_RR_TRACE_DIR'} = ".";
|
||||
$command = "$ENV{'TOP_BUILDDIR'}/libtool --mode=execute rr record --chaos $NAMED ";
|
||||
$command = "rr record --chaos $NAMED ";
|
||||
} else {
|
||||
$command = "$NAMED ";
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ main(int argc, char *argv[]) {
|
||||
if (printmemstats) {
|
||||
isc_mem_stats(mctx, stdout);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -425,7 +425,7 @@ cleanup:
|
||||
if (message != NULL) {
|
||||
dns_message_detach(&message);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
exit(rv);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ cleanup(void) {
|
||||
isc_lex_destroy(&lex);
|
||||
}
|
||||
if (mctx != NULL) {
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -886,6 +886,31 @@ AC_CHECK_HEADERS([execinfo.h],
|
||||
[AC_SEARCH_LIBS([backtrace_symbols], [execinfo],
|
||||
[AC_CHECK_FUNCS([backtrace_symbols])])])
|
||||
|
||||
#
|
||||
# We do the IPv6 compilation checking after libtool so that we can put
|
||||
# the right suffix on the files.
|
||||
#
|
||||
AC_MSG_CHECKING([for IPv6 structures])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
]],
|
||||
[[
|
||||
struct sockaddr_in6 sin6;
|
||||
struct in6_addr in6;
|
||||
struct in6_pktinfo in6_pi;
|
||||
struct sockaddr_storage storage;
|
||||
in6 = in6addr_any;
|
||||
in6 = in6addr_loopback;
|
||||
sin6.sin6_scope_id = 0;
|
||||
return (0);
|
||||
]])],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_FAILURE([IPv6 support is mandatory])])
|
||||
|
||||
#
|
||||
# Allow forcibly disabling TCP Fast Open support as autodetection might yield
|
||||
# confusing results on some systems (e.g. FreeBSD; see set_tcp_fastopen()
|
||||
|
||||
+1
-1
@@ -154,7 +154,7 @@ main(int argc, char **argv) {
|
||||
if (memstats) {
|
||||
isc_mem_stats(mctx, stderr);
|
||||
}
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
|
||||
fflush(stdout);
|
||||
if (ferror(stdout)) {
|
||||
|
||||
@@ -74,6 +74,6 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
end:
|
||||
dns_db_detach(&db);
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -211,7 +211,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
}
|
||||
|
||||
dns_qp_destroy(&qp);
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
isc_mem_checkdestroyed(stderr);
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(item); i++) {
|
||||
|
||||
@@ -145,6 +145,6 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
cleanup:
|
||||
isc_lex_close(lex);
|
||||
isc_lex_destroy(&lex);
|
||||
isc_mem_detach(&mctx);
|
||||
isc_mem_destroy(&mctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -567,6 +567,14 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
||||
rdataset->ttl = ttlclamp(rdataset->ttl);
|
||||
}
|
||||
|
||||
if (rdtype != dns_rdatatype_a && rdtype != dns_rdatatype_aaaa) {
|
||||
char rb[DNS_RDATATYPE_FORMATSIZE];
|
||||
char nb[DNS_NAME_FORMATSIZE];
|
||||
dns_rdatatype_format(rdtype, rb, sizeof(rb));
|
||||
dns_name_format(adbname->name, nb, sizeof(nb));
|
||||
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
|
||||
"%s has %s", nb, rb);
|
||||
}
|
||||
REQUIRE(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
|
||||
|
||||
for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
|
||||
|
||||
+2
-2
@@ -38,9 +38,9 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/dir.h>
|
||||
#include <isc/file.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/lex.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/once.h>
|
||||
@@ -226,7 +226,7 @@ dst__lib_shutdown(void) {
|
||||
}
|
||||
}
|
||||
|
||||
isc_mem_detach(&dst__mctx);
|
||||
isc_mem_destroy(&dst__mctx);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
+8
-8
@@ -43,7 +43,7 @@ struct dyndb_implementation {
|
||||
dns_dyndb_destroy_t *destroy_func;
|
||||
char *name;
|
||||
void *inst;
|
||||
ISC_LINK(dyndb_implementation_t) link;
|
||||
LINK(dyndb_implementation_t) link;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -52,7 +52,7 @@ struct dyndb_implementation {
|
||||
* These are stored here so they can be cleaned up on shutdown.
|
||||
* (The order in which they are stored is not important.)
|
||||
*/
|
||||
static ISC_LIST(dyndb_implementation_t) dyndb_implementations;
|
||||
static LIST(dyndb_implementation_t) dyndb_implementations;
|
||||
|
||||
/* Locks dyndb_implementations. */
|
||||
static isc_mutex_t dyndb_lock;
|
||||
@@ -60,7 +60,7 @@ static isc_mutex_t dyndb_lock;
|
||||
void
|
||||
dns__dyndb_initialize(void) {
|
||||
isc_mutex_init(&dyndb_lock);
|
||||
ISC_LIST_INIT(dyndb_implementations);
|
||||
INIT_LIST(dyndb_implementations);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -135,7 +135,7 @@ load_library(isc_mem_t *mctx, const char *filename, const char *instname,
|
||||
|
||||
isc_mem_attach(mctx, &imp->mctx);
|
||||
|
||||
ISC_LINK_INIT(imp, link);
|
||||
INIT_LINK(imp, link);
|
||||
|
||||
r = uv_dlopen(filename, &imp->handle);
|
||||
if (r != 0) {
|
||||
@@ -225,7 +225,7 @@ dns_dyndb_load(const char *libname, const char *name, const char *parameters,
|
||||
CHECK(implementation->register_func(mctx, name, parameters, file, line,
|
||||
dctx, &implementation->inst));
|
||||
|
||||
ISC_LIST_APPEND(dyndb_implementations, implementation, link);
|
||||
APPEND(dyndb_implementations, implementation, link);
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
@@ -245,10 +245,10 @@ dns_dyndb_cleanup(void) {
|
||||
dyndb_implementation_t *prev;
|
||||
|
||||
LOCK(&dyndb_lock);
|
||||
elem = ISC_LIST_TAIL(dyndb_implementations);
|
||||
elem = TAIL(dyndb_implementations);
|
||||
while (elem != NULL) {
|
||||
prev = ISC_LIST_PREV(elem, link);
|
||||
ISC_LIST_UNLINK(dyndb_implementations, elem, link);
|
||||
prev = PREV(elem, link);
|
||||
UNLINK(dyndb_implementations, elem, link);
|
||||
isc_log_write(DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB,
|
||||
ISC_LOG_INFO, "unloading DynDB instance '%s'",
|
||||
elem->name);
|
||||
|
||||
@@ -54,21 +54,16 @@
|
||||
isc_result_t
|
||||
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
|
||||
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
|
||||
dns_ttl_t maxttl, dns_rdataset_t *addedrdataset);
|
||||
isc_result_t
|
||||
dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
|
||||
dns_dbnode_t *node, dns_rdatatype_t covers,
|
||||
isc_stdtime_t now, dns_ttl_t minttl, dns_ttl_t maxttl,
|
||||
bool optout, dns_rdataset_t *addedrdataset);
|
||||
dns_ttl_t maxttl, bool optout, bool secure,
|
||||
dns_rdataset_t *addedrdataset);
|
||||
/*%<
|
||||
* Convert the authority data from 'message' into a negative cache
|
||||
* rdataset, and store it in 'cache' at 'node' with a TTL limited to
|
||||
* 'maxttl'.
|
||||
*
|
||||
* \li dns_ncache_add produces a negative cache entry with a trust of no
|
||||
* more than answer
|
||||
* \li dns_ncache_addoptout produces a negative cache entry which will have
|
||||
* a trust of secure if all the records that make up the entry are secure.
|
||||
* \li if 'secure' is true and all the records that make up the entry
|
||||
* are secure, then dns_ncache_add produces a negative cache entry
|
||||
* with trust level secure.
|
||||
*
|
||||
* The 'covers' argument is the RR type whose nonexistence we are caching,
|
||||
* or dns_rdatatype_any when caching a NXDOMAIN response.
|
||||
|
||||
@@ -399,7 +399,7 @@ dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code);
|
||||
*/
|
||||
|
||||
void
|
||||
dns_rcodestats_increment(dns_stats_t *stats, dns_rcode_t code);
|
||||
dns_rcodestats_increment(dns_stats_t *stats, dns_opcode_t code);
|
||||
/*%<
|
||||
* Increment the statistics counter for 'code'.
|
||||
*
|
||||
|
||||
@@ -124,7 +124,7 @@ typedef struct dns_nametree dns_nametree_t;
|
||||
typedef ISC_LIST(dns_name_t) dns_namelist_t;
|
||||
typedef struct dns_ntatable dns_ntatable_t;
|
||||
typedef struct dns_ntnode dns_ntnode_t;
|
||||
typedef enum dns_opcode dns_opcode_t;
|
||||
typedef uint16_t dns_opcode_t;
|
||||
typedef struct dns_order dns_order_t;
|
||||
typedef struct dns_peer dns_peer_t;
|
||||
typedef struct dns_peerlist dns_peerlist_t;
|
||||
@@ -308,18 +308,20 @@ enum {
|
||||
/*%
|
||||
* Opcodes.
|
||||
*/
|
||||
enum dns_opcode {
|
||||
enum {
|
||||
dns_opcode_query = 0,
|
||||
#define dns_opcode_query ((dns_opcode_t)dns_opcode_query)
|
||||
dns_opcode_iquery = 1,
|
||||
#define dns_opcode_iquery ((dns_opcode_t)dns_opcode_iquery)
|
||||
dns_opcode_status = 2,
|
||||
#define dns_opcode_status ((dns_opcode_t)dns_opcode_status)
|
||||
dns_opcode_notify = 4,
|
||||
#define dns_opcode_notify ((dns_opcode_t)dns_opcode_notify)
|
||||
dns_opcode_update = 5, /* dynamic update */
|
||||
#define dns_opcode_update ((dns_opcode_t)dns_opcode_update)
|
||||
dns_opcode_max = 6,
|
||||
dns__opcode_expand = UINT16_MAX,
|
||||
} __attribute__((__packed__));
|
||||
/* Absent attribute packed, the enum will be sized as an int */
|
||||
STATIC_ASSERT(sizeof(uint16_t) == sizeof(dns_opcode_t),
|
||||
"sizeof(dns_opecode)t) is not 16-bit");
|
||||
#define dns_opcode_max ((dns_opcode_t)dns_opcode_max)
|
||||
};
|
||||
|
||||
/*%
|
||||
* Trust levels. Must be kept in sync with trustnames[] in masterdump.c.
|
||||
|
||||
@@ -1539,19 +1539,14 @@ dns_zone_getsourceaddr(dns_zone_t *zone);
|
||||
* \li 'zone' has a non-empty primaries list.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *dest);
|
||||
isc_sockaddr_t
|
||||
dns_zone_getprimaryaddr(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Get the zone's current primary server into '*dest'.
|
||||
* Get the zone's current primary server.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'zone' to be a valid zone.
|
||||
* \li 'zone' has a non-empty primaries list.
|
||||
* \li 'dest' != NULL.
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS if the current primary server was found
|
||||
*\li #ISC_R_NOMORE if all the primaries were already iterated over
|
||||
*/
|
||||
|
||||
isc_time_t
|
||||
|
||||
+40
-71
@@ -189,19 +189,13 @@ dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first) {
|
||||
isc_stdtime_t zrrsig_present;
|
||||
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
|
||||
zrrsig_present = published + ttlsig +
|
||||
dns_kasp_zonepropagationdelay(kasp);
|
||||
dns_kasp_zonepropagationdelay(kasp) +
|
||||
dns_kasp_publishsafety(kasp);
|
||||
if (zrrsig_present > syncpublish) {
|
||||
syncpublish = zrrsig_present;
|
||||
}
|
||||
}
|
||||
dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncpublish);
|
||||
|
||||
uint32_t lifetime = 0;
|
||||
ret = dst_key_getnum(key, DST_NUM_LIFETIME, &lifetime);
|
||||
if (ret == ISC_R_SUCCESS && lifetime > 0) {
|
||||
dst_key_settime(key, DST_TIME_SYNCDELETE,
|
||||
(syncpublish + lifetime));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -249,17 +243,6 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
|
||||
pub = now;
|
||||
}
|
||||
|
||||
/*
|
||||
* To calculate phase out times ("Retired", "Removed", ...),
|
||||
* the key lifetime is required.
|
||||
*/
|
||||
uint32_t klifetime = 0;
|
||||
ret = dst_key_getnum(key->key, DST_NUM_LIFETIME, &klifetime);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
|
||||
klifetime = lifetime;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate prepublication time.
|
||||
*/
|
||||
@@ -289,16 +272,13 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
|
||||
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp,
|
||||
true);
|
||||
syncpub2 = pub + ttlsig +
|
||||
dns_kasp_publishsafety(kasp) +
|
||||
dns_kasp_zonepropagationdelay(kasp);
|
||||
}
|
||||
|
||||
syncpub = ISC_MAX(syncpub1, syncpub2);
|
||||
dst_key_settime(key->key, DST_TIME_SYNCPUBLISH,
|
||||
syncpub);
|
||||
if (klifetime > 0) {
|
||||
dst_key_settime(key->key, DST_TIME_SYNCDELETE,
|
||||
(syncpub + klifetime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,6 +291,13 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
|
||||
|
||||
ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
uint32_t klifetime = 0;
|
||||
|
||||
ret = dst_key_getnum(key->key, DST_NUM_LIFETIME, &klifetime);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
|
||||
klifetime = lifetime;
|
||||
}
|
||||
if (klifetime == 0) {
|
||||
/*
|
||||
* No inactive time and no lifetime,
|
||||
@@ -411,7 +398,7 @@ keymgr_key_update_lifetime(dns_dnsseckey_t *key, dns_kasp_t *kasp,
|
||||
/* Initialize lifetime. */
|
||||
if (r != ISC_R_SUCCESS) {
|
||||
dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
|
||||
l = lifetime - 1;
|
||||
return;
|
||||
}
|
||||
/* Skip keys that are still hidden or already retiring. */
|
||||
if (g != OMNIPRESENT) {
|
||||
@@ -433,7 +420,6 @@ keymgr_key_update_lifetime(dns_dnsseckey_t *key, dns_kasp_t *kasp,
|
||||
} else {
|
||||
dst_key_unsettime(key->key, DST_TIME_INACTIVE);
|
||||
dst_key_unsettime(key->key, DST_TIME_DELETE);
|
||||
dst_key_unsettime(key->key, DST_TIME_SYNCDELETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1300,7 +1286,6 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
|
||||
isc_result_t ret;
|
||||
isc_stdtime_t lastchange, dstime, nexttime = now;
|
||||
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
|
||||
uint32_t dsstate;
|
||||
|
||||
/*
|
||||
* No need to wait if we move things into an uncertain state.
|
||||
@@ -1370,12 +1355,15 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
|
||||
* records. This translates to:
|
||||
*
|
||||
* Dsgn + zone-propagation-delay + max-zone-ttl.
|
||||
*
|
||||
* We will also add the retire-safety interval.
|
||||
*/
|
||||
nexttime = lastchange + ttlsig +
|
||||
dns_kasp_zonepropagationdelay(kasp);
|
||||
dns_kasp_zonepropagationdelay(kasp) +
|
||||
dns_kasp_retiresafety(kasp);
|
||||
/*
|
||||
* Only add the sign delay Dsgn and retire-safety if
|
||||
* there is an actual predecessor or successor key.
|
||||
* Only add the sign delay Dsgn if there is an actual
|
||||
* predecessor or successor key.
|
||||
*/
|
||||
uint32_t tag;
|
||||
ret = dst_key_getnum(key->key, DST_NUM_PREDECESSOR,
|
||||
@@ -1385,8 +1373,7 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
|
||||
DST_NUM_SUCCESSOR, &tag);
|
||||
}
|
||||
if (ret == ISC_R_SUCCESS) {
|
||||
nexttime += dns_kasp_signdelay(kasp) +
|
||||
dns_kasp_retiresafety(kasp);
|
||||
nexttime += dns_kasp_signdelay(kasp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1412,36 +1399,35 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
|
||||
* This translates to:
|
||||
*
|
||||
* parent-propagation-delay + parent-ds-ttl.
|
||||
*
|
||||
* We will also add the retire-safety interval.
|
||||
*/
|
||||
case OMNIPRESENT:
|
||||
case HIDDEN:
|
||||
/* Make sure DS has been seen in/withdrawn from the
|
||||
* parent. */
|
||||
dsstate = next_state == HIDDEN ? DST_TIME_DSDELETE
|
||||
: DST_TIME_DSPUBLISH;
|
||||
ret = dst_key_gettime(key->key, dsstate, &dstime);
|
||||
/* Make sure DS has been seen in the parent. */
|
||||
ret = dst_key_gettime(key->key, DST_TIME_DSPUBLISH,
|
||||
&dstime);
|
||||
if (ret != ISC_R_SUCCESS || dstime > now) {
|
||||
/* Not yet, try again in an hour. */
|
||||
nexttime = now + 3600;
|
||||
} else {
|
||||
nexttime =
|
||||
dstime + dns_kasp_dsttl(kasp) +
|
||||
dns_kasp_parentpropagationdelay(kasp);
|
||||
/*
|
||||
* Only add the retire-safety if there is an
|
||||
* actual predecessor or successor key.
|
||||
*/
|
||||
uint32_t tag;
|
||||
ret = dst_key_getnum(key->key,
|
||||
DST_NUM_PREDECESSOR, &tag);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
ret = dst_key_getnum(key->key,
|
||||
DST_NUM_SUCCESSOR,
|
||||
&tag);
|
||||
}
|
||||
if (ret == ISC_R_SUCCESS) {
|
||||
nexttime += dns_kasp_retiresafety(kasp);
|
||||
}
|
||||
dns_kasp_parentpropagationdelay(kasp) +
|
||||
dns_kasp_retiresafety(kasp);
|
||||
}
|
||||
break;
|
||||
case HIDDEN:
|
||||
/* Make sure DS has been withdrawn from the parent. */
|
||||
ret = dst_key_gettime(key->key, DST_TIME_DSDELETE,
|
||||
&dstime);
|
||||
if (ret != ISC_R_SUCCESS || dstime > now) {
|
||||
/* Not yet, try again in an hour. */
|
||||
nexttime = now + 3600;
|
||||
} else {
|
||||
nexttime =
|
||||
dstime + dns_kasp_dsttl(kasp) +
|
||||
dns_kasp_parentpropagationdelay(kasp) +
|
||||
dns_kasp_retiresafety(kasp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1777,9 +1763,7 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
|
||||
if (prepub == 0 || prepub > now) {
|
||||
/* No need to start rollover now. */
|
||||
if (*nexttime == 0 || prepub < *nexttime) {
|
||||
if (prepub > 0) {
|
||||
*nexttime = prepub;
|
||||
}
|
||||
*nexttime = prepub;
|
||||
}
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
@@ -2038,20 +2022,6 @@ keymgr_purge_keyfile(dst_key_t *key, int type) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
dst_key_doublematch(dns_dnsseckey_t *key, dns_kasp_t *kasp) {
|
||||
int matches = 0;
|
||||
|
||||
for (dns_kasp_key_t *kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp));
|
||||
kkey != NULL; kkey = ISC_LIST_NEXT(kkey, link))
|
||||
{
|
||||
if (dns_kasp_key_match(kkey, key)) {
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
return matches > 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Examine 'keys' and match 'kasp' policy.
|
||||
*
|
||||
@@ -2191,7 +2161,6 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
|
||||
* matches the kasp policy.
|
||||
*/
|
||||
if (!dst_key_is_unused(dkey->key) &&
|
||||
!dst_key_doublematch(dkey, kasp) &&
|
||||
(dst_key_goal(dkey->key) ==
|
||||
OMNIPRESENT) &&
|
||||
!keymgr_dep(dkey->key, keyring,
|
||||
|
||||
+2
-25
@@ -50,12 +50,6 @@ atomic_getuint8(isc_buffer_t *b) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
|
||||
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
|
||||
dns_ttl_t maxttl, bool optout, bool secure,
|
||||
dns_rdataset_t *addedrdataset);
|
||||
|
||||
static isc_result_t
|
||||
copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
|
||||
isc_result_t result;
|
||||
@@ -107,25 +101,8 @@ copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
|
||||
isc_result_t
|
||||
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
|
||||
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
|
||||
dns_ttl_t maxttl, dns_rdataset_t *addedrdataset) {
|
||||
return addoptout(message, cache, node, covers, now, minttl, maxttl,
|
||||
false, false, addedrdataset);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
|
||||
dns_dbnode_t *node, dns_rdatatype_t covers,
|
||||
isc_stdtime_t now, dns_ttl_t minttl, dns_ttl_t maxttl,
|
||||
bool optout, dns_rdataset_t *addedrdataset) {
|
||||
return addoptout(message, cache, node, covers, now, minttl, maxttl,
|
||||
optout, true, addedrdataset);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
|
||||
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
|
||||
dns_ttl_t maxttl, bool optout, bool secure,
|
||||
dns_rdataset_t *addedrdataset) {
|
||||
dns_ttl_t maxttl, bool optout, bool secure,
|
||||
dns_rdataset_t *addedrdataset) {
|
||||
isc_result_t result;
|
||||
isc_buffer_t buffer;
|
||||
isc_region_t r;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/mutexblock.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/thread.h>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <openssl/param_build.h>
|
||||
#endif
|
||||
|
||||
#include <isc/fips.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/safe.h>
|
||||
@@ -706,7 +707,7 @@ opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
|
||||
if (!isc_crypto_fips_mode()) {
|
||||
if (!isc_fips_mode()) {
|
||||
ret = opensslecdsa_set_deterministic(
|
||||
pctx, dctx->key->key_alg);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
|
||||
+83
-106
@@ -202,10 +202,9 @@ struct qpcnode {
|
||||
uint8_t : 0;
|
||||
|
||||
/*%
|
||||
* Used for dead nodes cleaning. This linked list is used to mark nodes
|
||||
* which have no data any longer, but we cannot unlink at that exact
|
||||
* moment because we did not or could not obtain a write lock on the
|
||||
* tree.
|
||||
* Used for dead node cleaning. The deadnodes queue is used
|
||||
* for nodes that have no data any longer, but we can't unlink
|
||||
* yet because we don't have a tree lock.
|
||||
*/
|
||||
isc_queue_node_t deadlink;
|
||||
};
|
||||
@@ -216,9 +215,8 @@ struct qpcnode {
|
||||
* to reduce contention between threads.
|
||||
*/
|
||||
typedef struct qpcache_bucket {
|
||||
/*%
|
||||
* Temporary storage for stale cache nodes and dynamically
|
||||
* deleted nodes that await being cleaned up.
|
||||
/*
|
||||
* Temporary storage for cache nodes that need to be deleted.
|
||||
*/
|
||||
isc_queue_t deadnodes;
|
||||
|
||||
@@ -1999,23 +1997,78 @@ tree_exit:
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
seek_ns_headers(qpc_search_t *search, qpcnode_t *node, dns_dbnode_t **nodep,
|
||||
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
|
||||
dns_name_t *foundname, dns_name_t *dcname,
|
||||
isc_rwlocktype_t *tlocktype) {
|
||||
qpcache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
|
||||
isc_stdtime_t __now, dns_dbnode_t **nodep,
|
||||
dns_name_t *foundname, dns_name_t *dcname,
|
||||
dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
|
||||
qpcnode_t *node = NULL;
|
||||
isc_rwlock_t *nlock = NULL;
|
||||
isc_result_t result;
|
||||
dns_slabheader_t *header = NULL;
|
||||
dns_slabheader_t *header_prev = NULL, *header_next = NULL;
|
||||
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||
isc_rwlock_t *nlock = &search->qpdb->buckets[node->locknum].lock;
|
||||
dns_slabheader_t *found = NULL, *foundsig = NULL;
|
||||
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
|
||||
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||
bool dcnull = (dcname == NULL);
|
||||
qpc_search_t search = (qpc_search_t){
|
||||
.qpdb = (qpcache_t *)db,
|
||||
.options = options,
|
||||
.now = __now ? __now : isc_stdtime_now(),
|
||||
};
|
||||
|
||||
REQUIRE(VALID_QPDB((qpcache_t *)db));
|
||||
|
||||
if (dcnull) {
|
||||
dcname = foundname;
|
||||
}
|
||||
|
||||
TREE_RDLOCK(&search.qpdb->tree_lock, &tlocktype);
|
||||
|
||||
/*
|
||||
* Search down from the root of the tree.
|
||||
*/
|
||||
result = dns_qp_lookup(search.qpdb->tree, name, NULL, NULL,
|
||||
&search.chain, (void **)&node, NULL);
|
||||
if (result != ISC_R_NOTFOUND) {
|
||||
dns_name_copy(&node->name, dcname);
|
||||
}
|
||||
if ((options & DNS_DBFIND_NOEXACT) != 0 && result == ISC_R_SUCCESS) {
|
||||
int len = dns_qpchain_length(&search.chain);
|
||||
if (len >= 2) {
|
||||
node = NULL;
|
||||
dns_qpchain_node(&search.chain, len - 2, NULL,
|
||||
(void **)&node, NULL);
|
||||
search.chain.len = len - 1;
|
||||
result = DNS_R_PARTIALMATCH;
|
||||
} else {
|
||||
result = ISC_R_NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == DNS_R_PARTIALMATCH) {
|
||||
result = find_deepest_zonecut(&search, node, nodep, foundname,
|
||||
rdataset,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
goto tree_exit;
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
goto tree_exit;
|
||||
} else if (!dcnull) {
|
||||
dns_name_copy(dcname, foundname);
|
||||
}
|
||||
|
||||
/*
|
||||
* We now go looking for an NS rdataset at the node.
|
||||
*/
|
||||
|
||||
nlock = &search.qpdb->buckets[node->locknum].lock;
|
||||
NODE_RDLOCK(nlock, &nlocktype);
|
||||
|
||||
for (header = node->data; header != NULL; header = header_next) {
|
||||
header_next = header->next;
|
||||
bool ns = (header->type == dns_rdatatype_ns ||
|
||||
header->type == DNS_SIGTYPE(dns_rdatatype_ns));
|
||||
if (check_stale_header(node, header, &nlocktype, nlock, search,
|
||||
if (check_stale_header(node, header, &nlocktype, nlock, &search,
|
||||
&header_prev))
|
||||
{
|
||||
if (ns) {
|
||||
@@ -2038,108 +2091,32 @@ seek_ns_headers(qpc_search_t *search, qpcnode_t *node, dns_dbnode_t **nodep,
|
||||
}
|
||||
|
||||
if (found == NULL) {
|
||||
isc_result_t result;
|
||||
|
||||
/*
|
||||
* No active NS records found. Call find_deepest_zonecut()
|
||||
* to look for them in nodes above this one.
|
||||
*/
|
||||
NODE_UNLOCK(nlock, &nlocktype);
|
||||
result = find_deepest_zonecut(search, node, nodep, foundname,
|
||||
rdataset,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
if (dcname != NULL) {
|
||||
dns_name_copy(foundname, dcname);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (nodep != NULL) {
|
||||
qpcnode_acquire(search->qpdb, node, nlocktype,
|
||||
*tlocktype DNS__DB_FLARG_PASS);
|
||||
*nodep = (dns_dbnode_t *)node;
|
||||
}
|
||||
|
||||
bindrdatasets(search->qpdb, node, found, foundsig, search->now,
|
||||
nlocktype, *tlocktype, rdataset,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
maybe_update_headers(search->qpdb, found, foundsig, nlock, &nlocktype,
|
||||
search->now);
|
||||
|
||||
NODE_UNLOCK(nlock, &nlocktype);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
qpcache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
|
||||
isc_stdtime_t __now, dns_dbnode_t **nodep,
|
||||
dns_name_t *foundname, dns_name_t *dcname,
|
||||
dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
|
||||
qpcnode_t *node = NULL;
|
||||
isc_result_t result;
|
||||
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
|
||||
qpc_search_t search = (qpc_search_t){
|
||||
.qpdb = (qpcache_t *)db,
|
||||
.options = options,
|
||||
.now = __now ? __now : isc_stdtime_now(),
|
||||
};
|
||||
unsigned int len = 0;
|
||||
|
||||
REQUIRE(VALID_QPDB((qpcache_t *)db));
|
||||
|
||||
TREE_RDLOCK(&search.qpdb->tree_lock, &tlocktype);
|
||||
|
||||
/*
|
||||
* Search down from the root of the tree.
|
||||
*/
|
||||
result = dns_qp_lookup(search.qpdb->tree, name, NULL, NULL,
|
||||
&search.chain, (void **)&node, NULL);
|
||||
|
||||
switch (result) {
|
||||
case ISC_R_SUCCESS:
|
||||
if ((options & DNS_DBFIND_NOEXACT) == 0) {
|
||||
if (dcname != NULL) {
|
||||
dns_name_copy(&node->name, dcname);
|
||||
}
|
||||
dns_name_copy(&node->name, foundname);
|
||||
result = seek_ns_headers(&search, node, nodep, rdataset,
|
||||
sigrdataset, foundname, dcname,
|
||||
&tlocktype);
|
||||
break;
|
||||
}
|
||||
|
||||
len = dns_qpchain_length(&search.chain);
|
||||
if (len < 2) {
|
||||
result = ISC_R_NOTFOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
FALLTHROUGH;
|
||||
case DNS_R_PARTIALMATCH:
|
||||
if (dcname != NULL) {
|
||||
dns_name_copy(&node->name, dcname);
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
/* Fell through from the previous case */
|
||||
INSIST(len >= 2);
|
||||
|
||||
node = NULL;
|
||||
dns_qpchain_node(&search.chain, len - 2, NULL,
|
||||
(void **)&node, NULL);
|
||||
search.chain.len = len - 1;
|
||||
}
|
||||
|
||||
result = find_deepest_zonecut(&search, node, nodep, foundname,
|
||||
rdataset,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
dns_name_copy(foundname, dcname);
|
||||
goto tree_exit;
|
||||
}
|
||||
|
||||
if (nodep != NULL) {
|
||||
qpcnode_acquire(search.qpdb, node, nlocktype,
|
||||
tlocktype DNS__DB_FLARG_PASS);
|
||||
*nodep = (dns_dbnode_t *)node;
|
||||
}
|
||||
|
||||
bindrdatasets(search.qpdb, node, found, foundsig, search.now, nlocktype,
|
||||
tlocktype, rdataset, sigrdataset DNS__DB_FLARG_PASS);
|
||||
maybe_update_headers(search.qpdb, found, foundsig, nlock, &nlocktype,
|
||||
search.now);
|
||||
|
||||
NODE_UNLOCK(nlock, &nlocktype);
|
||||
|
||||
tree_exit:
|
||||
TREE_UNLOCK(&search.qpdb->tree_lock, &tlocktype);
|
||||
|
||||
INSIST(!search.need_cleanup);
|
||||
|
||||
+112
-30
@@ -544,7 +544,7 @@ qpzone_destroy(qpzonedb_t *qpdb) {
|
||||
isc_refcount_decrementz(&qpdb->current_version->references);
|
||||
|
||||
isc_refcount_destroy(&qpdb->current_version->references);
|
||||
ISC_LIST_UNLINK(qpdb->open_versions, qpdb->current_version, link);
|
||||
UNLINK(qpdb->open_versions, qpdb->current_version, link);
|
||||
cds_wfs_destroy(&qpdb->current_version->glue_stack);
|
||||
isc_rwlock_destroy(&qpdb->current_version->rwlock);
|
||||
isc_mem_put(qpdb->common.mctx, qpdb->current_version,
|
||||
@@ -723,7 +723,7 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
|
||||
* Keep the current version in the open list so that list operation
|
||||
* won't happen in normal lookup operations.
|
||||
*/
|
||||
ISC_LIST_PREPEND(qpdb->open_versions, qpdb->current_version, link);
|
||||
PREPEND(qpdb->open_versions, qpdb->current_version, link);
|
||||
|
||||
qpdb->common.magic = DNS_DB_MAGIC;
|
||||
qpdb->common.impmagic = QPZONE_DB_MAGIC;
|
||||
@@ -875,6 +875,7 @@ clean_zone_node(qpznode_t *node, uint32_t least_serial) {
|
||||
}
|
||||
top_prev = current;
|
||||
}
|
||||
|
||||
if (!still_dirty) {
|
||||
node->dirty = false;
|
||||
}
|
||||
@@ -1124,13 +1125,13 @@ cleanup_nondirty(qpz_version_t *version, qpz_changedlist_t *cleanup_list) {
|
||||
*
|
||||
* The caller must be holding the database lock.
|
||||
*/
|
||||
for (changed = ISC_LIST_HEAD(version->changed_list); changed != NULL;
|
||||
for (changed = HEAD(version->changed_list); changed != NULL;
|
||||
changed = next_changed)
|
||||
{
|
||||
next_changed = ISC_LIST_NEXT(changed, link);
|
||||
next_changed = NEXT(changed, link);
|
||||
if (!changed->dirty) {
|
||||
ISC_LIST_UNLINK(version->changed_list, changed, link);
|
||||
ISC_LIST_APPEND(*cleanup_list, changed, link);
|
||||
UNLINK(version->changed_list, changed, link);
|
||||
APPEND(*cleanup_list, changed, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1377,13 +1378,12 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
(void)isc_refcount_current(
|
||||
&cur_version->references);
|
||||
if (cur_version->serial == qpdb->least_serial) {
|
||||
INSIST(ISC_LIST_EMPTY(
|
||||
INSIST(EMPTY(
|
||||
cur_version->changed_list));
|
||||
}
|
||||
ISC_LIST_UNLINK(qpdb->open_versions,
|
||||
cur_version, link);
|
||||
UNLINK(qpdb->open_versions, cur_version, link);
|
||||
}
|
||||
if (ISC_LIST_EMPTY(qpdb->open_versions)) {
|
||||
if (EMPTY(qpdb->open_versions)) {
|
||||
/*
|
||||
* We're going to become the least open
|
||||
* version.
|
||||
@@ -1413,9 +1413,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
*/
|
||||
if (cur_ref == 1) {
|
||||
cleanup_version = cur_version;
|
||||
ISC_LIST_APPENDLIST(
|
||||
version->changed_list,
|
||||
cleanup_version->changed_list, link);
|
||||
APPENDLIST(version->changed_list,
|
||||
cleanup_version->changed_list, link);
|
||||
}
|
||||
/*
|
||||
* Become the current version.
|
||||
@@ -1434,8 +1433,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
*/
|
||||
INSIST(isc_refcount_increment0(&version->references) ==
|
||||
0);
|
||||
ISC_LIST_PREPEND(qpdb->open_versions,
|
||||
qpdb->current_version, link);
|
||||
PREPEND(qpdb->open_versions, qpdb->current_version,
|
||||
link);
|
||||
resigned_list = version->resigned_list;
|
||||
ISC_LIST_INIT(version->resigned_list);
|
||||
} else {
|
||||
@@ -1462,7 +1461,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
* Find the version with the least serial
|
||||
* number greater than ours.
|
||||
*/
|
||||
least_greater = ISC_LIST_PREV(version, link);
|
||||
least_greater = PREV(version, link);
|
||||
if (least_greater == NULL) {
|
||||
least_greater = qpdb->current_version;
|
||||
}
|
||||
@@ -1483,21 +1482,20 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
* Add any unexecuted cleanups to
|
||||
* those of the least greater version.
|
||||
*/
|
||||
ISC_LIST_APPENDLIST(least_greater->changed_list,
|
||||
version->changed_list,
|
||||
link);
|
||||
APPENDLIST(least_greater->changed_list,
|
||||
version->changed_list, link);
|
||||
}
|
||||
} else if (version->serial == qpdb->least_serial) {
|
||||
INSIST(ISC_LIST_EMPTY(version->changed_list));
|
||||
INSIST(EMPTY(version->changed_list));
|
||||
}
|
||||
ISC_LIST_UNLINK(qpdb->open_versions, version, link);
|
||||
UNLINK(qpdb->open_versions, version, link);
|
||||
}
|
||||
least_serial = qpdb->least_serial;
|
||||
RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
|
||||
|
||||
if (cleanup_version != NULL) {
|
||||
isc_refcount_destroy(&cleanup_version->references);
|
||||
INSIST(ISC_LIST_EMPTY(cleanup_version->changed_list));
|
||||
INSIST(EMPTY(cleanup_version->changed_list));
|
||||
cleanup_gluelists(&cleanup_version->glue_stack);
|
||||
cds_wfs_destroy(&cleanup_version->glue_stack);
|
||||
isc_rwlock_destroy(&cleanup_version->rwlock);
|
||||
@@ -1508,8 +1506,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
/*
|
||||
* Commit/rollback re-signed headers.
|
||||
*/
|
||||
for (header = ISC_LIST_HEAD(resigned_list); header != NULL;
|
||||
header = ISC_LIST_HEAD(resigned_list))
|
||||
for (header = HEAD(resigned_list); header != NULL;
|
||||
header = HEAD(resigned_list))
|
||||
{
|
||||
isc_rwlock_t *nlock = NULL;
|
||||
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||
@@ -1526,18 +1524,16 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
NODE_UNLOCK(nlock, &nlocktype);
|
||||
}
|
||||
|
||||
if (ISC_LIST_EMPTY(cleanup_list)) {
|
||||
*versionp = NULL;
|
||||
return;
|
||||
}
|
||||
dns_qp_t *tree = NULL, *nsec = NULL, *nsec3 = NULL;
|
||||
bool need_tree = false, need_nsec = false, need_nsec3 = false;
|
||||
|
||||
for (changed = ISC_LIST_HEAD(cleanup_list); changed != NULL;
|
||||
for (changed = HEAD(cleanup_list); changed != NULL;
|
||||
changed = next_changed)
|
||||
{
|
||||
isc_rwlock_t *nlock = NULL;
|
||||
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||
|
||||
next_changed = ISC_LIST_NEXT(changed, link);
|
||||
next_changed = NEXT(changed, link);
|
||||
node = changed->node;
|
||||
nlock = &qpdb->buckets[node->locknum].lock;
|
||||
|
||||
@@ -1545,14 +1541,100 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
if (rollback) {
|
||||
rollback_node(node, serial);
|
||||
}
|
||||
|
||||
qpznode_ref(node);
|
||||
qpznode_release(qpdb, node, least_serial,
|
||||
&nlocktype DNS__DB_FILELINE);
|
||||
|
||||
/* If the node is now empty, we can delete it. */
|
||||
if (commit && node->data == NULL) {
|
||||
switch ((int)node->nsec) {
|
||||
case DNS_DB_NSEC_HAS_NSEC:
|
||||
/*
|
||||
* Delete the matching node from the NSEC tree
|
||||
* first, then fall through to the main tree.
|
||||
*/
|
||||
if (nsec == NULL) {
|
||||
need_nsec = true;
|
||||
next_changed = changed;
|
||||
} else {
|
||||
dns_qp_deletename(nsec, &node->name,
|
||||
NULL, NULL);
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case DNS_DB_NSEC_NORMAL:
|
||||
if (tree == NULL) {
|
||||
need_tree = true;
|
||||
next_changed = changed;
|
||||
} else {
|
||||
dns_qp_deletename(tree, &node->name,
|
||||
NULL, NULL);
|
||||
}
|
||||
break;
|
||||
case DNS_DB_NSEC_NSEC:
|
||||
if (nsec == NULL) {
|
||||
need_nsec = true;
|
||||
next_changed = changed;
|
||||
} else {
|
||||
dns_qp_deletename(nsec, &node->name,
|
||||
NULL, NULL);
|
||||
}
|
||||
break;
|
||||
case DNS_DB_NSEC_NSEC3:
|
||||
if (nsec3 == NULL) {
|
||||
need_nsec3 = true;
|
||||
next_changed = changed;
|
||||
} else {
|
||||
dns_qp_deletename(nsec3, &node->name,
|
||||
NULL, NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
qpznode_detach(&node);
|
||||
|
||||
NODE_UNLOCK(nlock, &nlocktype);
|
||||
|
||||
if (next_changed == changed) {
|
||||
/*
|
||||
* We found a node to delete but didn't have a
|
||||
* QP writer open, so we open one now, then go
|
||||
* back to delete the node. If there's a next
|
||||
* time, we'll already have the writer open,
|
||||
* so we won't need this extra step.
|
||||
*/
|
||||
if (need_tree && tree == NULL) {
|
||||
dns_qpmulti_write(qpdb->tree, &tree);
|
||||
}
|
||||
if (need_nsec && nsec == NULL) {
|
||||
dns_qpmulti_write(qpdb->nsec, &nsec);
|
||||
}
|
||||
if (need_nsec3 && nsec3 == NULL) {
|
||||
dns_qpmulti_write(qpdb->nsec3, &nsec3);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
isc_mem_put(qpdb->common.mctx, changed, sizeof(*changed));
|
||||
}
|
||||
|
||||
if (tree != NULL) {
|
||||
dns_qp_compact(tree, DNS_QPGC_MAYBE);
|
||||
dns_qpmulti_commit(qpdb->tree, &tree);
|
||||
}
|
||||
if (nsec != NULL) {
|
||||
dns_qp_compact(nsec, DNS_QPGC_MAYBE);
|
||||
dns_qpmulti_commit(qpdb->nsec, &nsec);
|
||||
}
|
||||
if (nsec3 != NULL) {
|
||||
dns_qp_compact(nsec3, DNS_QPGC_MAYBE);
|
||||
dns_qpmulti_commit(qpdb->nsec3, &nsec3);
|
||||
}
|
||||
|
||||
*versionp = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -387,9 +387,6 @@ static int
|
||||
compare_rrsig(ARGS_COMPARE) {
|
||||
isc_region_t r1;
|
||||
isc_region_t r2;
|
||||
dns_name_t name1;
|
||||
dns_name_t name2;
|
||||
int order;
|
||||
|
||||
REQUIRE(rdata1->type == rdata2->type);
|
||||
REQUIRE(rdata1->rdclass == rdata2->rdclass);
|
||||
@@ -399,32 +396,6 @@ compare_rrsig(ARGS_COMPARE) {
|
||||
|
||||
dns_rdata_toregion(rdata1, &r1);
|
||||
dns_rdata_toregion(rdata2, &r2);
|
||||
|
||||
INSIST(r1.length > 18);
|
||||
INSIST(r2.length > 18);
|
||||
r1.length = 18;
|
||||
r2.length = 18;
|
||||
order = isc_region_compare(&r1, &r2);
|
||||
if (order != 0) {
|
||||
return order;
|
||||
}
|
||||
|
||||
dns_name_init(&name1);
|
||||
dns_name_init(&name2);
|
||||
dns_rdata_toregion(rdata1, &r1);
|
||||
dns_rdata_toregion(rdata2, &r2);
|
||||
isc_region_consume(&r1, 18);
|
||||
isc_region_consume(&r2, 18);
|
||||
dns_name_fromregion(&name1, &r1);
|
||||
dns_name_fromregion(&name2, &r2);
|
||||
order = dns_name_rdatacompare(&name1, &name2);
|
||||
if (order != 0) {
|
||||
return order;
|
||||
}
|
||||
|
||||
isc_region_consume(&r1, name_length(&name1));
|
||||
isc_region_consume(&r2, name_length(&name2));
|
||||
|
||||
return isc_region_compare(&r1, &r2);
|
||||
}
|
||||
|
||||
@@ -592,32 +563,13 @@ additionaldata_rrsig(ARGS_ADDLDATA) {
|
||||
|
||||
static isc_result_t
|
||||
digest_rrsig(ARGS_DIGEST) {
|
||||
isc_region_t r1, r2;
|
||||
dns_name_t name;
|
||||
|
||||
REQUIRE(rdata->type == dns_rdatatype_rrsig);
|
||||
|
||||
dns_rdata_toregion(rdata, &r1);
|
||||
r2 = r1;
|
||||
UNUSED(rdata);
|
||||
UNUSED(digest);
|
||||
UNUSED(arg);
|
||||
|
||||
/*
|
||||
* Type covered (2) + Algorithm (1) +
|
||||
* Labels (1) + Original TTL (4) +
|
||||
* Expire time (4) + Time signed (4) +
|
||||
* Key ID (2).
|
||||
*/
|
||||
isc_region_consume(&r2, 18);
|
||||
r1.length = 18;
|
||||
RETERR((digest)(arg, &r1));
|
||||
|
||||
/* Signer */
|
||||
dns_name_init(&name);
|
||||
dns_name_fromregion(&name, &r2);
|
||||
RETERR(dns_name_digest(&name, digest, arg));
|
||||
isc_region_consume(&r2, name_length(&name));
|
||||
|
||||
/* Signature */
|
||||
return (digest)(arg, &r2);
|
||||
return ISC_R_NOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
static dns_rdatatype_t
|
||||
@@ -658,7 +610,47 @@ checknames_rrsig(ARGS_CHECKNAMES) {
|
||||
|
||||
static int
|
||||
casecompare_rrsig(ARGS_COMPARE) {
|
||||
return compare_rrsig(rdata1, rdata2);
|
||||
isc_region_t r1;
|
||||
isc_region_t r2;
|
||||
dns_name_t name1;
|
||||
dns_name_t name2;
|
||||
int order;
|
||||
|
||||
REQUIRE(rdata1->type == rdata2->type);
|
||||
REQUIRE(rdata1->rdclass == rdata2->rdclass);
|
||||
REQUIRE(rdata1->type == dns_rdatatype_rrsig);
|
||||
REQUIRE(rdata1->length != 0);
|
||||
REQUIRE(rdata2->length != 0);
|
||||
|
||||
dns_rdata_toregion(rdata1, &r1);
|
||||
dns_rdata_toregion(rdata2, &r2);
|
||||
|
||||
INSIST(r1.length > 18);
|
||||
INSIST(r2.length > 18);
|
||||
r1.length = 18;
|
||||
r2.length = 18;
|
||||
order = isc_region_compare(&r1, &r2);
|
||||
if (order != 0) {
|
||||
return order;
|
||||
}
|
||||
|
||||
dns_name_init(&name1);
|
||||
dns_name_init(&name2);
|
||||
dns_rdata_toregion(rdata1, &r1);
|
||||
dns_rdata_toregion(rdata2, &r2);
|
||||
isc_region_consume(&r1, 18);
|
||||
isc_region_consume(&r2, 18);
|
||||
dns_name_fromregion(&name1, &r1);
|
||||
dns_name_fromregion(&name2, &r2);
|
||||
order = dns_name_rdatacompare(&name1, &name2);
|
||||
if (order != 0) {
|
||||
return order;
|
||||
}
|
||||
|
||||
isc_region_consume(&r1, name_length(&name1));
|
||||
isc_region_consume(&r2, name_length(&name2));
|
||||
|
||||
return isc_region_compare(&r1, &r2);
|
||||
}
|
||||
|
||||
#endif /* RDATA_GENERIC_RRSIG_46_C */
|
||||
|
||||
@@ -556,32 +556,13 @@ additionaldata_sig(ARGS_ADDLDATA) {
|
||||
|
||||
static isc_result_t
|
||||
digest_sig(ARGS_DIGEST) {
|
||||
isc_region_t r1, r2;
|
||||
dns_name_t name;
|
||||
|
||||
REQUIRE(rdata->type == dns_rdatatype_sig);
|
||||
|
||||
dns_rdata_toregion(rdata, &r1);
|
||||
r2 = r1;
|
||||
UNUSED(rdata);
|
||||
UNUSED(digest);
|
||||
UNUSED(arg);
|
||||
|
||||
/*
|
||||
* Type covered (2) + Algorithm (1) +
|
||||
* Labels (1) + Original TTL (4) +
|
||||
* Expire time (4) + Time signed (4) +
|
||||
* Key ID (2).
|
||||
*/
|
||||
isc_region_consume(&r2, 18);
|
||||
r1.length = 18;
|
||||
RETERR((digest)(arg, &r1));
|
||||
|
||||
/* Signer */
|
||||
dns_name_init(&name);
|
||||
dns_name_fromregion(&name, &r2);
|
||||
RETERR(dns_name_digest(&name, digest, arg));
|
||||
isc_region_consume(&r2, name_length(&name));
|
||||
|
||||
/* Signature */
|
||||
return (digest)(arg, &r2);
|
||||
return ISC_R_NOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
static dns_rdatatype_t
|
||||
|
||||
+9
-24
@@ -5263,7 +5263,7 @@ validated(void *arg) {
|
||||
* is returned, and that the rdatasets are bound.
|
||||
*/
|
||||
if (val->result == ISC_R_SUCCESS && !negative &&
|
||||
val->rdataset != NULL && CHAINING(val->rdataset))
|
||||
CHAINING(val->rdataset))
|
||||
{
|
||||
if (val->rdataset->type == dns_rdatatype_cname) {
|
||||
eresult = DNS_R_CNAME;
|
||||
@@ -5357,18 +5357,14 @@ validated(void *arg) {
|
||||
nextval = ISC_LIST_HEAD(fctx->validators);
|
||||
if (nextval != NULL) {
|
||||
dns_validator_send(nextval);
|
||||
goto cleanup_fetchctx;
|
||||
} else if (sentresponse) {
|
||||
done = true;
|
||||
goto cleanup_fetchctx;
|
||||
} else if (result == DNS_R_BROKENCHAIN) {
|
||||
done = true;
|
||||
goto cleanup_fetchctx;
|
||||
} else {
|
||||
fctx_try(fctx, true);
|
||||
goto cleanup_fetchctx;
|
||||
}
|
||||
UNREACHABLE();
|
||||
goto cleanup_fetchctx;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
@@ -5663,9 +5659,7 @@ answer_response:
|
||||
if (NEGATIVE(hresp->rdataset)) {
|
||||
INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
|
||||
eresult == DNS_R_NCACHENXRRSET);
|
||||
} else if (eresult == ISC_R_SUCCESS &&
|
||||
hresp->rdataset->type != fctx->type)
|
||||
{
|
||||
} else if (eresult == ISC_R_SUCCESS) {
|
||||
switch (hresp->rdataset->type) {
|
||||
case dns_rdatatype_cname:
|
||||
eresult = DNS_R_CNAME;
|
||||
@@ -6328,12 +6322,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
||||
*/
|
||||
if (dns_rdataset_isassociated(resp->rdataset)) {
|
||||
if (NEGATIVE(resp->rdataset)) {
|
||||
INSIST(eresult ==
|
||||
DNS_R_NCACHENXDOMAIN ||
|
||||
INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
|
||||
eresult == DNS_R_NCACHENXRRSET);
|
||||
} else if (eresult == ISC_R_SUCCESS &&
|
||||
resp->rdataset->type != fctx->type)
|
||||
{
|
||||
} else if (eresult == ISC_R_SUCCESS) {
|
||||
switch (resp->rdataset->type) {
|
||||
case dns_rdatatype_cname:
|
||||
eresult = DNS_R_CNAME;
|
||||
@@ -6409,8 +6400,7 @@ cache_message(fetchctx_t *fctx, dns_message_t *message,
|
||||
}
|
||||
|
||||
/*
|
||||
* Do what dns_ncache_addoptout() does, and then compute an appropriate
|
||||
* eresult.
|
||||
* Call dns_ncache_add() and then compute an appropriate eresult.
|
||||
*/
|
||||
static isc_result_t
|
||||
ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
|
||||
@@ -6424,14 +6414,9 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
|
||||
dns_rdataset_init(&rdataset);
|
||||
ardataset = &rdataset;
|
||||
}
|
||||
if (secure) {
|
||||
result = dns_ncache_addoptout(message, cache, node, covers, now,
|
||||
minttl, maxttl, optout,
|
||||
ardataset);
|
||||
} else {
|
||||
result = dns_ncache_add(message, cache, node, covers, now,
|
||||
minttl, maxttl, ardataset);
|
||||
}
|
||||
|
||||
result = dns_ncache_add(message, cache, node, covers, now, optout,
|
||||
secure, minttl, maxttl, ardataset);
|
||||
if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
|
||||
/*
|
||||
* If the cache now contains a negative entry and we
|
||||
|
||||
+6
-12
@@ -18385,22 +18385,18 @@ dns_zone_getsourceaddr(dns_zone_t *zone) {
|
||||
return sourceaddr;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *dest) {
|
||||
isc_result_t result = ISC_R_NOMORE;
|
||||
isc_sockaddr_t
|
||||
dns_zone_getprimaryaddr(dns_zone_t *zone) {
|
||||
isc_sockaddr_t curraddr;
|
||||
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(dest != NULL);
|
||||
|
||||
LOCK_ZONE(zone);
|
||||
INSIST(dns_remote_count(&zone->primaries) > 0);
|
||||
if (!dns_remote_done(&zone->primaries)) {
|
||||
*dest = dns_remote_curraddr(&zone->primaries);
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
curraddr = dns_remote_curraddr(&zone->primaries);
|
||||
UNLOCK_ZONE(zone);
|
||||
|
||||
return result;
|
||||
return curraddr;
|
||||
}
|
||||
|
||||
isc_time_t
|
||||
@@ -18461,9 +18457,7 @@ get_request_transport_type(dns_zone_t *zone) {
|
||||
: DNS_TRANSPORT_UDP;
|
||||
|
||||
/* Check if the peer is forced to always use TCP. */
|
||||
if (transport_type != DNS_TRANSPORT_TCP &&
|
||||
!dns_remote_done(&zone->primaries))
|
||||
{
|
||||
if (transport_type != DNS_TRANSPORT_TCP) {
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t primaryaddr;
|
||||
isc_netaddr_t primaryip;
|
||||
|
||||
@@ -15,6 +15,7 @@ libisc_la_HEADERS = \
|
||||
include/isc/base64.h \
|
||||
include/isc/buffer.h \
|
||||
include/isc/commandline.h \
|
||||
include/isc/condition.h \
|
||||
include/isc/counter.h \
|
||||
include/isc/crypto.h \
|
||||
include/isc/dir.h \
|
||||
@@ -24,6 +25,7 @@ libisc_la_HEADERS = \
|
||||
include/isc/errno.h \
|
||||
include/isc/error.h \
|
||||
include/isc/file.h \
|
||||
include/isc/fips.h \
|
||||
include/isc/formatcheck.h \
|
||||
include/isc/fuzz.h \
|
||||
include/isc/getaddresses.h \
|
||||
@@ -50,6 +52,7 @@ libisc_la_HEADERS = \
|
||||
include/isc/mem.h \
|
||||
include/isc/meminfo.h \
|
||||
include/isc/mutex.h \
|
||||
include/isc/mutexblock.h \
|
||||
include/isc/net.h \
|
||||
include/isc/netaddr.h \
|
||||
include/isc/netmgr.h \
|
||||
@@ -120,6 +123,7 @@ libisc_la_SOURCES = \
|
||||
base32.c \
|
||||
base64.c \
|
||||
commandline.c \
|
||||
condition.c \
|
||||
counter.c \
|
||||
crypto.c \
|
||||
dir.c \
|
||||
@@ -129,6 +133,7 @@ libisc_la_SOURCES = \
|
||||
errno2result.h \
|
||||
error.c \
|
||||
file.c \
|
||||
fips.c \
|
||||
getaddresses.c \
|
||||
hash.c \
|
||||
hashmap.c \
|
||||
@@ -156,6 +161,7 @@ libisc_la_SOURCES = \
|
||||
meminfo.c \
|
||||
mutex.c \
|
||||
mutex_p.h \
|
||||
mutexblock.c \
|
||||
net.c \
|
||||
netaddr.c \
|
||||
netscope.c \
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <isc/async.h>
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/barrier.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/job.h>
|
||||
#include <isc/loop.h>
|
||||
#include <isc/magic.h>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <isc/condition.h>
|
||||
#include <isc/strerr.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/time.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
isc_result_t
|
||||
isc__condition_waituntil(pthread_cond_t *c, pthread_mutex_t *m, isc_time_t *t) {
|
||||
int presult;
|
||||
isc_result_t result;
|
||||
struct timespec ts;
|
||||
|
||||
REQUIRE(c != NULL && m != NULL && t != NULL);
|
||||
|
||||
/*
|
||||
* POSIX defines a timespec's tv_sec as time_t.
|
||||
*/
|
||||
result = isc_time_secondsastimet(t, &ts.tv_sec);
|
||||
|
||||
/*
|
||||
* If we have a range error ts.tv_sec is most probably a signed
|
||||
* 32 bit value. Set ts.tv_sec to INT_MAX. This is a kludge.
|
||||
*/
|
||||
if (result == ISC_R_RANGE) {
|
||||
ts.tv_sec = INT_MAX;
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* POSIX defines a timespec's tv_nsec as long. isc_time_nanoseconds
|
||||
* ensures its return value is < 1 billion, which will fit in a long.
|
||||
*/
|
||||
ts.tv_nsec = (long)isc_time_nanoseconds(t);
|
||||
|
||||
do {
|
||||
presult = pthread_cond_timedwait(c, m, &ts);
|
||||
if (presult == 0) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
if (presult == ETIMEDOUT) {
|
||||
return ISC_R_TIMEDOUT;
|
||||
}
|
||||
} while (presult == EINTR);
|
||||
|
||||
UNEXPECTED_SYSERROR(presult, "pthread_cond_timedwait()");
|
||||
return ISC_R_UNEXPECTED;
|
||||
}
|
||||
+34
-139
@@ -11,17 +11,13 @@
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/provider.h>
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
|
||||
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/tls.h>
|
||||
@@ -29,10 +25,6 @@
|
||||
|
||||
static isc_mem_t *isc__crypto_mctx = NULL;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
static OSSL_PROVIDER *base = NULL, *fips = NULL;
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
|
||||
|
||||
const EVP_MD *isc__crypto_md5 = NULL;
|
||||
const EVP_MD *isc__crypto_sha1 = NULL;
|
||||
const EVP_MD *isc__crypto_sha224 = NULL;
|
||||
@@ -57,6 +49,7 @@ const EVP_MD *isc__crypto_sha512 = NULL;
|
||||
isc__crypto_##alg = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
|
||||
#define md_register_algorithm(alg, algname) \
|
||||
{ \
|
||||
@@ -68,34 +61,6 @@ const EVP_MD *isc__crypto_sha512 = NULL;
|
||||
#define md_unregister_algorithm(alg)
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
|
||||
|
||||
static isc_result_t
|
||||
register_algorithms(void) {
|
||||
if (!isc_crypto_fips_mode()) {
|
||||
md_register_algorithm(md5, "MD5");
|
||||
}
|
||||
|
||||
md_register_algorithm(sha1, "SHA1");
|
||||
md_register_algorithm(sha224, "SHA224");
|
||||
md_register_algorithm(sha256, "SHA256");
|
||||
md_register_algorithm(sha384, "SHA384");
|
||||
md_register_algorithm(sha512, "SHA512");
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
unregister_algorithms(void) {
|
||||
md_unregister_algorithm(sha512);
|
||||
md_unregister_algorithm(sha384);
|
||||
md_unregister_algorithm(sha256);
|
||||
md_unregister_algorithm(sha224);
|
||||
md_unregister_algorithm(sha1);
|
||||
md_unregister_algorithm(md5);
|
||||
}
|
||||
|
||||
#undef md_unregister_algorithm
|
||||
#undef md_register_algorithm
|
||||
|
||||
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
/*
|
||||
* This was crippled with LibreSSL, so just skip it:
|
||||
@@ -114,14 +79,14 @@ unregister_algorithms(void) {
|
||||
|
||||
static void *
|
||||
isc__crypto_malloc_ex(size_t size, const char *file, int line) {
|
||||
return isc__mem_allocate(isc__crypto_mctx, size, 0, __func__, file,
|
||||
return isc__mem_allocate(isc__crypto_mctx, size, 0, file,
|
||||
(unsigned int)line);
|
||||
}
|
||||
|
||||
static void *
|
||||
isc__crypto_realloc_ex(void *ptr, size_t size, const char *file, int line) {
|
||||
return isc__mem_reallocate(isc__crypto_mctx, ptr, size, 0, __func__,
|
||||
file, (unsigned int)line);
|
||||
return isc__mem_reallocate(isc__crypto_mctx, ptr, size, 0, file,
|
||||
(unsigned int)line);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -130,7 +95,7 @@ isc__crypto_free_ex(void *ptr, const char *file, int line) {
|
||||
return;
|
||||
}
|
||||
if (isc__crypto_mctx != NULL) {
|
||||
isc__mem_free(isc__crypto_mctx, ptr, 0, __func__, file,
|
||||
isc__mem_free(isc__crypto_mctx, ptr, 0, file,
|
||||
(unsigned int)line);
|
||||
}
|
||||
}
|
||||
@@ -167,82 +132,6 @@ isc__crypto_free_ex(void *ptr, const char *file, int line) {
|
||||
|
||||
#endif /* !defined(LIBRESSL_VERSION_NUMBER) */
|
||||
|
||||
#if defined(HAVE_EVP_DEFAULT_PROPERTIES_ENABLE_FIPS)
|
||||
bool
|
||||
isc_crypto_fips_mode(void) {
|
||||
return EVP_default_properties_is_fips_enabled(NULL) != 0;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_crypto_fips_enable(void) {
|
||||
if (isc_crypto_fips_mode()) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
INSIST(fips == NULL);
|
||||
fips = OSSL_PROVIDER_load(NULL, "fips");
|
||||
if (fips == NULL) {
|
||||
return isc_tlserr2result(
|
||||
ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO,
|
||||
"OSSL_PROVIDER_load", ISC_R_CRYPTOFAILURE);
|
||||
}
|
||||
|
||||
INSIST(base == NULL);
|
||||
base = OSSL_PROVIDER_load(NULL, "base");
|
||||
if (base == NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
return isc_tlserr2result(
|
||||
ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO,
|
||||
"OSS_PROVIDER_load", ISC_R_CRYPTOFAILURE);
|
||||
}
|
||||
|
||||
if (EVP_default_properties_enable_fips(NULL, 1) == 0) {
|
||||
return isc_tlserr2result(ISC_LOGCATEGORY_GENERAL,
|
||||
ISC_LOGMODULE_CRYPTO,
|
||||
"EVP_default_properties_enable_fips",
|
||||
ISC_R_CRYPTOFAILURE);
|
||||
}
|
||||
|
||||
unregister_algorithms();
|
||||
register_algorithms();
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
#elif defined(HAVE_FIPS_MODE)
|
||||
bool
|
||||
isc_crypto_fips_mode(void) {
|
||||
return FIPS_mode() != 0;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_crypto_fips_enable(void) {
|
||||
if (isc_crypto_fips_mode()) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
if (FIPS_mode_set(1) == 0) {
|
||||
return isc_tlserr2result(ISC_LOGCATEGORY_GENERAL,
|
||||
ISC_LOGMODULE_CRYPTO, "FIPS_mode_set",
|
||||
ISC_R_CRYPTOFAILURE);
|
||||
}
|
||||
|
||||
unregister_algorithms();
|
||||
register_algorithms();
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
#else
|
||||
bool
|
||||
isc_crypto_fips_mode(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_crypto_fips_enable(void) {
|
||||
return ISC_R_NOTIMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
isc__crypto_setdestroycheck(bool check) {
|
||||
isc_mem_setdestroycheck(isc__crypto_mctx, check);
|
||||
@@ -278,16 +167,6 @@ isc__crypto_initialize(void) {
|
||||
|
||||
RUNTIME_CHECK(OPENSSL_init_ssl(opts, NULL) == 1);
|
||||
|
||||
register_algorithms();
|
||||
|
||||
#if defined(ENABLE_FIPS_MODE)
|
||||
if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
|
||||
ERR_clear_error();
|
||||
FATAL_ERROR("Failed to toggle FIPS mode but is "
|
||||
"required for this build");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Protect ourselves against unseeded PRNG */
|
||||
if (RAND_status() != 1) {
|
||||
isc_tlserr2result(ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO,
|
||||
@@ -296,23 +175,39 @@ isc__crypto_initialize(void) {
|
||||
"cannot be initialized (see the `PRNG not "
|
||||
"seeded' message in the OpenSSL FAQ)");
|
||||
}
|
||||
|
||||
#if defined(ENABLE_FIPS_MODE)
|
||||
if (!isc_fips_mode()) {
|
||||
if (isc_fips_set_mode(1) != ISC_R_SUCCESS) {
|
||||
isc_tlserr2result(ISC_LOGCATEGORY_GENERAL,
|
||||
ISC_LOGMODULE_CRYPTO, "FIPS_mode_set",
|
||||
ISC_R_CRYPTOFAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
md_register_algorithm(md5, "MD5");
|
||||
md_register_algorithm(sha1, "SHA1");
|
||||
md_register_algorithm(sha224, "SHA224");
|
||||
md_register_algorithm(sha256, "SHA256");
|
||||
md_register_algorithm(sha384, "SHA384");
|
||||
md_register_algorithm(sha512, "SHA512");
|
||||
}
|
||||
|
||||
void
|
||||
isc__crypto_shutdown(void) {
|
||||
unregister_algorithms();
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (base != NULL) {
|
||||
OSSL_PROVIDER_unload(base);
|
||||
}
|
||||
|
||||
if (fips != NULL) {
|
||||
OSSL_PROVIDER_unload(fips);
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
|
||||
md_unregister_algorithm(sha512);
|
||||
md_unregister_algorithm(sha384);
|
||||
md_unregister_algorithm(sha256);
|
||||
md_unregister_algorithm(sha224);
|
||||
md_unregister_algorithm(sha1);
|
||||
md_unregister_algorithm(md5);
|
||||
|
||||
OPENSSL_cleanup();
|
||||
|
||||
isc_mem_detach(&isc__crypto_mctx);
|
||||
isc_mem_destroy(&isc__crypto_mctx);
|
||||
}
|
||||
|
||||
#undef md_unregister_algorithm
|
||||
#undef md_register_algorithm
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <isc/fips.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#if defined(HAVE_EVP_DEFAULT_PROPERTIES_ENABLE_FIPS)
|
||||
#include <openssl/evp.h>
|
||||
bool
|
||||
isc_fips_mode(void) {
|
||||
return EVP_default_properties_is_fips_enabled(NULL) != 0;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_fips_set_mode(int mode) {
|
||||
return EVP_default_properties_enable_fips(NULL, mode) != 0
|
||||
? ISC_R_SUCCESS
|
||||
: ISC_R_FAILURE;
|
||||
}
|
||||
#elif defined(HAVE_FIPS_MODE)
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
bool
|
||||
isc_fips_mode(void) {
|
||||
return FIPS_mode() != 0;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_fips_set_mode(int mode) {
|
||||
return FIPS_mode_set(mode) != 0 ? ISC_R_SUCCESS : ISC_R_FAILURE;
|
||||
}
|
||||
#else
|
||||
bool
|
||||
isc_fips_mode(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_fips_set_mode(int mode) {
|
||||
UNUSED(mode);
|
||||
return ISC_R_NOTIMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/barrier.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/helper.h>
|
||||
#include <isc/job.h>
|
||||
#include <isc/loop.h>
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <isc/error.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
/*
|
||||
* We use macros instead of static inline functions so that the exact code
|
||||
* location can be reported when PTHREADS_RUNTIME_CHECK() fails or when mutrace
|
||||
* reports lock contention.
|
||||
*/
|
||||
|
||||
#ifdef ISC_TRACK_PTHREADS_OBJECTS
|
||||
|
||||
typedef pthread_cond_t *isc_condition_t;
|
||||
|
||||
#define isc_condition_init(cp) \
|
||||
{ \
|
||||
*cp = malloc(sizeof(**cp)); \
|
||||
isc__condition_init(*cp); \
|
||||
}
|
||||
#define isc_condition_wait(cp, mp) isc__condition_wait(*cp, *mp)
|
||||
#define isc_condition_waituntil(cp, mp, t) isc__condition_waituntil(*cp, *mp, t)
|
||||
#define isc_condition_signal(cp) isc__condition_signal(*cp)
|
||||
#define isc_condition_broadcast(cp) isc__condition_broadcast(*cp)
|
||||
#define isc_condition_destroy(cp) \
|
||||
{ \
|
||||
isc__condition_destroy(*cp); \
|
||||
free(*cp); \
|
||||
}
|
||||
|
||||
#else /* ISC_TRACK_PTHREADS_OBJECTS */
|
||||
|
||||
typedef pthread_cond_t isc_condition_t;
|
||||
|
||||
#define isc_condition_init(cond) isc__condition_init(cond)
|
||||
#define isc_condition_wait(cp, mp) isc__condition_wait(cp, mp)
|
||||
#define isc_condition_waituntil(cp, mp, t) isc__condition_waituntil(cp, mp, t)
|
||||
#define isc_condition_signal(cp) isc__condition_signal(cp)
|
||||
#define isc_condition_broadcast(cp) isc__condition_broadcast(cp)
|
||||
#define isc_condition_destroy(cp) isc__condition_destroy(cp)
|
||||
|
||||
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
|
||||
|
||||
#define isc__condition_init(cond) \
|
||||
{ \
|
||||
int _ret = pthread_cond_init(cond, NULL); \
|
||||
PTHREADS_RUNTIME_CHECK(pthread_cond_init, _ret); \
|
||||
}
|
||||
|
||||
#define isc__condition_wait(cp, mp) \
|
||||
{ \
|
||||
int _ret = pthread_cond_wait(cp, mp); \
|
||||
PTHREADS_RUNTIME_CHECK(pthread_cond_wait, _ret); \
|
||||
}
|
||||
|
||||
#define isc__condition_signal(cp) \
|
||||
{ \
|
||||
int _ret = pthread_cond_signal(cp); \
|
||||
PTHREADS_RUNTIME_CHECK(pthread_cond_signal, _ret); \
|
||||
}
|
||||
|
||||
#define isc__condition_broadcast(cp) \
|
||||
{ \
|
||||
int _ret = pthread_cond_broadcast(cp); \
|
||||
PTHREADS_RUNTIME_CHECK(pthread_cond_broadcast, _ret); \
|
||||
}
|
||||
|
||||
#define isc__condition_destroy(cp) \
|
||||
{ \
|
||||
int _ret = pthread_cond_destroy(cp); \
|
||||
PTHREADS_RUNTIME_CHECK(pthread_cond_destroy, _ret); \
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc__condition_waituntil(pthread_cond_t *, pthread_mutex_t *, isc_time_t *);
|
||||
@@ -24,20 +24,6 @@ extern const EVP_MD *isc__crypto_sha256;
|
||||
extern const EVP_MD *isc__crypto_sha384;
|
||||
extern const EVP_MD *isc__crypto_sha512;
|
||||
|
||||
bool
|
||||
isc_crypto_fips_mode(void);
|
||||
/*
|
||||
* Return if FIPS mode is currently enabled or not.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_crypto_fips_enable(void);
|
||||
/*
|
||||
* Enable FIPS mode. It cannot be disabled afterwards.
|
||||
*
|
||||
* This function is NOT thread safe.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Private
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
*****/
|
||||
|
||||
/***
|
||||
*** Imports
|
||||
***/
|
||||
|
||||
#include <isc/types.h>
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
bool
|
||||
isc_fips_mode(void);
|
||||
/*
|
||||
* Return if FIPS mode is currently enabled or not
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_fips_set_mode(int mode);
|
||||
/*
|
||||
* Enable FIPS mode.
|
||||
*/
|
||||
+31
-15
@@ -21,12 +21,9 @@
|
||||
#include <isc/attributes.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/overflow.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/urcu.h>
|
||||
|
||||
/* Add -DISC_MEM_TRACE=1 to CFLAGS for detailed reference tracing */
|
||||
|
||||
/*%
|
||||
* Define ISC_MEM_TRACKLINES=1 to turn on detailed tracing of memory
|
||||
* allocation and freeing by file and line number.
|
||||
@@ -65,8 +62,8 @@ extern unsigned int isc_mem_defaultflags;
|
||||
/*@}*/
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
#define _ISC_MEM_FILELINE , __func__, __FILE__, __LINE__
|
||||
#define _ISC_MEM_FLARG , const char *, const char *, unsigned int
|
||||
#define _ISC_MEM_FILELINE , __FILE__, __LINE__
|
||||
#define _ISC_MEM_FLARG , const char *, unsigned int
|
||||
#else /* if ISC_MEM_TRACKLINES */
|
||||
#define _ISC_MEM_FILELINE
|
||||
#define _ISC_MEM_FLARG
|
||||
@@ -252,16 +249,35 @@ isc_mem_arena_set_dirty_decay_ms(isc_mem_t *mctx, const ssize_t decay_ms);
|
||||
*/
|
||||
/*@}*/
|
||||
|
||||
#if ISC_MEM_TRACE
|
||||
#define isc_mem_ref(ptr) isc_mem__ref(ptr, __func__, __FILE__, __LINE__)
|
||||
#define isc_mem_unref(ptr) isc_mem__unref(ptr, __func__, __FILE__, __LINE__)
|
||||
#define isc_mem_attach(ptr, ptrp) \
|
||||
isc_mem__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
|
||||
#define isc_mem_detach(ptrp) isc_mem__detach(ptrp, __func__, __FILE__, __LINE__)
|
||||
ISC_REFCOUNT_TRACE_DECL(isc_mem);
|
||||
#else
|
||||
ISC_REFCOUNT_DECL(isc_mem);
|
||||
#endif
|
||||
void
|
||||
isc_mem_attach(isc_mem_t *, isc_mem_t **);
|
||||
|
||||
/*@{*/
|
||||
void
|
||||
isc_mem_attach(isc_mem_t *, isc_mem_t **);
|
||||
#define isc_mem_detach(cp) isc__mem_detach((cp)_ISC_MEM_FILELINE)
|
||||
void
|
||||
isc__mem_detach(isc_mem_t **_ISC_MEM_FLARG);
|
||||
/*!<
|
||||
* \brief Attach to / detach from a memory context.
|
||||
*
|
||||
* This is intended for applications that use multiple memory contexts
|
||||
* in such a way that it is not obvious when the last allocations from
|
||||
* a given context has been freed and destroying the context is safe.
|
||||
*
|
||||
* Most applications do not need to call these functions as they can
|
||||
* simply create a single memory context at the beginning of main()
|
||||
* and destroy it at the end of main(), thereby guaranteeing that it
|
||||
* is not destroyed while there are outstanding allocations.
|
||||
*/
|
||||
/*@}*/
|
||||
|
||||
#define isc_mem_destroy(cp) isc__mem_destroy((cp)_ISC_MEM_FILELINE)
|
||||
void
|
||||
isc__mem_destroy(isc_mem_t **_ISC_MEM_FLARG);
|
||||
/*%<
|
||||
* Destroy a memory context.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_mem_stats(isc_mem_t *mctx, FILE *out);
|
||||
|
||||
@@ -22,21 +22,6 @@
|
||||
#include <isc/result.h> /* for ISC_R_ codes */
|
||||
#include <isc/util.h>
|
||||
|
||||
#define LOCK(lp) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "LOCKING %p %s %d\n", (lp), \
|
||||
__FILE__, __LINE__)); \
|
||||
isc_mutex_lock((lp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "LOCKED %p %s %d\n", (lp), \
|
||||
__FILE__, __LINE__)); \
|
||||
}
|
||||
#define UNLOCK(lp) \
|
||||
{ \
|
||||
isc_mutex_unlock((lp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "UNLOCKED %p %s %d\n", (lp), \
|
||||
__FILE__, __LINE__)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* We use macros instead of static inline functions so that the exact code
|
||||
* location can be reported when PTHREADS_RUNTIME_CHECK() fails or when mutrace
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*! \file isc/mutexblock.h */
|
||||
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
void
|
||||
isc_mutexblock_init(isc_mutex_t *block, unsigned int count);
|
||||
/*%<
|
||||
* Initialize a block of locks. If an error occurs all initialized locks
|
||||
* will be destroyed, if possible.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li block != NULL
|
||||
*
|
||||
*\li count > 0
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
isc_mutexblock_destroy(isc_mutex_t *block, unsigned int count);
|
||||
/*%<
|
||||
* Destroy a block of locks.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li block != NULL
|
||||
*
|
||||
*\li count > 0
|
||||
*
|
||||
*\li Each lock in the block be initialized via isc_mutex_init() or
|
||||
* the whole block was initialized via isc_mutex_initblock().
|
||||
*
|
||||
*/
|
||||
@@ -14,6 +14,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*! \file isc/rwlock.h */
|
||||
|
||||
@@ -26,42 +27,7 @@ typedef enum {
|
||||
isc_rwlocktype_write
|
||||
} isc_rwlocktype_t;
|
||||
|
||||
#define RWLOCK(lp, t) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "RWLOCK %p, %d %s %d\n", (lp), \
|
||||
(t), __FILE__, __LINE__)); \
|
||||
isc_rwlock_lock((lp), (t)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "RWLOCKED %p, %d %s %d\n", \
|
||||
(lp), (t), __FILE__, __LINE__)); \
|
||||
}
|
||||
#define RWUNLOCK(lp, t) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "RWUNLOCK %p, %d %s %d\n", \
|
||||
(lp), (t), __FILE__, __LINE__)); \
|
||||
isc_rwlock_unlock((lp), (t)); \
|
||||
}
|
||||
|
||||
#define RDLOCK(lp) RWLOCK(lp, isc_rwlocktype_read)
|
||||
#define RDUNLOCK(lp) RWUNLOCK(lp, isc_rwlocktype_read)
|
||||
#define WRLOCK(lp) RWLOCK(lp, isc_rwlocktype_write)
|
||||
#define WRUNLOCK(lp) RWUNLOCK(lp, isc_rwlocktype_write)
|
||||
|
||||
#define UPGRADELOCK(lock, locktype) \
|
||||
{ \
|
||||
if (locktype == isc_rwlocktype_read) { \
|
||||
if (isc_rwlock_tryupgrade(lock) == ISC_R_SUCCESS) { \
|
||||
locktype = isc_rwlocktype_write; \
|
||||
} else { \
|
||||
RWUNLOCK(lock, locktype); \
|
||||
locktype = isc_rwlocktype_write; \
|
||||
RWLOCK(lock, locktype); \
|
||||
} \
|
||||
} \
|
||||
INSIST(locktype == isc_rwlocktype_write); \
|
||||
}
|
||||
|
||||
#if USE_PTHREAD_RWLOCK
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/*
|
||||
@@ -72,8 +38,6 @@ typedef enum {
|
||||
|
||||
#if ISC_TRACK_PTHREADS_OBJECTS
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef pthread_rwlock_t *isc_rwlock_t;
|
||||
typedef pthread_rwlock_t isc__rwlock_t;
|
||||
|
||||
|
||||
@@ -21,21 +21,6 @@
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#define SPINLOCK(sp) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "SPINLOCKING %p %s %d\n", (sp), \
|
||||
__FILE__, __LINE__)); \
|
||||
isc_spinlock_lock((sp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "SPINLOCKED %p %s %d\n", (sp), \
|
||||
__FILE__, __LINE__)); \
|
||||
}
|
||||
#define SPINUNLOCK(sp) \
|
||||
{ \
|
||||
isc_spinlock_unlock((sp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "SPINUNLOCKED %p %s %d\n", \
|
||||
(sp), __FILE__, __LINE__)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* We use macros instead of static inline functions so that the exact code
|
||||
* location can be reported when PTHREADS_RUNTIME_CHECK() fails or when mutrace
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
* ISC_ or isc_ to the name.
|
||||
*/
|
||||
|
||||
#include <isc/attributes.h>
|
||||
|
||||
/***
|
||||
*** Clang Compatibility Macros
|
||||
***/
|
||||
@@ -108,6 +110,11 @@
|
||||
*/
|
||||
#define EMPTY_TRANSLATION_UNIT extern int isc__empty;
|
||||
|
||||
/*%
|
||||
* We use macros instead of calling the routines directly because
|
||||
* the capital letters make the locking stand out.
|
||||
*/
|
||||
|
||||
#ifdef ISC_UTIL_TRACEON
|
||||
#define ISC_UTIL_TRACE(a) a
|
||||
#include <stdio.h> /* Required for fprintf/stderr when tracing. */
|
||||
@@ -115,6 +122,125 @@
|
||||
#define ISC_UTIL_TRACE(a)
|
||||
#endif /* ifdef ISC_UTIL_TRACEON */
|
||||
|
||||
#include <isc/result.h> /* Contractual promise. */
|
||||
|
||||
#define SPINLOCK(sp) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "SPINLOCKING %p %s %d\n", (sp), \
|
||||
__FILE__, __LINE__)); \
|
||||
isc_spinlock_lock((sp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "SPINLOCKED %p %s %d\n", (sp), \
|
||||
__FILE__, __LINE__)); \
|
||||
}
|
||||
#define SPINUNLOCK(sp) \
|
||||
{ \
|
||||
isc_spinlock_unlock((sp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "SPINUNLOCKED %p %s %d\n", \
|
||||
(sp), __FILE__, __LINE__)); \
|
||||
}
|
||||
|
||||
#define LOCK(lp) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "LOCKING %p %s %d\n", (lp), \
|
||||
__FILE__, __LINE__)); \
|
||||
isc_mutex_lock((lp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "LOCKED %p %s %d\n", (lp), \
|
||||
__FILE__, __LINE__)); \
|
||||
}
|
||||
#define UNLOCK(lp) \
|
||||
{ \
|
||||
isc_mutex_unlock((lp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "UNLOCKED %p %s %d\n", (lp), \
|
||||
__FILE__, __LINE__)); \
|
||||
}
|
||||
|
||||
#define BROADCAST(cvp) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "BROADCAST %p %s %d\n", (cvp), \
|
||||
__FILE__, __LINE__)); \
|
||||
isc_condition_broadcast((cvp)); \
|
||||
}
|
||||
#define SIGNAL(cvp) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "SIGNAL %p %s %d\n", (cvp), \
|
||||
__FILE__, __LINE__)); \
|
||||
isc_condition_signal((cvp)); \
|
||||
}
|
||||
#define WAIT(cvp, lp) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "WAIT %p LOCK %p %s %d\n", \
|
||||
(cvp), (lp), __FILE__, __LINE__)); \
|
||||
isc_condition_wait((cvp), (lp)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "WAITED %p LOCKED %p %s %d\n", \
|
||||
(cvp), (lp), __FILE__, __LINE__)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
|
||||
* don't RUNTIME_CHECK the result.
|
||||
*
|
||||
* XXX Also, can't really debug this then...
|
||||
*/
|
||||
|
||||
#define WAITUNTIL(cvp, lp, tp) isc_condition_waituntil((cvp), (lp), (tp))
|
||||
|
||||
#define RWLOCK(lp, t) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "RWLOCK %p, %d %s %d\n", (lp), \
|
||||
(t), __FILE__, __LINE__)); \
|
||||
isc_rwlock_lock((lp), (t)); \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "RWLOCKED %p, %d %s %d\n", \
|
||||
(lp), (t), __FILE__, __LINE__)); \
|
||||
}
|
||||
#define RWUNLOCK(lp, t) \
|
||||
{ \
|
||||
ISC_UTIL_TRACE(fprintf(stderr, "RWUNLOCK %p, %d %s %d\n", \
|
||||
(lp), (t), __FILE__, __LINE__)); \
|
||||
isc_rwlock_unlock((lp), (t)); \
|
||||
}
|
||||
|
||||
#define RDLOCK(lp) RWLOCK(lp, isc_rwlocktype_read)
|
||||
#define RDUNLOCK(lp) RWUNLOCK(lp, isc_rwlocktype_read)
|
||||
#define WRLOCK(lp) RWLOCK(lp, isc_rwlocktype_write)
|
||||
#define WRUNLOCK(lp) RWUNLOCK(lp, isc_rwlocktype_write)
|
||||
|
||||
#define UPGRADELOCK(lock, locktype) \
|
||||
{ \
|
||||
if (locktype == isc_rwlocktype_read) { \
|
||||
if (isc_rwlock_tryupgrade(lock) == ISC_R_SUCCESS) { \
|
||||
locktype = isc_rwlocktype_write; \
|
||||
} else { \
|
||||
RWUNLOCK(lock, locktype); \
|
||||
locktype = isc_rwlocktype_write; \
|
||||
RWLOCK(lock, locktype); \
|
||||
} \
|
||||
} \
|
||||
INSIST(locktype == isc_rwlocktype_write); \
|
||||
}
|
||||
|
||||
/*
|
||||
* List Macros.
|
||||
*/
|
||||
#include <isc/list.h> /* Contractual promise. */
|
||||
|
||||
#define LIST(type) ISC_LIST(type)
|
||||
#define INIT_LIST(type) ISC_LIST_INIT(type)
|
||||
#define LINK(type) ISC_LINK(type)
|
||||
#define INIT_LINK(elt, link) ISC_LINK_INIT(elt, link)
|
||||
#define HEAD(list) ISC_LIST_HEAD(list)
|
||||
#define TAIL(list) ISC_LIST_TAIL(list)
|
||||
#define EMPTY(list) ISC_LIST_EMPTY(list)
|
||||
#define PREV(elt, link) ISC_LIST_PREV(elt, link)
|
||||
#define NEXT(elt, link) ISC_LIST_NEXT(elt, link)
|
||||
#define APPEND(list, elt, link) ISC_LIST_APPEND(list, elt, link)
|
||||
#define PREPEND(list, elt, link) ISC_LIST_PREPEND(list, elt, link)
|
||||
#define UNLINK(list, elt, link) ISC_LIST_UNLINK(list, elt, link)
|
||||
#define ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
|
||||
#define DEQUEUE(list, elt, link) ISC_LIST_UNLINK(list, elt, link)
|
||||
#define INSERTBEFORE(li, b, e, ln) ISC_LIST_INSERTBEFORE(li, b, e, ln)
|
||||
#define INSERTAFTER(li, a, e, ln) ISC_LIST_INSERTAFTER(li, a, e, ln)
|
||||
#define APPENDLIST(list1, list2, link) ISC_LIST_APPENDLIST(list1, list2, link)
|
||||
|
||||
/*%
|
||||
* Performance
|
||||
*/
|
||||
@@ -140,7 +266,18 @@
|
||||
#define ISC_NO_SANITIZE_THREAD
|
||||
#endif /* if __SANITIZE_THREAD__ */
|
||||
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 6)
|
||||
#define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
|
||||
#elif __has_feature(c_static_assert)
|
||||
#define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
|
||||
#else /* if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 6) */
|
||||
|
||||
/* Courtesy of Joseph Quinsey: https://godbolt.org/z/K9RvWS */
|
||||
#define TOKENPASTE(a, b) a##b /* "##" is the "Token Pasting Operator" */
|
||||
#define EXPAND_THEN_PASTE(a, b) TOKENPASTE(a, b) /* expand then paste */
|
||||
#define STATIC_ASSERT(x, msg) \
|
||||
enum { EXPAND_THEN_PASTE(ASSERT_line_, __LINE__) = 1 / ((msg) && (x)) }
|
||||
#endif /* if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 6) */
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
extern void
|
||||
@@ -199,6 +336,8 @@ mock_assert(const int result, const char *const expression,
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
#include <errno.h> /* for errno */
|
||||
|
||||
#include <isc/error.h> /* Contractual promise. */
|
||||
#include <isc/strerr.h> /* for ISC_STRERRORSIZE */
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/barrier.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/job.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/loop.h>
|
||||
|
||||
+12
-12
@@ -61,7 +61,7 @@ struct isc_lex {
|
||||
unsigned int paren_count;
|
||||
unsigned int saved_paren_count;
|
||||
isc_lexspecials_t specials;
|
||||
ISC_LIST(struct inputsource) sources;
|
||||
LIST(struct inputsource) sources;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -104,7 +104,7 @@ isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp) {
|
||||
lex->paren_count = 0;
|
||||
lex->saved_paren_count = 0;
|
||||
memset(lex->specials, 0, 256);
|
||||
ISC_LIST_INIT(lex->sources);
|
||||
INIT_LIST(lex->sources);
|
||||
lex->magic = LEX_MAGIC;
|
||||
|
||||
*lexp = lex;
|
||||
@@ -123,7 +123,7 @@ isc_lex_destroy(isc_lex_t **lexp) {
|
||||
*lexp = NULL;
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
|
||||
while (!ISC_LIST_EMPTY(lex->sources)) {
|
||||
while (!EMPTY(lex->sources)) {
|
||||
RUNTIME_CHECK(isc_lex_close(lex) == ISC_R_SUCCESS);
|
||||
}
|
||||
if (lex->data != NULL) {
|
||||
@@ -259,7 +259,7 @@ isc_lex_close(isc_lex_t *lex) {
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
if (source == NULL) {
|
||||
return ISC_R_NOMORE;
|
||||
}
|
||||
@@ -352,7 +352,7 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) {
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
REQUIRE(tokenp != NULL);
|
||||
|
||||
if (source == NULL) {
|
||||
@@ -999,7 +999,7 @@ isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp) {
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
REQUIRE(source != NULL);
|
||||
REQUIRE(tokenp != NULL);
|
||||
REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 ||
|
||||
@@ -1018,7 +1018,7 @@ isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r) {
|
||||
inputsource *source;
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
REQUIRE(source != NULL);
|
||||
REQUIRE(tokenp != NULL);
|
||||
REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 ||
|
||||
@@ -1038,7 +1038,7 @@ isc_lex_getsourcename(isc_lex_t *lex) {
|
||||
inputsource *source;
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
|
||||
if (source == NULL) {
|
||||
return NULL;
|
||||
@@ -1052,7 +1052,7 @@ isc_lex_getsourceline(isc_lex_t *lex) {
|
||||
inputsource *source;
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
|
||||
if (source == NULL) {
|
||||
return 0;
|
||||
@@ -1067,7 +1067,7 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name) {
|
||||
char *newname;
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
|
||||
if (source == NULL) {
|
||||
return ISC_R_NOTFOUND;
|
||||
@@ -1083,7 +1083,7 @@ isc_lex_setsourceline(isc_lex_t *lex, unsigned long line) {
|
||||
inputsource *source;
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
|
||||
if (source == NULL) {
|
||||
return ISC_R_NOTFOUND;
|
||||
@@ -1099,7 +1099,7 @@ isc_lex_isfile(isc_lex_t *lex) {
|
||||
|
||||
REQUIRE(VALID_LEX(lex));
|
||||
|
||||
source = ISC_LIST_HEAD(lex->sources);
|
||||
source = HEAD(lex->sources);
|
||||
|
||||
if (source == NULL) {
|
||||
return false;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <isc/async.h>
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/barrier.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/job.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/log.h>
|
||||
|
||||
+1
-1
@@ -47,5 +47,5 @@ isc_managers_destroy(isc_mem_t **mctxp, isc_loopmgr_t **loopmgrp,
|
||||
|
||||
isc_netmgr_destroy(netmgrp);
|
||||
isc_loopmgr_destroy(loopmgrp);
|
||||
isc_mem_detach(mctxp);
|
||||
isc_mem_destroy(mctxp);
|
||||
}
|
||||
|
||||
+100
-55
@@ -86,15 +86,14 @@ struct debuglink {
|
||||
ISC_LINK(debuglink_t) link;
|
||||
const void *ptr;
|
||||
size_t size;
|
||||
const char *func;
|
||||
const char *file;
|
||||
unsigned int line;
|
||||
};
|
||||
|
||||
typedef ISC_LIST(debuglink_t) debuglist_t;
|
||||
|
||||
#define FLARG_PASS , func, file, line
|
||||
#define FLARG , const char *func, const char *file, unsigned int line
|
||||
#define FLARG_PASS , file, line
|
||||
#define FLARG , const char *file, unsigned int line
|
||||
#else /* if ISC_MEM_TRACKLINES */
|
||||
#define FLARG_PASS
|
||||
#define FLARG
|
||||
@@ -165,8 +164,8 @@ struct isc_mempool {
|
||||
*/
|
||||
|
||||
#if !ISC_MEM_TRACKLINES
|
||||
#define ADD_TRACE(mctx, ptr, size, func, file, line)
|
||||
#define DELETE_TRACE(mctx, ptr, size, func, file, line)
|
||||
#define ADD_TRACE(mctx, ptr, size, file, line)
|
||||
#define DELETE_TRACE(mctx, ptr, size, file, line)
|
||||
#define ISC_MEMFUNC_SCOPE
|
||||
#else /* if !ISC_MEM_TRACKLINES */
|
||||
#define TRACE_OR_RECORD (ISC_MEM_DEBUGTRACE | ISC_MEM_DEBUGRECORD)
|
||||
@@ -174,14 +173,14 @@ struct isc_mempool {
|
||||
#define SHOULD_TRACE_OR_RECORD(mctx, ptr) \
|
||||
(((mctx)->debugging & TRACE_OR_RECORD) != 0 && ptr != NULL)
|
||||
|
||||
#define ADD_TRACE(mctx, ptr, size, func, file, line) \
|
||||
if (SHOULD_TRACE_OR_RECORD(mctx, ptr)) { \
|
||||
add_trace_entry(mctx, ptr, size, func, file, line); \
|
||||
#define ADD_TRACE(mctx, ptr, size, file, line) \
|
||||
if (SHOULD_TRACE_OR_RECORD(mctx, ptr)) { \
|
||||
add_trace_entry(mctx, ptr, size, file, line); \
|
||||
}
|
||||
|
||||
#define DELETE_TRACE(mctx, ptr, size, func, file, line) \
|
||||
if (SHOULD_TRACE_OR_RECORD(mctx, ptr)) { \
|
||||
delete_trace_entry(mctx, ptr, size, func, file, line); \
|
||||
#define DELETE_TRACE(mctx, ptr, size, file, line) \
|
||||
if (SHOULD_TRACE_OR_RECORD(mctx, ptr)) { \
|
||||
delete_trace_entry(mctx, ptr, size, file, line); \
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -201,9 +200,8 @@ add_trace_entry(isc_mem_t *mctx, const void *ptr, size_t size FLARG) {
|
||||
MCTXLOCK(mctx);
|
||||
|
||||
if ((mctx->debugging & ISC_MEM_DEBUGTRACE) != 0) {
|
||||
fprintf(stderr,
|
||||
"add %p size %zu func %s file %s line %u mctx %p\n",
|
||||
ptr, size, func, file, line, mctx);
|
||||
fprintf(stderr, "add %p size %zu file %s line %u mctx %p\n",
|
||||
ptr, size, file, line, mctx);
|
||||
}
|
||||
|
||||
if (mctx->debuglist == NULL) {
|
||||
@@ -227,7 +225,6 @@ add_trace_entry(isc_mem_t *mctx, const void *ptr, size_t size FLARG) {
|
||||
ISC_LINK_INIT(dl, link);
|
||||
dl->ptr = ptr;
|
||||
dl->size = size;
|
||||
dl->func = func;
|
||||
dl->file = file;
|
||||
dl->line = line;
|
||||
|
||||
@@ -238,7 +235,8 @@ unlock:
|
||||
}
|
||||
|
||||
static void
|
||||
delete_trace_entry(isc_mem_t *mctx, const void *ptr, size_t size FLARG) {
|
||||
delete_trace_entry(isc_mem_t *mctx, const void *ptr, size_t size,
|
||||
const char *file, unsigned int line) {
|
||||
debuglink_t *dl = NULL;
|
||||
uint32_t hash;
|
||||
uint32_t idx;
|
||||
@@ -246,9 +244,8 @@ delete_trace_entry(isc_mem_t *mctx, const void *ptr, size_t size FLARG) {
|
||||
MCTXLOCK(mctx);
|
||||
|
||||
if ((mctx->debugging & ISC_MEM_DEBUGTRACE) != 0) {
|
||||
fprintf(stderr,
|
||||
"del %p size %zu func %s file %s line %u mctx %p\n",
|
||||
ptr, size, func, file, line, mctx);
|
||||
fprintf(stderr, "del %p size %zu file %s line %u mctx %p\n",
|
||||
ptr, size, file, line, mctx);
|
||||
}
|
||||
|
||||
if (mctx->debuglist == NULL) {
|
||||
@@ -430,8 +427,6 @@ void
|
||||
isc__mem_shutdown(void) {
|
||||
bool empty;
|
||||
|
||||
rcu_barrier();
|
||||
|
||||
isc__mem_checkdestroyed();
|
||||
|
||||
LOCK(&contextslock);
|
||||
@@ -500,11 +495,8 @@ mem_create(isc_mem_t **ctxp, unsigned int debugging, unsigned int flags,
|
||||
*/
|
||||
|
||||
static void
|
||||
mem_destroy(isc_mem_t *ctx) {
|
||||
destroy(isc_mem_t *ctx) {
|
||||
unsigned int arena_no;
|
||||
|
||||
isc_refcount_destroy(&ctx->references);
|
||||
|
||||
LOCK(&contextslock);
|
||||
ISC_LIST_UNLINK(contexts, ctx, link);
|
||||
UNLOCK(&contextslock);
|
||||
@@ -551,11 +543,36 @@ mem_destroy(isc_mem_t *ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
#if ISC_MEM_TRACE
|
||||
ISC_REFCOUNT_TRACE_IMPL(isc_mem, mem_destroy);
|
||||
#else
|
||||
ISC_REFCOUNT_IMPL(isc_mem, mem_destroy);
|
||||
void
|
||||
isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
|
||||
REQUIRE(VALID_CONTEXT(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
isc_refcount_increment(&source->references);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
void
|
||||
isc__mem_detach(isc_mem_t **ctxp FLARG) {
|
||||
isc_mem_t *ctx = NULL;
|
||||
|
||||
REQUIRE(ctxp != NULL && VALID_CONTEXT(*ctxp));
|
||||
|
||||
ctx = *ctxp;
|
||||
*ctxp = NULL;
|
||||
|
||||
if (isc_refcount_decrement(&ctx->references) == 1) {
|
||||
isc_refcount_destroy(&ctx->references);
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if ((ctx->debugging & ISC_MEM_DEBUGTRACE) != 0) {
|
||||
fprintf(stderr, "destroy mctx %p file %s line %u\n",
|
||||
ctx, file, line);
|
||||
}
|
||||
#endif
|
||||
destroy(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* isc_mem_putanddetach() is the equivalent of:
|
||||
@@ -578,11 +595,41 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size,
|
||||
*ctxp = NULL;
|
||||
|
||||
isc__mem_put(ctx, ptr, size, flags FLARG_PASS);
|
||||
#if ISC_MEM_TRACE
|
||||
isc_mem__detach(&ctx, func, file, line);
|
||||
#else
|
||||
isc_mem_detach(&ctx);
|
||||
#endif
|
||||
isc__mem_detach(&ctx FLARG_PASS);
|
||||
}
|
||||
|
||||
void
|
||||
isc__mem_destroy(isc_mem_t **ctxp FLARG) {
|
||||
isc_mem_t *ctx = NULL;
|
||||
|
||||
/*
|
||||
* This routine provides legacy support for callers who use mctxs
|
||||
* without attaching/detaching.
|
||||
*/
|
||||
|
||||
REQUIRE(ctxp != NULL && VALID_CONTEXT(*ctxp));
|
||||
|
||||
ctx = *ctxp;
|
||||
*ctxp = NULL;
|
||||
|
||||
rcu_barrier();
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if ((ctx->debugging & ISC_MEM_DEBUGTRACE) != 0) {
|
||||
fprintf(stderr, "destroy mctx %p file %s line %u\n", ctx, file,
|
||||
line);
|
||||
}
|
||||
|
||||
if (isc_refcount_decrement(&ctx->references) > 1) {
|
||||
print_active(ctx, stderr);
|
||||
}
|
||||
#else /* if ISC_MEM_TRACKLINES */
|
||||
isc_refcount_decrementz(&ctx->references);
|
||||
#endif /* if ISC_MEM_TRACKLINES */
|
||||
isc_refcount_destroy(&ctx->references);
|
||||
destroy(ctx);
|
||||
|
||||
*ctxp = NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
@@ -594,7 +641,7 @@ isc__mem_get(isc_mem_t *ctx, size_t size, int flags FLARG) {
|
||||
ptr = mem_get(ctx, size, flags);
|
||||
|
||||
mem_getstats(ctx, size);
|
||||
ADD_TRACE(ctx, ptr, size, func, file, line);
|
||||
ADD_TRACE(ctx, ptr, size, file, line);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@@ -603,7 +650,7 @@ void
|
||||
isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size, int flags FLARG) {
|
||||
REQUIRE(VALID_CONTEXT(ctx));
|
||||
|
||||
DELETE_TRACE(ctx, ptr, size, func, file, line);
|
||||
DELETE_TRACE(ctx, ptr, size, file, line);
|
||||
|
||||
mem_putstats(ctx, size);
|
||||
mem_put(ctx, ptr, size, flags);
|
||||
@@ -700,7 +747,7 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size, int flags FLARG) {
|
||||
size = sallocx(ptr, flags | ctx->jemalloc_flags);
|
||||
|
||||
mem_getstats(ctx, size);
|
||||
ADD_TRACE(ctx, ptr, size, func, file, line);
|
||||
ADD_TRACE(ctx, ptr, size, file, line);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@@ -716,13 +763,13 @@ isc__mem_reget(isc_mem_t *ctx, void *old_ptr, size_t old_size, size_t new_size,
|
||||
} else if (new_size == 0) {
|
||||
isc__mem_put(ctx, old_ptr, old_size, flags FLARG_PASS);
|
||||
} else {
|
||||
DELETE_TRACE(ctx, old_ptr, old_size, func, file, line);
|
||||
DELETE_TRACE(ctx, old_ptr, old_size, file, line);
|
||||
mem_putstats(ctx, old_size);
|
||||
|
||||
new_ptr = mem_realloc(ctx, old_ptr, old_size, new_size, flags);
|
||||
|
||||
mem_getstats(ctx, new_size);
|
||||
ADD_TRACE(ctx, new_ptr, new_size, func, file, line);
|
||||
ADD_TRACE(ctx, new_ptr, new_size, file, line);
|
||||
|
||||
/*
|
||||
* We want to postpone the call to water in edge case
|
||||
@@ -748,7 +795,7 @@ isc__mem_reallocate(isc_mem_t *ctx, void *old_ptr, size_t new_size,
|
||||
} else {
|
||||
size_t old_size = sallocx(old_ptr, flags | ctx->jemalloc_flags);
|
||||
|
||||
DELETE_TRACE(ctx, old_ptr, old_size, func, file, line);
|
||||
DELETE_TRACE(ctx, old_ptr, old_size, file, line);
|
||||
mem_putstats(ctx, old_size);
|
||||
|
||||
new_ptr = mem_realloc(ctx, old_ptr, old_size, new_size, flags);
|
||||
@@ -757,7 +804,7 @@ isc__mem_reallocate(isc_mem_t *ctx, void *old_ptr, size_t new_size,
|
||||
new_size = sallocx(new_ptr, flags | ctx->jemalloc_flags);
|
||||
|
||||
mem_getstats(ctx, new_size);
|
||||
ADD_TRACE(ctx, new_ptr, new_size, func, file, line);
|
||||
ADD_TRACE(ctx, new_ptr, new_size, file, line);
|
||||
|
||||
/*
|
||||
* We want to postpone the call to water in edge case
|
||||
@@ -778,7 +825,7 @@ isc__mem_free(isc_mem_t *ctx, void *ptr, int flags FLARG) {
|
||||
|
||||
size = sallocx(ptr, flags | ctx->jemalloc_flags);
|
||||
|
||||
DELETE_TRACE(ctx, ptr, size, func, file, line);
|
||||
DELETE_TRACE(ctx, ptr, size, file, line);
|
||||
|
||||
mem_putstats(ctx, size);
|
||||
mem_put(ctx, ptr, size, flags);
|
||||
@@ -963,9 +1010,8 @@ isc__mempool_create(isc_mem_t *restrict mctx, const size_t element_size,
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if ((mctx->debugging & ISC_MEM_DEBUGTRACE) != 0) {
|
||||
fprintf(stderr,
|
||||
"create pool %p func %s file %s line %u mctx %p\n",
|
||||
mpctx, func, file, line, mctx);
|
||||
fprintf(stderr, "create pool %p file %s line %u mctx %p\n",
|
||||
mpctx, file, line, mctx);
|
||||
}
|
||||
#endif /* ISC_MEM_TRACKLINES */
|
||||
|
||||
@@ -1004,9 +1050,8 @@ isc__mempool_destroy(isc_mempool_t **restrict mpctxp FLARG) {
|
||||
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if ((mctx->debugging & ISC_MEM_DEBUGTRACE) != 0) {
|
||||
fprintf(stderr,
|
||||
"destroy pool %p func %s file %s line %u mctx %p\n",
|
||||
mpctx, func, file, line, mctx);
|
||||
fprintf(stderr, "destroy pool %p file %s line %u mctx %p\n",
|
||||
mpctx, file, line, mctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1078,7 +1123,7 @@ isc__mempool_get(isc_mempool_t *restrict mpctx FLARG) {
|
||||
mpctx->freecount--;
|
||||
mpctx->gets++;
|
||||
|
||||
ADD_TRACE(mpctx->mctx, item, mpctx->size, func, file, line);
|
||||
ADD_TRACE(mpctx->mctx, item, mpctx->size, file, line);
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -1102,7 +1147,7 @@ isc__mempool_put(isc_mempool_t *restrict mpctx, void *mem FLARG) {
|
||||
INSIST(mpctx->allocated > 0);
|
||||
mpctx->allocated--;
|
||||
|
||||
DELETE_TRACE(mctx, mem, mpctx->size, func, file, line);
|
||||
DELETE_TRACE(mctx, mem, mpctx->size, file, line);
|
||||
|
||||
/*
|
||||
* If our free list is full, return this to the mctx directly.
|
||||
@@ -1437,8 +1482,8 @@ isc__mem_create(isc_mem_t **mctxp FLARG) {
|
||||
mem_create(mctxp, isc_mem_debugging, isc_mem_defaultflags, 0);
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0) {
|
||||
fprintf(stderr, "create mctx %p func %s file %s line %u\n",
|
||||
*mctxp, func, file, line);
|
||||
fprintf(stderr, "create mctx %p file %s line %u\n", *mctxp,
|
||||
file, line);
|
||||
}
|
||||
#endif /* ISC_MEM_TRACKLINES */
|
||||
}
|
||||
@@ -1464,9 +1509,9 @@ isc__mem_create_arena(isc_mem_t **mctxp FLARG) {
|
||||
#if ISC_MEM_TRACKLINES
|
||||
if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0) {
|
||||
fprintf(stderr,
|
||||
"create mctx %p func %s file %s line %u "
|
||||
"for jemalloc arena %u\n",
|
||||
*mctxp, func, file, line, arena_no);
|
||||
"create mctx %p file %s line %u for jemalloc arena "
|
||||
"%u\n",
|
||||
*mctxp, file, line, arena_no);
|
||||
}
|
||||
#endif /* ISC_MEM_TRACKLINES */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <isc/mutexblock.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
void
|
||||
isc_mutexblock_init(isc_mutex_t *block, unsigned int count) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
isc_mutex_init(&block[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc_mutexblock_destroy(isc_mutex_t *block, unsigned int count) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
isc_mutex_destroy(&block[i]);
|
||||
}
|
||||
}
|
||||
+57
-67
@@ -150,7 +150,7 @@ typedef struct http_cstream {
|
||||
|
||||
isc_nm_http_response_status_t response_status;
|
||||
isc_nmsocket_t *httpsock;
|
||||
ISC_LINK(struct http_cstream) link;
|
||||
LINK(struct http_cstream) link;
|
||||
} http_cstream_t;
|
||||
|
||||
#define HTTP2_SESSION_MAGIC ISC_MAGIC('H', '2', 'S', 'S')
|
||||
@@ -190,8 +190,6 @@ struct isc_nm_http_session {
|
||||
|
||||
size_t data_in_flight;
|
||||
|
||||
bool async_queued;
|
||||
|
||||
/*
|
||||
* The statistical values below are for usage on server-side
|
||||
* only. They are meant to detect clients that are taking too many
|
||||
@@ -1295,10 +1293,7 @@ http_readcb(isc_nmhandle_t *handle ISC_ATTR_UNUSED, isc_result_t result,
|
||||
}
|
||||
isc_buffer_putmem(session->buf, region->base + readlen,
|
||||
unread_size);
|
||||
if (session->handle != NULL) {
|
||||
INSIST(VALID_NMHANDLE(session->handle));
|
||||
isc_nm_read_stop(session->handle);
|
||||
}
|
||||
isc_nm_read_stop(session->handle);
|
||||
http_do_bio_async(session);
|
||||
} else {
|
||||
/* We might have something to receive or send, do IO */
|
||||
@@ -1467,27 +1462,26 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
|
||||
* to avoid hitting unnecessary limitations on a TLS record size
|
||||
* within some tools (e.g. flamethrower).
|
||||
*/
|
||||
if (cb != NULL) {
|
||||
if (max_total_write_size >= FLUSH_HTTP_WRITE_BUFFER_AFTER) {
|
||||
/*
|
||||
* Case 0: The callback is specified, that means that a DNS
|
||||
* message is ready. Let's flush the the buffer.
|
||||
*/
|
||||
total = max_total_write_size;
|
||||
} else if (max_total_write_size >= FLUSH_HTTP_WRITE_BUFFER_AFTER) {
|
||||
/*
|
||||
* Case 1: We have equal or more than
|
||||
* FLUSH_HTTP_WRITE_BUFFER_AFTER bytes to send. Let's flush it.
|
||||
* Case 1: We have at least FLUSH_HTTP_WRITE_BUFFER_AFTER
|
||||
* bytes to send. Let's flush it.
|
||||
*/
|
||||
total = max_total_write_size;
|
||||
} else if (session->sending > 0 && total > 0) {
|
||||
/*
|
||||
* Case 2: There is one or more write requests in flight and
|
||||
* we have some new data form nghttp2 to send.
|
||||
* Then let's return from the function: as soon as the
|
||||
* we have some new data form nghttp2 to send. Let's put the
|
||||
* write callback (if any) into the pending write callbacks
|
||||
* list. Then let's return from the function: as soon as the
|
||||
* "in-flight" write callback get's called or we have reached
|
||||
* FLUSH_HTTP_WRITE_BUFFER_AFTER bytes in the write buffer, we
|
||||
* will flush the buffer. */
|
||||
INSIST(cb == NULL);
|
||||
* will flush the buffer.
|
||||
*/
|
||||
if (cb != NULL) {
|
||||
http_append_pending_send_request(session, httphandle,
|
||||
cb, cbarg);
|
||||
}
|
||||
goto nothing_to_send;
|
||||
} else if (session->sending == 0 && total == 0 &&
|
||||
session->pending_write_data != NULL)
|
||||
@@ -1522,6 +1516,8 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
|
||||
(total == 0 && session->sending == 0) ||
|
||||
(total > 0 && session->sending == 0));
|
||||
}
|
||||
#else
|
||||
INSIST(ISC_LIST_EMPTY(session->pending_write_callbacks));
|
||||
#endif /* ENABLE_HTTP_WRITE_BUFFERING */
|
||||
|
||||
if (total == 0) {
|
||||
@@ -1583,7 +1579,7 @@ http_too_many_active_streams(isc_nm_http_session_t *session) {
|
||||
*/
|
||||
const uint64_t max_active_streams =
|
||||
ISC_MAX(ISC_NETMGR_MAX_STREAM_CLIENTS_PER_CONN,
|
||||
(session->max_concurrent_streams * 6) / 10); /* 60% */
|
||||
session->max_concurrent_streams / 3);
|
||||
|
||||
if (session->client) {
|
||||
return false;
|
||||
@@ -1603,12 +1599,10 @@ http_too_many_active_streams(isc_nm_http_session_t *session) {
|
||||
static void
|
||||
http_do_bio(isc_nm_http_session_t *session, isc_nmhandle_t *send_httphandle,
|
||||
isc_nm_cb_t send_cb, void *send_cbarg) {
|
||||
isc__nm_uvreq_t *req = NULL;
|
||||
size_t remaining = 0;
|
||||
REQUIRE(VALID_HTTP2_SESSION(session));
|
||||
|
||||
if (session->closed) {
|
||||
goto cancel;
|
||||
return;
|
||||
} else if (session->closing) {
|
||||
/*
|
||||
* There might be leftover callbacks waiting to be received
|
||||
@@ -1616,24 +1610,23 @@ http_do_bio(isc_nm_http_session_t *session, isc_nmhandle_t *send_httphandle,
|
||||
if (session->sending == 0) {
|
||||
finish_http_session(session);
|
||||
}
|
||||
goto cancel;
|
||||
} else if (nghttp2_session_want_read(session->ngsession) == 0 &&
|
||||
nghttp2_session_want_write(session->ngsession) == 0 &&
|
||||
session->pending_write_data == NULL)
|
||||
{
|
||||
session->closing = true;
|
||||
if (session->handle != NULL) {
|
||||
isc_nm_read_stop(session->handle);
|
||||
}
|
||||
if (session->sending == 0) {
|
||||
finish_http_session(session);
|
||||
}
|
||||
goto cancel;
|
||||
return;
|
||||
}
|
||||
|
||||
else if (session->buf != NULL)
|
||||
{
|
||||
remaining = isc_buffer_remaininglength(session->buf);
|
||||
if (send_cb != NULL) {
|
||||
INSIST(VALID_NMHANDLE(send_httphandle));
|
||||
http_send_outgoing(session, send_httphandle, send_cb,
|
||||
send_cbarg);
|
||||
return;
|
||||
}
|
||||
|
||||
INSIST(send_httphandle == NULL);
|
||||
INSIST(send_cb == NULL);
|
||||
INSIST(send_cbarg == NULL);
|
||||
|
||||
if (session->pending_write_data != NULL && session->sending == 0) {
|
||||
http_send_outgoing(session, NULL, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nghttp2_session_want_read(session->ngsession) != 0) {
|
||||
@@ -1642,7 +1635,9 @@ http_do_bio(isc_nm_http_session_t *session, isc_nmhandle_t *send_httphandle,
|
||||
isc__nmsocket_timer_start(session->handle->sock);
|
||||
isc_nm_read(session->handle, http_readcb, session);
|
||||
session->reading = true;
|
||||
} else if (session->buf != NULL && remaining > 0) {
|
||||
} else if (session->buf != NULL) {
|
||||
size_t remaining =
|
||||
isc_buffer_remaininglength(session->buf);
|
||||
/* Leftover data in the buffer, use it */
|
||||
size_t remaining_after = 0;
|
||||
ssize_t readlen = 0;
|
||||
@@ -1666,12 +1661,8 @@ http_do_bio(isc_nm_http_session_t *session, isc_nmhandle_t *send_httphandle,
|
||||
http_log_flooding_peer(session);
|
||||
failed_read_cb(ISC_R_RANGE, session);
|
||||
} else if ((size_t)readlen == remaining) {
|
||||
isc_buffer_clear(session->buf);
|
||||
isc_buffer_compact(session->buf);
|
||||
http_do_bio(session, send_httphandle, send_cb,
|
||||
send_cbarg);
|
||||
isc__nm_httpsession_detach(&tmpsess);
|
||||
return;
|
||||
isc_buffer_free(&session->buf);
|
||||
http_do_bio(session, NULL, NULL, NULL);
|
||||
} else if (remaining_after > 0 &&
|
||||
remaining_after < remaining)
|
||||
{
|
||||
@@ -1688,36 +1679,39 @@ http_do_bio(isc_nm_http_session_t *session, isc_nmhandle_t *send_httphandle,
|
||||
* it and that could overwhelm the server.
|
||||
*/
|
||||
http_do_bio_async(session);
|
||||
} else {
|
||||
http_send_outgoing(session, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
isc__nm_httpsession_detach(&tmpsess);
|
||||
} else if (session->handle != NULL) {
|
||||
INSIST(VALID_NMHANDLE(session->handle));
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* Resume reading, it's idempotent, wait for more
|
||||
*/
|
||||
isc__nmsocket_timer_start(session->handle->sock);
|
||||
isc_nm_read(session->handle, http_readcb, session);
|
||||
}
|
||||
} else if (session->handle != NULL) {
|
||||
INSIST(VALID_NMHANDLE(session->handle));
|
||||
} else {
|
||||
/* We don't want more data, stop reading for now */
|
||||
isc_nm_read_stop(session->handle);
|
||||
}
|
||||
|
||||
/* we might have some data to send after processing */
|
||||
http_send_outgoing(session, send_httphandle, send_cb, send_cbarg);
|
||||
http_send_outgoing(session, NULL, NULL, NULL);
|
||||
|
||||
if (nghttp2_session_want_read(session->ngsession) == 0 &&
|
||||
nghttp2_session_want_write(session->ngsession) == 0 &&
|
||||
session->pending_write_data == NULL)
|
||||
{
|
||||
session->closing = true;
|
||||
isc_nm_read_stop(session->handle);
|
||||
if (session->sending == 0) {
|
||||
finish_http_session(session);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
cancel:
|
||||
if (send_cb == NULL) {
|
||||
return;
|
||||
}
|
||||
req = isc__nm_uvreq_get(send_httphandle->sock);
|
||||
|
||||
req->cb.send = send_cb;
|
||||
req->cbarg = send_cbarg;
|
||||
isc_nmhandle_attach(send_httphandle, &req->handle);
|
||||
isc__nm_sendcb(send_httphandle->sock, req, ISC_R_CANCELED, true);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1726,8 +1720,6 @@ http_do_bio_async_cb(void *arg) {
|
||||
|
||||
REQUIRE(VALID_HTTP2_SESSION(session));
|
||||
|
||||
session->async_queued = false;
|
||||
|
||||
if (session->handle != NULL &&
|
||||
!isc__nmsocket_closing(session->handle->sock))
|
||||
{
|
||||
@@ -1744,12 +1736,10 @@ http_do_bio_async(isc_nm_http_session_t *session) {
|
||||
REQUIRE(VALID_HTTP2_SESSION(session));
|
||||
|
||||
if (session->handle == NULL ||
|
||||
isc__nmsocket_closing(session->handle->sock) ||
|
||||
session->async_queued)
|
||||
isc__nmsocket_closing(session->handle->sock))
|
||||
{
|
||||
return;
|
||||
}
|
||||
session->async_queued = true;
|
||||
isc__nm_httpsession_attach(session, &tmpsess);
|
||||
isc_async_run(session->handle->sock->worker->loop, http_do_bio_async_cb,
|
||||
tmpsess);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/barrier.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/dnsstream.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
@@ -270,8 +271,8 @@ struct isc_nmhandle {
|
||||
void *backtrace[TRACE_SIZE];
|
||||
int backtrace_size;
|
||||
#endif
|
||||
ISC_LINK(isc_nmhandle_t) active_link;
|
||||
ISC_LINK(isc_nmhandle_t) inactive_link;
|
||||
LINK(isc_nmhandle_t) active_link;
|
||||
LINK(isc_nmhandle_t) inactive_link;
|
||||
|
||||
void *opaque;
|
||||
|
||||
@@ -422,7 +423,7 @@ typedef struct isc_nm_httphandler {
|
||||
char *path;
|
||||
isc_nm_recv_cb_t cb;
|
||||
void *cbarg;
|
||||
ISC_LINK(struct isc_nm_httphandler) link;
|
||||
LINK(struct isc_nm_httphandler) link;
|
||||
} isc_nm_httphandler_t;
|
||||
|
||||
struct isc_nm_http_endpoints {
|
||||
@@ -466,7 +467,7 @@ typedef struct isc_nmsocket_h2 {
|
||||
|
||||
isc_nm_recv_cb_t cb;
|
||||
void *cbarg;
|
||||
ISC_LINK(struct isc_nmsocket_h2) link;
|
||||
LINK(struct isc_nmsocket_h2) link;
|
||||
|
||||
isc_nm_http_endpoints_t **listener_endpoints;
|
||||
size_t n_listener_endpoints;
|
||||
@@ -712,7 +713,7 @@ struct isc_nmsocket {
|
||||
void *backtrace[TRACE_SIZE];
|
||||
int backtrace_size;
|
||||
#endif
|
||||
ISC_LINK(isc_nmsocket_t) active_link;
|
||||
LINK(isc_nmsocket_t) active_link;
|
||||
|
||||
isc_job_t job;
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <isc/backtrace.h>
|
||||
#include <isc/barrier.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/errno.h>
|
||||
#include <isc/job.h>
|
||||
#include <isc/list.h>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/barrier.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/errno.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/magic.h>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <isc/async.h>
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/barrier.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/errno.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
|
||||
@@ -231,7 +231,7 @@ isc__ratelimiter_tick(void *arg) {
|
||||
REQUIRE(rl->timer != NULL);
|
||||
|
||||
if (rl->state == isc_ratelimiter_shuttingdown) {
|
||||
INSIST(ISC_LIST_EMPTY(rl->pending));
|
||||
INSIST(EMPTY(rl->pending));
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ isc__ratelimiter_doshutdown(void *arg) {
|
||||
|
||||
LOCK(&rl->lock);
|
||||
INSIST(rl->state == isc_ratelimiter_shuttingdown);
|
||||
INSIST(ISC_LIST_EMPTY(rl->pending));
|
||||
INSIST(EMPTY(rl->pending));
|
||||
|
||||
isc_timer_stop(rl->timer);
|
||||
isc_timer_destroy(&rl->timer);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <isc/async.h>
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/condition.h>
|
||||
#include <isc/heap.h>
|
||||
#include <isc/job.h>
|
||||
#include <isc/log.h>
|
||||
|
||||
@@ -35,11 +35,13 @@
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/ht.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/mutexblock.h>
|
||||
#include <isc/once.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/refcount.h>
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ void
|
||||
isc__uv_shutdown(void) {
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 38, 0)
|
||||
uv_library_shutdown();
|
||||
isc_mem_detach(&isc__uv_mctx);
|
||||
isc_mem_destroy(&isc__uv_mctx);
|
||||
#endif /* UV_VERSION_HEX < UV_VERSION(1, 38, 0) */
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <isc/iterated_hash.h>
|
||||
#include <isc/job.h>
|
||||
#include <isc/loop.h>
|
||||
#include <isc/urcu.h>
|
||||
@@ -26,15 +25,11 @@ static void
|
||||
isc__work_cb(uv_work_t *req) {
|
||||
isc_work_t *work = uv_req_get_data((uv_req_t *)req);
|
||||
|
||||
isc__iterated_hash_initialize();
|
||||
|
||||
rcu_register_thread();
|
||||
|
||||
work->work_cb(work->cbarg);
|
||||
|
||||
rcu_unregister_thread();
|
||||
|
||||
isc__iterated_hash_shutdown();
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ void
|
||||
isc__xml_shutdown(void) {
|
||||
#ifdef HAVE_LIBXML2
|
||||
xmlCleanupParser();
|
||||
isc_mem_detach(&isc__xml_mctx);
|
||||
isc_mem_destroy(&isc__xml_mctx);
|
||||
#endif /* HAVE_LIBXML2 */
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <isc/crypto.h>
|
||||
#include <isc/fips.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/region.h>
|
||||
@@ -227,7 +227,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (check_algorithms && isc_crypto_fips_mode() &&
|
||||
if (check_algorithms && isc_fips_mode() &&
|
||||
(key->algorithm == DNS_KEYALG_RSASHA1 ||
|
||||
key->algorithm == DNS_KEYALG_NSEC3RSASHA1))
|
||||
{
|
||||
@@ -259,7 +259,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
||||
case DNS_KEYALG_NSEC3RSASHA1:
|
||||
case DNS_KEYALG_RSASHA256:
|
||||
case DNS_KEYALG_RSASHA512:
|
||||
if (isc_crypto_fips_mode()) {
|
||||
if (isc_fips_mode()) {
|
||||
min = 2048;
|
||||
} else {
|
||||
min = DNS_KEYALG_RSASHA512 ? 1024 : 512;
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ struct ns_plugin {
|
||||
ns_plugin_check_t *check_func;
|
||||
ns_plugin_register_t *register_func;
|
||||
ns_plugin_destroy_t *destroy_func;
|
||||
ISC_LINK(ns_plugin_t) link;
|
||||
LINK(ns_plugin_t) link;
|
||||
};
|
||||
|
||||
static ns_hooklist_t default_hooktable[NS_HOOKPOINTS_COUNT];
|
||||
|
||||
+1
-4
@@ -7757,10 +7757,7 @@ query_respond_any(query_ctx_t *qctx) {
|
||||
}
|
||||
|
||||
qctx->rpz_st = qctx->client->query.rpz_st;
|
||||
if (qctx->rpz_st != NULL &&
|
||||
qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
|
||||
qctx->rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU)
|
||||
{
|
||||
if (qctx->rpz_st != NULL) {
|
||||
qctx->rdataset->ttl =
|
||||
ISC_MIN(qctx->rdataset->ttl,
|
||||
qctx->rpz_st->m.ttl);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user