Implement SKR import
When 'rndc skr import' is called, read the file contents and store the
data in the zone's skr structure.
(cherry picked from commit 037382c4a5)
This commit is contained in:
+9
-2
@@ -16751,8 +16751,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__)
|
||||
|
||||
+279
-12
@@ -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,160 @@ 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_lctx, 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_lctx, 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_lctx, 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) {
|
||||
@@ -5734,6 +5746,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));
|
||||
@@ -24229,3 +24256,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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user