mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 23:25:38 +00:00
Enable dns_zoneverify_dnssec() to check whether the zone was signed by a trust anchor
Extend check_dnskey_sigs() so that, if requested, it checks whether the DNSKEY RRset at zone apex is signed by at least one trust anchor. The trust anchor table is passed as an argument to dns_zoneverify_dnssec() and passed around in the verification context structure. Neither dnssec-signzone nor dnssec-verify are yet modified to make use of that feature, though.
This commit is contained in:
@@ -3916,7 +3916,7 @@ main(int argc, char *argv[]) {
|
|||||||
vresult = ISC_R_SUCCESS;
|
vresult = ISC_R_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
vresult = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin,
|
vresult = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin,
|
||||||
mctx, ignore_kskflag,
|
NULL, mctx, ignore_kskflag,
|
||||||
keyset_kskonly);
|
keyset_kskonly);
|
||||||
if (vresult != ISC_R_SUCCESS) {
|
if (vresult != ISC_R_SUCCESS) {
|
||||||
fprintf(output_stdout ? stderr : stdout,
|
fprintf(output_stdout ? stderr : stdout,
|
||||||
|
@@ -323,8 +323,8 @@ main(int argc, char *argv[]) {
|
|||||||
result = dns_db_newversion(gdb, &gversion);
|
result = dns_db_newversion(gdb, &gversion);
|
||||||
check_result(result, "dns_db_newversion()");
|
check_result(result, "dns_db_newversion()");
|
||||||
|
|
||||||
result = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin, mctx,
|
result = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin, NULL,
|
||||||
ignore_kskflag, keyset_kskonly);
|
mctx, ignore_kskflag, keyset_kskonly);
|
||||||
|
|
||||||
dns_db_closeversion(gdb, &gversion, ISC_FALSE);
|
dns_db_closeversion(gdb, &gversion, ISC_FALSE);
|
||||||
dns_db_detach(&gdb);
|
dns_db_detach(&gdb);
|
||||||
|
@@ -33,8 +33,8 @@ ISC_LANG_BEGINDECLS
|
|||||||
*/
|
*/
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
|
dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
|
||||||
dns_name_t *origin, isc_mem_t *mctx,
|
dns_name_t *origin, dns_keytable_t *secroots,
|
||||||
isc_boolean_t ignore_kskflag,
|
isc_mem_t *mctx, isc_boolean_t ignore_kskflag,
|
||||||
isc_boolean_t keyset_kskonly);
|
isc_boolean_t keyset_kskonly);
|
||||||
|
|
||||||
ISC_LANG_ENDDECLS
|
ISC_LANG_ENDDECLS
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include <dns/dbiterator.h>
|
#include <dns/dbiterator.h>
|
||||||
#include <dns/dnssec.h>
|
#include <dns/dnssec.h>
|
||||||
#include <dns/fixedname.h>
|
#include <dns/fixedname.h>
|
||||||
|
#include <dns/keytable.h>
|
||||||
#include <dns/keyvalues.h>
|
#include <dns/keyvalues.h>
|
||||||
#include <dns/log.h>
|
#include <dns/log.h>
|
||||||
#include <dns/name.h>
|
#include <dns/name.h>
|
||||||
@@ -56,6 +57,7 @@ typedef struct vctx {
|
|||||||
dns_db_t * db;
|
dns_db_t * db;
|
||||||
dns_dbversion_t * ver;
|
dns_dbversion_t * ver;
|
||||||
dns_name_t * origin;
|
dns_name_t * origin;
|
||||||
|
dns_keytable_t * secroots;
|
||||||
isc_boolean_t goodksk;
|
isc_boolean_t goodksk;
|
||||||
isc_boolean_t goodzsk;
|
isc_boolean_t goodzsk;
|
||||||
dns_rdataset_t keyset;
|
dns_rdataset_t keyset;
|
||||||
@@ -1315,7 +1317,7 @@ verifyemptynodes(const vctx_t *vctx, const dns_name_t *name,
|
|||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
vctx_init(vctx_t *vctx, isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
|
vctx_init(vctx_t *vctx, isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
|
||||||
dns_dbversion_t *ver, dns_name_t *origin)
|
dns_dbversion_t *ver, dns_name_t *origin, dns_keytable_t *secroots)
|
||||||
{
|
{
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
|
||||||
@@ -1326,6 +1328,7 @@ vctx_init(vctx_t *vctx, isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
|
|||||||
vctx->db = db;
|
vctx->db = db;
|
||||||
vctx->ver = ver;
|
vctx->ver = ver;
|
||||||
vctx->origin = origin;
|
vctx->origin = origin;
|
||||||
|
vctx->secroots = secroots;
|
||||||
vctx->goodksk = ISC_FALSE;
|
vctx->goodksk = ISC_FALSE;
|
||||||
vctx->goodzsk = ISC_FALSE;
|
vctx->goodzsk = ISC_FALSE;
|
||||||
|
|
||||||
@@ -1491,17 +1494,21 @@ check_apex_rrsets(vctx_t *vctx) {
|
|||||||
* Update 'vctx' tables tracking active and standby key algorithms used in the
|
* Update 'vctx' tables tracking active and standby key algorithms used in the
|
||||||
* verified zone based on the signatures made using 'dnskey' (prepared from
|
* verified zone based on the signatures made using 'dnskey' (prepared from
|
||||||
* 'rdata') found at zone apex. Set 'vctx->goodksk' or 'vctx->goodzsk' to true
|
* 'rdata') found at zone apex. Set 'vctx->goodksk' or 'vctx->goodzsk' to true
|
||||||
* if 'dnskey' correctly signs the DNSKEY RRset at zone apex.
|
* if 'dnskey' correctly signs the DNSKEY RRset at zone apex and either
|
||||||
|
* 'vctx->secroots' is NULL or 'dnskey' is present in 'vctx->secroots'.
|
||||||
*
|
*
|
||||||
* The variables to update are chosen based on 'is_ksk', which is true when
|
* The variables to update are chosen based on 'is_ksk', which is true when
|
||||||
* 'dnskey' is a KSK and false otherwise.
|
* 'dnskey' is a KSK and false otherwise.
|
||||||
*/
|
*/
|
||||||
static void
|
static isc_result_t
|
||||||
check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
|
check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
|
||||||
dns_rdata_t *rdata, isc_boolean_t is_ksk)
|
dns_rdata_t *rdata, isc_boolean_t is_ksk)
|
||||||
{
|
{
|
||||||
unsigned char *active_keys, *standby_keys;
|
unsigned char *active_keys, *standby_keys;
|
||||||
|
dns_keynode_t *keynode = NULL;
|
||||||
isc_boolean_t *goodkey;
|
isc_boolean_t *goodkey;
|
||||||
|
dst_key_t *key = NULL;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
active_keys = (is_ksk ? vctx->ksk_algorithms : vctx->zsk_algorithms);
|
active_keys = (is_ksk ? vctx->ksk_algorithms : vctx->zsk_algorithms);
|
||||||
standby_keys = (is_ksk ? vctx->standby_ksk : vctx->standby_zsk);
|
standby_keys = (is_ksk ? vctx->standby_ksk : vctx->standby_zsk);
|
||||||
@@ -1513,7 +1520,6 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
|
|||||||
if (active_keys[dnskey->algorithm] != 255) {
|
if (active_keys[dnskey->algorithm] != 255) {
|
||||||
active_keys[dnskey->algorithm]++;
|
active_keys[dnskey->algorithm]++;
|
||||||
}
|
}
|
||||||
*goodkey = ISC_TRUE;
|
|
||||||
} else if (!is_ksk &&
|
} else if (!is_ksk &&
|
||||||
dns_dnssec_signs(rdata, vctx->origin, &vctx->soaset,
|
dns_dnssec_signs(rdata, vctx->origin, &vctx->soaset,
|
||||||
&vctx->soasigs, ISC_FALSE, vctx->mctx))
|
&vctx->soasigs, ISC_FALSE, vctx->mctx))
|
||||||
@@ -1521,11 +1527,65 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
|
|||||||
if (active_keys[dnskey->algorithm] != 255) {
|
if (active_keys[dnskey->algorithm] != 255) {
|
||||||
active_keys[dnskey->algorithm]++;
|
active_keys[dnskey->algorithm]++;
|
||||||
}
|
}
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
if (standby_keys[dnskey->algorithm] != 255) {
|
if (standby_keys[dnskey->algorithm] != 255) {
|
||||||
standby_keys[dnskey->algorithm]++;
|
standby_keys[dnskey->algorithm]++;
|
||||||
}
|
}
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a trust anchor table was not supplied, a correctly self-signed
|
||||||
|
* DNSKEY RRset is good enough.
|
||||||
|
*/
|
||||||
|
if (vctx->secroots == NULL) {
|
||||||
|
*goodkey = ISC_TRUE;
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the supplied key in the trust anchor table.
|
||||||
|
*/
|
||||||
|
result = dns_dnssec_keyfromrdata(vctx->origin, rdata, vctx->mctx,
|
||||||
|
&key);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
result = dns_keytable_findkeynode(vctx->secroots, vctx->origin,
|
||||||
|
dst_key_alg(key), dst_key_id(key),
|
||||||
|
&keynode);
|
||||||
|
switch (result) {
|
||||||
|
case ISC_R_SUCCESS:
|
||||||
|
/*
|
||||||
|
* The supplied key is a trust anchor.
|
||||||
|
*/
|
||||||
|
dns_keytable_detachkeynode(vctx->secroots, &keynode);
|
||||||
|
*goodkey = ISC_TRUE;
|
||||||
|
break;
|
||||||
|
case DNS_R_PARTIALMATCH:
|
||||||
|
case ISC_R_NOTFOUND:
|
||||||
|
/*
|
||||||
|
* The supplied key is not present in the trust anchor table,
|
||||||
|
* but other keys signing the DNSKEY RRset may be, so this is
|
||||||
|
* not an error, we just do not set 'vctx->good[kz]sk'.
|
||||||
|
*/
|
||||||
|
result = ISC_R_SUCCESS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* An error occurred while searching the trust anchor table,
|
||||||
|
* return it to the caller.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up.
|
||||||
|
*/
|
||||||
|
dst_key_free(&key);
|
||||||
|
|
||||||
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
@@ -1914,14 +1974,15 @@ print_summary(const vctx_t *vctx, isc_boolean_t keyset_kskonly) {
|
|||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
|
dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
|
||||||
dns_name_t *origin, isc_mem_t *mctx,
|
dns_name_t *origin, dns_keytable_t *secroots,
|
||||||
isc_boolean_t ignore_kskflag,
|
isc_mem_t *mctx, isc_boolean_t ignore_kskflag,
|
||||||
isc_boolean_t keyset_kskonly)
|
isc_boolean_t keyset_kskonly)
|
||||||
{
|
{
|
||||||
|
const char *keydesc = (secroots == NULL ? "self-signed" : "trusted");
|
||||||
isc_result_t result, vresult = ISC_R_UNSET;
|
isc_result_t result, vresult = ISC_R_UNSET;
|
||||||
vctx_t vctx;
|
vctx_t vctx;
|
||||||
|
|
||||||
result = vctx_init(&vctx, mctx, zone, db, ver, origin);
|
result = vctx_init(&vctx, mctx, zone, db, ver, origin, secroots);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@@ -1938,13 +1999,13 @@ dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
|
|||||||
|
|
||||||
if (ignore_kskflag) {
|
if (ignore_kskflag) {
|
||||||
if (!vctx.goodksk && !vctx.goodzsk) {
|
if (!vctx.goodksk && !vctx.goodzsk) {
|
||||||
zoneverify_log_error(&vctx,
|
zoneverify_log_error(&vctx, "No %s DNSKEY found",
|
||||||
"No self-signed DNSKEY found");
|
keydesc);
|
||||||
result = ISC_R_FAILURE;
|
result = ISC_R_FAILURE;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
} else if (!vctx.goodksk) {
|
} else if (!vctx.goodksk) {
|
||||||
zoneverify_log_error(&vctx, "No self-signed KSK DNSKEY found");
|
zoneverify_log_error(&vctx, "No %s KSK DNSKEY found", keydesc);
|
||||||
result = ISC_R_FAILURE;
|
result = ISC_R_FAILURE;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user