mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-15 22:09:31 -04:00
Implement SKR import
When 'rndc skr import' is called, read the file contents and store the data in the zone's skr structure.
This commit is contained in:
parent
445722d2bf
commit
037382c4a5
5 changed files with 357 additions and 39 deletions
|
|
@ -16715,8 +16715,15 @@ named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
CHECK(putstr(text, "import command not implemented"));
|
||||
CHECK(putnull(text));
|
||||
result = dns_zone_import_skr(zone, skrfile);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CHECK(putstr(text, "import failed: "));
|
||||
CHECK(putstr(text, isc_result_totext(result)));
|
||||
CHECK(putnull(text));
|
||||
} else {
|
||||
/* Schedule a rekey */
|
||||
dns_zone_rekey(zone, false);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (zone != NULL) {
|
||||
|
|
|
|||
|
|
@ -54,26 +54,6 @@ struct dns_skrbundle {
|
|||
ISC_LINK(dns_skrbundle_t) link;
|
||||
};
|
||||
|
||||
void
|
||||
dns_skrbundle_create(isc_mem_t *mctx, dns_name_t *name,
|
||||
dns_rdataclass_t rdclass, isc_stdtime_t inception,
|
||||
dns_skrbundle_t **bp);
|
||||
/*%<
|
||||
* Create a single bundle.
|
||||
*
|
||||
* Requires:
|
||||
* \li *bp != NULL && *bp == NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_skrbundle_addtuple(dns_skrbundle_t *bundle, dns_difftuple_t **tuple);
|
||||
/*%<
|
||||
* Add a single tuple to a key bundle.
|
||||
*
|
||||
* \li 'bundle' is a valid bundle
|
||||
* \li '*tuple' is a valid tuple
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_skrbundle_getsig(dns_skrbundle_t *bundle, dst_key_t *key,
|
||||
dns_rdatatype_t covering_type, dns_rdata_t *sigrdata);
|
||||
|
|
@ -101,14 +81,15 @@ dns_skr_create(isc_mem_t *mctx, const char *filename, dns_name_t *origin,
|
|||
* \li *skrp != NULL && *skrp == NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_skr_addbundle(dns_skr_t *skr, dns_skrbundle_t **bundlep);
|
||||
isc_result_t
|
||||
dns_skr_read(isc_mem_t *mctx, const char *filename, dns_name_t *origin,
|
||||
dns_rdataclass_t rdclass, dns_ttl_t dnskeyttl, dns_skr_t **skrp);
|
||||
/*%<
|
||||
* Add a single bundle to a SKR.
|
||||
* Read a SKR from 'filename'.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'skr' is a valid SKR
|
||||
* \li 'bundle' is a valid bundle
|
||||
* \li mctx != NULL
|
||||
* \li *skrp != NULL && *skrp == NULL
|
||||
*/
|
||||
|
||||
dns_skrbundle_t *
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <dns/masterdump.h>
|
||||
#include <dns/rdatastruct.h>
|
||||
#include <dns/rpz.h>
|
||||
#include <dns/skr.h>
|
||||
#include <dns/types.h>
|
||||
#include <dns/xfrin.h>
|
||||
#include <dns/zt.h>
|
||||
|
|
@ -2750,6 +2751,19 @@ dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db,
|
|||
* 'false' if the zone would have NSEC only DNSKEYs and an NSEC3 chain.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_zone_import_skr(dns_zone_t *zone, const char *file);
|
||||
/**<
|
||||
* Import a Signed Key Response (SKR) from file.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'zone' to be a valid zone.
|
||||
* \li 'file' is not NULL.
|
||||
*
|
||||
* Returns:
|
||||
* \li ISC_R_SUCCESS if there were no errors loading the SKR.
|
||||
*/
|
||||
|
||||
#if DNS_ZONE_TRACE
|
||||
#define dns_zone_ref(ptr) dns_zone__ref(ptr, __func__, __FILE__, __LINE__)
|
||||
#define dns_zone_unref(ptr) dns_zone__unref(ptr, __func__, __FILE__, __LINE__)
|
||||
|
|
|
|||
290
lib/dns/skr.c
290
lib/dns/skr.c
|
|
@ -13,19 +13,132 @@
|
|||
|
||||
/*! \file */
|
||||
|
||||
#include <dns/skr.h>
|
||||
#include <isc/lex.h>
|
||||
#include <isc/log.h>
|
||||
|
||||
void
|
||||
dns_skrbundle_create(isc_mem_t *mctx, dns_name_t *name,
|
||||
dns_rdataclass_t rdclass, isc_stdtime_t inception,
|
||||
dns_skrbundle_t **bp) {
|
||||
#include <dns/callbacks.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdataclass.h>
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/skr.h>
|
||||
#include <dns/time.h>
|
||||
#include <dns/ttl.h>
|
||||
|
||||
#define CHECK(op) \
|
||||
do { \
|
||||
result = (op); \
|
||||
if (result != ISC_R_SUCCESS) \
|
||||
goto failure; \
|
||||
} while (0)
|
||||
|
||||
#define READLINE(lex, opt, token)
|
||||
|
||||
#define NEXTTOKEN(lex, opt, token) \
|
||||
{ \
|
||||
ret = isc_lex_gettoken(lex, opt, token); \
|
||||
if (ret != ISC_R_SUCCESS) \
|
||||
goto cleanup; \
|
||||
}
|
||||
|
||||
#define BADTOKEN() \
|
||||
{ \
|
||||
ret = ISC_R_UNEXPECTEDTOKEN; \
|
||||
goto cleanup; \
|
||||
}
|
||||
|
||||
#define TOKENSIZ (8 * 1024)
|
||||
#define STR(t) ((t).value.as_textregion.base)
|
||||
|
||||
static isc_result_t
|
||||
parse_rr(isc_lex_t *lex, isc_mem_t *mctx, char *owner, dns_name_t *origin,
|
||||
dns_rdataclass_t rdclass, isc_buffer_t *buf, dns_ttl_t *ttl,
|
||||
dns_rdatatype_t *rdtype, dns_rdata_t **rdata) {
|
||||
dns_rdatacallbacks_t callbacks;
|
||||
dns_fixedname_t dfname;
|
||||
dns_name_t *dname = NULL;
|
||||
dns_rdataclass_t clas;
|
||||
isc_buffer_t b;
|
||||
isc_token_t token;
|
||||
unsigned int opt = ISC_LEXOPT_EOL;
|
||||
isc_result_t ret = ISC_R_SUCCESS;
|
||||
|
||||
isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
|
||||
|
||||
/* Read the domain name */
|
||||
if (!strcmp(owner, "@")) {
|
||||
BADTOKEN();
|
||||
}
|
||||
dname = dns_fixedname_initname(&dfname);
|
||||
isc_buffer_init(&b, owner, strlen(owner));
|
||||
isc_buffer_add(&b, strlen(owner));
|
||||
ret = dns_name_fromtext(dname, &b, dns_rootname, 0, NULL);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
return (ret);
|
||||
}
|
||||
if (dns_name_compare(dname, origin) != 0) {
|
||||
return (DNS_R_BADOWNERNAME);
|
||||
}
|
||||
isc_buffer_clear(&b);
|
||||
|
||||
/* Read the next word: either TTL, class, or type */
|
||||
NEXTTOKEN(lex, opt, &token);
|
||||
if (token.type != isc_tokentype_string) {
|
||||
BADTOKEN();
|
||||
}
|
||||
|
||||
/* If it's a TTL, read the next one */
|
||||
ret = dns_ttl_fromtext(&token.value.as_textregion, ttl);
|
||||
if (ret == ISC_R_SUCCESS) {
|
||||
NEXTTOKEN(lex, opt, &token);
|
||||
}
|
||||
if (token.type != isc_tokentype_string) {
|
||||
BADTOKEN();
|
||||
}
|
||||
|
||||
/* If it's a class, read the next one */
|
||||
ret = dns_rdataclass_fromtext(&clas, &token.value.as_textregion);
|
||||
if (ret == ISC_R_SUCCESS) {
|
||||
if (clas != rdclass) {
|
||||
BADTOKEN();
|
||||
}
|
||||
NEXTTOKEN(lex, opt, &token);
|
||||
}
|
||||
if (token.type != isc_tokentype_string) {
|
||||
BADTOKEN();
|
||||
}
|
||||
|
||||
/* Must be the record type */
|
||||
ret = dns_rdatatype_fromtext(rdtype, &token.value.as_textregion);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
BADTOKEN();
|
||||
}
|
||||
switch (*rdtype) {
|
||||
case dns_rdatatype_dnskey:
|
||||
case dns_rdatatype_cdnskey:
|
||||
case dns_rdatatype_cds:
|
||||
case dns_rdatatype_rrsig:
|
||||
/* Allowed record types */
|
||||
break;
|
||||
default:
|
||||
BADTOKEN();
|
||||
}
|
||||
|
||||
dns_rdatacallbacks_init(&callbacks);
|
||||
ret = dns_rdata_fromtext(*rdata, rdclass, *rdtype, lex, dname, 0, mctx,
|
||||
buf, &callbacks);
|
||||
cleanup:
|
||||
isc_lex_setcomments(lex, 0);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
skrbundle_create(isc_mem_t *mctx, isc_stdtime_t inception,
|
||||
dns_skrbundle_t **bp) {
|
||||
dns_skrbundle_t *b;
|
||||
|
||||
REQUIRE(bp != NULL && *bp == NULL);
|
||||
|
||||
UNUSED(name);
|
||||
UNUSED(rdclass);
|
||||
|
||||
b = isc_mem_get(mctx, sizeof(*b));
|
||||
b->magic = DNS_SKRBUNDLE_MAGIC;
|
||||
b->inception = inception;
|
||||
|
|
@ -36,8 +149,8 @@ dns_skrbundle_create(isc_mem_t *mctx, dns_name_t *name,
|
|||
*bp = b;
|
||||
}
|
||||
|
||||
void
|
||||
dns_skrbundle_addtuple(dns_skrbundle_t *bundle, dns_difftuple_t **tuple) {
|
||||
static void
|
||||
skrbundle_addtuple(dns_skrbundle_t *bundle, dns_difftuple_t **tuple) {
|
||||
REQUIRE(DNS_DIFFTUPLE_VALID(*tuple));
|
||||
REQUIRE(DNS_SKRBUNDLE_VALID(bundle));
|
||||
REQUIRE(DNS_DIFF_VALID(&bundle->diff));
|
||||
|
|
@ -116,8 +229,8 @@ dns_skr_create(isc_mem_t *mctx, const char *filename, dns_name_t *origin,
|
|||
*skrp = skr;
|
||||
}
|
||||
|
||||
void
|
||||
dns_skr_addbundle(dns_skr_t *skr, dns_skrbundle_t **bundlep) {
|
||||
static void
|
||||
addbundle(dns_skr_t *skr, dns_skrbundle_t **bundlep) {
|
||||
REQUIRE(DNS_SKR_VALID(skr));
|
||||
REQUIRE(DNS_SKRBUNDLE_VALID(*bundlep));
|
||||
|
||||
|
|
@ -125,6 +238,159 @@ dns_skr_addbundle(dns_skr_t *skr, dns_skrbundle_t **bundlep) {
|
|||
*bundlep = NULL;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_skr_read(isc_mem_t *mctx, const char *filename, dns_name_t *origin,
|
||||
dns_rdataclass_t rdclass, dns_ttl_t dnskeyttl, dns_skr_t **skrp) {
|
||||
isc_result_t result;
|
||||
dns_skrbundle_t *bundle = NULL;
|
||||
char bundlebuf[1024];
|
||||
uint32_t bundle_id;
|
||||
isc_lex_t *lex = NULL;
|
||||
isc_lexspecials_t specials;
|
||||
isc_token_t token;
|
||||
unsigned int opt = ISC_LEXOPT_EOL;
|
||||
|
||||
REQUIRE(DNS_SKR_VALID(*skrp));
|
||||
|
||||
isc_lex_create(mctx, TOKENSIZ, &lex);
|
||||
memset(specials, 0, sizeof(specials));
|
||||
specials['('] = 1;
|
||||
specials[')'] = 1;
|
||||
specials['"'] = 1;
|
||||
isc_lex_setspecials(lex, specials);
|
||||
result = isc_lex_openfile(lex, filename);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
|
||||
ISC_LOG_ERROR, "unable to open ksr file %s: %s",
|
||||
filename, isc_result_totext(result));
|
||||
isc_lex_destroy(&lex);
|
||||
return (result);
|
||||
}
|
||||
|
||||
for (result = isc_lex_gettoken(lex, opt, &token);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = isc_lex_gettoken(lex, opt, &token))
|
||||
{
|
||||
if (token.type == isc_tokentype_eol) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.type != isc_tokentype_string) {
|
||||
CHECK(DNS_R_SYNTAX);
|
||||
}
|
||||
|
||||
if (strcmp(STR(token), ";;") == 0) {
|
||||
/* New bundle */
|
||||
CHECK(isc_lex_gettoken(lex, opt, &token));
|
||||
if (token.type != isc_tokentype_string ||
|
||||
strcmp(STR(token), "SignedKeyResponse") != 0)
|
||||
{
|
||||
CHECK(DNS_R_SYNTAX);
|
||||
}
|
||||
|
||||
/* Version */
|
||||
CHECK(isc_lex_gettoken(lex, opt, &token));
|
||||
if (token.type != isc_tokentype_string ||
|
||||
strcmp(STR(token), "1.0") != 0)
|
||||
{
|
||||
CHECK(DNS_R_SYNTAX);
|
||||
}
|
||||
|
||||
/* Date and time of bundle */
|
||||
CHECK(isc_lex_gettoken(lex, opt, &token));
|
||||
if (token.type != isc_tokentype_string) {
|
||||
CHECK(DNS_R_SYNTAX);
|
||||
}
|
||||
if (strcmp(STR(token), "generated") == 0) {
|
||||
/* Final bundle */
|
||||
goto readline;
|
||||
}
|
||||
if (token.type != isc_tokentype_string) {
|
||||
CHECK(DNS_R_SYNTAX);
|
||||
}
|
||||
|
||||
/* Add previous bundle */
|
||||
if (bundle != NULL) {
|
||||
addbundle(*skrp, &bundle);
|
||||
}
|
||||
|
||||
/* Create new bundle */
|
||||
sscanf(STR(token), "%s", bundlebuf);
|
||||
CHECK(dns_time32_fromtext(bundlebuf, &bundle_id));
|
||||
bundle = NULL;
|
||||
skrbundle_create(mctx, (isc_stdtime_t)bundle_id,
|
||||
&bundle);
|
||||
|
||||
readline:
|
||||
/* Read remainder of header line */
|
||||
do {
|
||||
CHECK(isc_lex_gettoken(lex, opt, &token));
|
||||
} while (token.type != isc_tokentype_eol);
|
||||
} else {
|
||||
isc_buffer_t buf;
|
||||
dns_rdata_t *rdata = NULL;
|
||||
u_char rdatabuf[DST_KEY_MAXSIZE];
|
||||
dns_rdatatype_t rdtype;
|
||||
|
||||
/* Parse record */
|
||||
rdata = isc_mem_get(mctx, sizeof(*rdata));
|
||||
dns_rdata_init(rdata);
|
||||
isc_buffer_init(&buf, rdatabuf, sizeof(rdatabuf));
|
||||
result = parse_rr(lex, mctx, STR(token), origin,
|
||||
rdclass, &buf, &dnskeyttl, &rdtype,
|
||||
&rdata);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(
|
||||
DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(1),
|
||||
"read skr file %s(%lu) parse rr "
|
||||
"failed: %s",
|
||||
filename, isc_lex_getsourceline(lex),
|
||||
isc_result_totext(result));
|
||||
isc_mem_put(mctx, rdata, sizeof(*rdata));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Create new diff tuple */
|
||||
dns_diffop_t op = (rdtype == dns_rdatatype_rrsig)
|
||||
? DNS_DIFFOP_ADDRESIGN
|
||||
: DNS_DIFFOP_ADD;
|
||||
dns_difftuple_t *tuple = NULL;
|
||||
|
||||
dns_difftuple_create((*skrp)->mctx, op, origin,
|
||||
dnskeyttl, rdata, &tuple);
|
||||
|
||||
skrbundle_addtuple(bundle, &tuple);
|
||||
INSIST(tuple == NULL);
|
||||
|
||||
isc_mem_put(mctx, rdata, sizeof(*rdata));
|
||||
}
|
||||
}
|
||||
|
||||
if (result != ISC_R_EOF) {
|
||||
CHECK(DNS_R_SYNTAX);
|
||||
}
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
/* Add final bundle */
|
||||
if (bundle != NULL) {
|
||||
addbundle(*skrp, &bundle);
|
||||
}
|
||||
|
||||
failure:
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
|
||||
ISC_LOG_DEBUG(1),
|
||||
"read skr file %s(%lu) failed: %s", filename,
|
||||
isc_lex_getsourceline(lex),
|
||||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
isc_lex_destroy(&lex);
|
||||
return (result);
|
||||
}
|
||||
|
||||
dns_skrbundle_t *
|
||||
dns_skr_lookup(dns_skr_t *skr, isc_stdtime_t time, uint32_t sigval) {
|
||||
dns_skrbundle_t *b, *next;
|
||||
|
|
|
|||
|
|
@ -79,11 +79,13 @@
|
|||
#include <dns/request.h>
|
||||
#include <dns/resolver.h>
|
||||
#include <dns/rriterator.h>
|
||||
#include <dns/skr.h>
|
||||
#include <dns/soa.h>
|
||||
#include <dns/ssu.h>
|
||||
#include <dns/stats.h>
|
||||
#include <dns/time.h>
|
||||
#include <dns/tsig.h>
|
||||
#include <dns/ttl.h>
|
||||
#include <dns/update.h>
|
||||
#include <dns/xfrin.h>
|
||||
#include <dns/zone.h>
|
||||
|
|
@ -499,6 +501,12 @@ struct dns_zone {
|
|||
dns_update_state_t *rss_state;
|
||||
|
||||
isc_stats_t *gluecachestats;
|
||||
|
||||
/*%
|
||||
* Offline KSK signed key responses.
|
||||
*/
|
||||
dns_skr_t *skr;
|
||||
dns_skrbundle_t *skrbundle;
|
||||
};
|
||||
|
||||
#define zonediff_init(z, d) \
|
||||
|
|
@ -1273,6 +1281,10 @@ zone_free(dns_zone_t *zone) {
|
|||
if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
|
||||
clear_keylist(&zone->checkds_ok, zone->mctx);
|
||||
}
|
||||
if (zone->skr != NULL) {
|
||||
zone->skrbundle = NULL;
|
||||
dns_skr_detach(&zone->skr);
|
||||
}
|
||||
|
||||
zone->journalsize = -1;
|
||||
if (zone->journal != NULL) {
|
||||
|
|
@ -5731,6 +5743,21 @@ dns_zone_getkasp(dns_zone_t *zone) {
|
|||
return (kasp);
|
||||
}
|
||||
|
||||
static void
|
||||
dns_zone_setskr(dns_zone_t *zone, dns_skr_t *skr) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
LOCK_ZONE(zone);
|
||||
zone->skrbundle = NULL;
|
||||
if (zone->skr != NULL) {
|
||||
dns_skr_detach(&zone->skr);
|
||||
}
|
||||
if (skr != NULL) {
|
||||
dns_skr_attach(skr, &zone->skr);
|
||||
}
|
||||
UNLOCK_ZONE(zone);
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
|
@ -24219,3 +24246,26 @@ dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
|
|||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_zone_import_skr(dns_zone_t *zone, const char *file) {
|
||||
dns_skr_t *skr = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(zone->kasp != NULL);
|
||||
REQUIRE(file != NULL);
|
||||
|
||||
dns_skr_create(zone->mctx, file, &zone->origin, zone->rdclass, &skr);
|
||||
|
||||
CHECK(dns_skr_read(zone->mctx, file, &zone->origin, zone->rdclass,
|
||||
dns_kasp_dnskeyttl(zone->kasp), &skr));
|
||||
|
||||
dns_zone_setskr(zone, skr);
|
||||
dnssec_log(zone, ISC_LOG_DEBUG(1), "imported skr file %s", file);
|
||||
|
||||
failure:
|
||||
dns_skr_detach(&skr);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue