Compare commits

..
Author SHA1 Message Date
Evan Hunt 3878c145c9 experiment 2025-02-26 16:01:01 -08:00
Evan Hunt 4acbfbc2d1 retry fix 2025-02-26 16:01:01 -08:00
Evan Hunt 1ef9a32de7 slight refactoring in validated()
fix some minor code redundancies.
2025-02-26 15:28:57 -08:00
Evan Hunt 6c738fe323 simplify dns_ncache_add()
there's no longer any reason to have both dns_ncache_add() and
dns_ncache_addoptout().
2025-02-26 15:28:57 -08:00
115 changed files with 2280 additions and 2546 deletions
+86 -121
View File
@@ -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
+1 -1
View File
@@ -1 +1 @@
doc/arm/changelog.rst
CHANGES
+1 -1
View File
@@ -761,7 +761,7 @@ cleanup:
}
if (mctx != NULL) {
isc_mem_detach(&mctx);
isc_mem_destroy(&mctx);
}
return result == ISC_R_SUCCESS ? 0 : 1;
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -290,7 +290,7 @@ options {\n\
isc_mem_stats(mctx, stderr);
}
isc_mem_detach(&mctx);
isc_mem_destroy(&mctx);
return 0;
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+1
View File
@@ -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>
-8
View File
@@ -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)
+1 -1
View File
@@ -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);
}
}
+1 -1
View File
@@ -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)) {
+1 -1
View File
@@ -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)) {
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -248,7 +248,7 @@ cleanup:
if (dir != NULL) {
isc_mem_free(mctx, dir);
}
isc_mem_detach(&mctx);
isc_mem_destroy(&mctx);
return 0;
}
+1 -1
View File
@@ -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;
}
+40 -3
View File
@@ -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) {
+1 -1
View File
@@ -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;
}
+1
View File
@@ -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>
+1
View File
@@ -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);
/*
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+7 -16
View File
@@ -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("-"));
+3 -3
View File
@@ -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
}
-52
View File
@@ -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'
+27 -628
View File
@@ -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
+7 -6
View File
@@ -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}"
+41 -41
View File
@@ -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}"
-28
View File
@@ -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
View File
@@ -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}
-569
View File
@@ -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)
+55 -33
View File
@@ -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)
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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 ";
}
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -425,7 +425,7 @@ cleanup:
if (message != NULL) {
dns_message_detach(&message);
}
isc_mem_detach(&mctx);
isc_mem_destroy(&mctx);
exit(rv);
}
+1 -1
View File
@@ -61,7 +61,7 @@ cleanup(void) {
isc_lex_destroy(&lex);
}
if (mctx != NULL) {
isc_mem_detach(&mctx);
isc_mem_destroy(&mctx);
}
}
+25
View File
@@ -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
View File
@@ -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)) {
+1 -1
View File
@@ -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
View File
@@ -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++) {
+1 -1
View File
@@ -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;
}
+8
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+5 -10
View File
@@ -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.
+1 -1
View File
@@ -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'.
*
+9 -7
View File
@@ -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.
+3 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -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>
+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+45 -53
View File
@@ -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 */
+4 -23
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+6
View File
@@ -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 \
+1
View File
@@ -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>
+65
View File
@@ -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
View File
@@ -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
+55
View File
@@ -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
+1
View File
@@ -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>
+97
View File
@@ -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 *);
-14
View File
@@ -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
*/
+40
View File
@@ -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
View File
@@ -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);
-15
View File
@@ -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
+49
View File
@@ -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().
*
*/
+1 -37
View File
@@ -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;
-15
View File
@@ -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
+139
View File
@@ -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 */
+1
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
}
+35
View File
@@ -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
View File
@@ -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);
+6 -5
View File
@@ -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;
};
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+2 -2
View File
@@ -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);
+1
View File
@@ -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>
+2
View File
@@ -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
View File
@@ -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) */
}
-5
View File
@@ -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
View File
@@ -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 */
}
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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