From 54a4ab02eb14cb716e9d4739df1054fb1f04618c Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Tue, 25 Feb 2025 15:08:35 +0100 Subject: [PATCH] * Add ldns-verify-zone -s option. It checks all signature results, instead of passing by when one RRSIG validates. That prints output for spurious RRSIGs, the failures for them. --- Changelog | 3 +++ examples/ldns-verify-zone.1.in | 7 +++++++ examples/ldns-verify-zone.c | 20 ++++++++++++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index d4a294bd..19cfc4f1 100644 --- a/Changelog +++ b/Changelog @@ -13,6 +13,9 @@ window and the type modulo 256 is equal to zero. * Fix #271: Intermittent build failure with multi-job builds (make -j). + * Add ldns-verify-zone -s option. It checks all signature results, + instead of passing by when one RRSIG validates. That prints output + for spurious RRSIGs, the failures for them. 1.8.4 2024-07-19 * Fix building documentation in build directory. diff --git a/examples/ldns-verify-zone.1.in b/examples/ldns-verify-zone.1.in index 6bea57f0..ea232d71 100644 --- a/examples/ldns-verify-zone.1.in +++ b/examples/ldns-verify-zone.1.in @@ -48,6 +48,13 @@ Only check this percentage of the zone. Which names to check is determined randomly. Defaults to 100. +.TP +\fB-s\fR +Check all signature results, instead of one. Without the option one signature +that validates stops error output for the RRset. With the option, all +results from signature validations are printed. For spurious RRSIGs that +prints output for the spurious RRSIGs if they are wrong. + .TP \fB-S\fR Chase signature(s) to a known key. diff --git a/examples/ldns-verify-zone.c b/examples/ldns-verify-zone.c index ac076cd1..8bf00d51 100644 --- a/examples/ldns-verify-zone.c +++ b/examples/ldns-verify-zone.c @@ -26,6 +26,7 @@ static int32_t inception_offset = 0; static int32_t expiration_offset = 0; static bool do_sigchase = false; static bool no_nomatch_msg = false; +static int check_all_sigs = 0; static FILE* myout; static FILE* myerr; @@ -171,23 +172,32 @@ verify_rrs(ldns_rr_list* rrset_rrs, ldns_dnssec_rrs* cur_sig, ldns_rr_list* keys) { ldns_status status, result = LDNS_STATUS_OK; + int one_signature_verified = 0; ldns_dnssec_rrs *cur_sig_bak = cur_sig; + int is_dnskey_rrset = ldns_rr_list_rr_count(rrset_rrs) > 0 && + ldns_rr_get_type(ldns_rr_list_rr(rrset_rrs, 0)) == LDNS_RR_TYPE_DNSKEY; /* A single valid signature validates the RRset */ - while (cur_sig) { + /* With check all sigs, it skips this, except for the DNSKEY RRset. */ + if(!check_all_sigs || is_dnskey_rrset) { + while (cur_sig) { if (ldns_verify_rrsig_keylist_time( rrset_rrs, cur_sig->rr , keys, check_time, NULL) || rrsig_check_time_margins(cur_sig->rr)) cur_sig = cur_sig->next; else return LDNS_STATUS_OK; + } } /* Without any valid signature, do print all errors. */ + /* When checking all sigs, keep track if one is valid. */ for (cur_sig = cur_sig_bak; cur_sig; cur_sig = cur_sig->next) { status = ldns_verify_rrsig_keylist_time(rrset_rrs, cur_sig->rr, keys, check_time, NULL); status = status ? status : rrsig_check_time_margins(cur_sig->rr); + if(check_all_sigs && status == LDNS_STATUS_OK) + one_signature_verified += 1; if (!status) ; /* pass */ else if (!no_nomatch_msg || status != @@ -196,6 +206,8 @@ verify_rrs(ldns_rr_list* rrset_rrs, ldns_dnssec_rrs* cur_sig, myerr, rrset_rrs, status, cur_sig); update_error(&result, status); } + if(check_all_sigs && one_signature_verified) + return LDNS_STATUS_OK; return result; } @@ -712,6 +724,7 @@ static void print_usage(FILE *out, const char *progname) "\t\t\tDefault is %s\n", LDNS_TRUST_ANCHOR_FILE); fprintf(out, "\t-p [0-100]\tonly checks this percentage of " "the zone.\n\t\t\tDefaults to 100\n"); + fprintf(out, "\t-s\t\tcheck all signature results, instead of one.\n"); fprintf(out, "\t-S\t\tchase signature(s) to a known key. " "The network may be\n\t\t\taccessed to " "validate the zone's DNSKEYs. (implies -k)\n"); @@ -759,7 +772,7 @@ main(int argc, char **argv) myout = stdout; myerr = stderr; - while ((c = getopt(argc, argv, "ae:hi:k:vV:p:St:Z")) != -1) { + while ((c = getopt(argc, argv, "ae:hi:k:vV:p:sSt:Z")) != -1) { switch(c) { case 'a': apexonly = true; @@ -828,6 +841,9 @@ main(int argc, char **argv) } srandom(time(NULL) ^ getpid()); break; + case 's': + check_all_sigs = 1; + break; case 'S': do_sigchase = true; /* may chase */