diff --git a/CHANGES b/CHANGES index ab02767e73..1b2169e99b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +3639. [bug] Treat type 65533 (KEYDATA) as opaque except when used + in a key zone. [RT #34238] + 3638. [cleanup] Add the ability to handle ENOPROTOOPT in case it is encountered. [RT #34668] diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 05ba17fba3..43fcd74cc6 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -2282,6 +2282,17 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:check KEYDATA records are printed in human readable form in key zone ($n)" +# force the zone to be written out +$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns4 +ret=0 +grep KEYDATA ns4/managed-keys.bind > /dev/null || ret=1 +# restart the server +$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns4 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:check dig's +nocrypto flag ($n)" ret=0 $DIG $DIGOPTS +norec +nocrypto DNSKEY . \ diff --git a/bin/tests/system/genzone.sh b/bin/tests/system/genzone.sh index 8177093d47..1e90e0195f 100644 --- a/bin/tests/system/genzone.sh +++ b/bin/tests/system/genzone.sh @@ -294,4 +294,8 @@ eui64 EUI64 01-23-45-67-89-ab-cd-ef uri01 URI 10 20 "https://www.isc.org/" uri02 URI 30 40 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/" +keydata TYPE65533 \# 0 +keydata TYPE65533 \# 6 010203040506 +keydata TYPE65533 \# 18 010203040506010203040506010203040506 + EOF diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index cf3b238a47..762d96eeb3 100644 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -500,8 +500,8 @@ grep ANY typelist.out.T.${n} > /dev/null && { ret=1; echo "I: failed: ANY found grep ANY typelist.out.P.${n} > /dev/null && { ret=1; echo "I: failed: ANY found (-P)"; } grep ANY typelist.out.TP.${n} > /dev/null && { ret=1; echo "I: failed: ANY found (-TP)"; } grep KEYDATA typelist.out.T.${n} > /dev/null && { ret=1; echo "I: failed: KEYDATA found (-T)"; } -grep KEYDATA typelist.out.P.${n} > /dev/null || { ret=1; echo "I: failed: KEYDATA not found (-P)"; } -grep KEYDATA typelist.out.TP.${n} > /dev/null || { ret=1; echo "I: failed: KEYDATA not found (-TP)"; } +grep KEYDATA typelist.out.P.${n} > /dev/null && { ret=1; echo "I: failed: KEYDATA found (-P)"; } +grep KEYDATA typelist.out.TP.${n} > /dev/null && { ret=1; echo "I: failed: KEYDATA found (-TP)"; } grep AAAA typelist.out.T.${n} > /dev/null || { ret=1; echo "I: failed: AAAA not found (-T)"; } grep AAAA typelist.out.P.${n} > /dev/null && { ret=1; echo "I: failed: AAAA found (-P)"; } grep AAAA typelist.out.TP.${n} > /dev/null || { ret=1; echo "I: failed: AAAA not found (-TP)"; } diff --git a/bin/tests/system/xfer/dig1.good b/bin/tests/system/xfer/dig1.good index adfd6656fb..b10153ea38 100644 --- a/bin/tests/system/xfer/dig1.good +++ b/bin/tests/system/xfer/dig1.good @@ -29,6 +29,9 @@ isdn02.example. 3600 IN ISDN "isdn-address" "subaddress" isdn03.example. 3600 IN ISDN "isdn-address" isdn04.example. 3600 IN ISDN "isdn-address" "subaddress" dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +keydata.example. 3600 IN TYPE65533 \# 0 +keydata.example. 3600 IN TYPE65533 \# 6 010203040506 +keydata.example. 3600 IN TYPE65533 \# 18 010203040506010203040506010203040506 kx01.example. 3600 IN KX 10 kdc.example. kx02.example. 3600 IN KX 10 . loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m diff --git a/bin/tests/system/xfer/dig2.good b/bin/tests/system/xfer/dig2.good index 977720e54a..8b63816968 100644 --- a/bin/tests/system/xfer/dig2.good +++ b/bin/tests/system/xfer/dig2.good @@ -29,6 +29,9 @@ isdn04.example. 3600 IN ISDN "isdn-address" "subaddress" hip1.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D hip2.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com. dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +keydata.example. 3600 IN TYPE65533 \# 0 +keydata.example. 3600 IN TYPE65533 \# 6 010203040506 +keydata.example. 3600 IN TYPE65533 \# 18 010203040506010203040506010203040506 kx01.example. 3600 IN KX 10 kdc.example. kx02.example. 3600 IN KX 10 . loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m diff --git a/lib/dns/gen.c b/lib/dns/gen.c index 6b533dd23f..ba1379499a 100644 --- a/lib/dns/gen.c +++ b/lib/dns/gen.c @@ -779,6 +779,14 @@ main(int argc, char **argv) { ttn = find_typename(i); if (ttn == NULL) continue; + /* + * Remove KEYDATA (65533) from the type to memonic + * translation as it is internal use only. This + * stops the tools from displaying KEYDATA instead + * of TYPE65533. + */ + if (i == 65533U) + continue; fprintf(stdout, "\tcase %u: return " "(str_totext(\"%s\", target)); \\\n", i, upper(ttn->typename)); diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h index ea40d057e6..5fe69deb95 100644 --- a/lib/dns/include/dns/masterdump.h +++ b/lib/dns/include/dns/masterdump.h @@ -151,6 +151,11 @@ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_simple; */ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_debug; +/*% + * The style used for dumping "key" zones. + */ +LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_keyzone; + /*** *** Functions ***/ diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 89ecaf8006..872a490de6 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -171,6 +171,9 @@ struct dns_rdata { #define DNS_STYLEFLAG_COMMENT 0x00000002U #define DNS_STYLEFLAG_RRCOMMENT 0x00000004U +/*% Output KEYDATA in human readable format. */ +#define DNS_STYLEFLAG_KEYDATA 0x00000008U + #define DNS_RDATA_DOWNCASE DNS_NAME_DOWNCASE #define DNS_RDATA_CHECKNAMES DNS_NAME_CHECKNAMES #define DNS_RDATA_CHECKNAMESFAIL DNS_NAME_CHECKNAMESFAIL diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index 5fb06747aa..6086390f2e 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -100,6 +100,21 @@ typedef struct dns_totext_ctx { isc_boolean_t current_ttl_valid; } dns_totext_ctx_t; +LIBDNS_EXTERNAL_DATA const dns_master_style_t +dns_master_style_keyzone = { + DNS_STYLEFLAG_OMIT_OWNER | + DNS_STYLEFLAG_OMIT_CLASS | + DNS_STYLEFLAG_REL_OWNER | + DNS_STYLEFLAG_REL_DATA | + DNS_STYLEFLAG_OMIT_TTL | + DNS_STYLEFLAG_TTL | + DNS_STYLEFLAG_COMMENT | + DNS_STYLEFLAG_RRCOMMENT | + DNS_STYLEFLAG_MULTILINE | + DNS_STYLEFLAG_KEYDATA, + 24, 24, 24, 32, 80, 8, UINT_MAX +}; + LIBDNS_EXTERNAL_DATA const dns_master_style_t dns_master_style_default = { DNS_STYLEFLAG_OMIT_OWNER | @@ -504,9 +519,22 @@ rdataset_totext(dns_rdataset_t *rdataset, type_start = target->used; if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) RETERR(str_totext("\\-", target)); - result = dns_rdatatype_totext(type, target); - if (result != ISC_R_SUCCESS) - return (result); + switch (type) { + case dns_rdatatype_keydata: +#define KEYDATA "KEYDATA" + if ((ctx->style.flags & DNS_STYLEFLAG_KEYDATA) != 0) { + if (isc_buffer_availablelength(target) < + (sizeof(KEYDATA) - 1)) + return (ISC_R_NOSPACE); + isc_buffer_putstr(target, KEYDATA); + break; + } + /* FALLTHROUGH */ + default: + result = dns_rdatatype_totext(type, target); + if (result != ISC_R_SUCCESS) + return (result); + } column += (target->used - type_start); /* diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c index 03ad1ed738..a8be854ae9 100644 --- a/lib/dns/rdata/generic/keydata_65533.c +++ b/lib/dns/rdata/generic/keydata_65533.c @@ -21,7 +21,7 @@ #include -#define RRTYPE_KEYDATA_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) +#define RRTYPE_KEYDATA_ATTRIBUTES (0) static inline isc_result_t fromtext_keydata(ARGS_FROMTEXT) { @@ -102,7 +102,9 @@ totext_keydata(ARGS_TOTEXT) { const char *keyinfo; REQUIRE(rdata->type == 65533); - REQUIRE(rdata->length != 0); + + if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16) + return (unknown_totext(rdata, tctx, target)); dns_rdata_toregion(rdata, &sr); @@ -204,18 +206,6 @@ fromwire_keydata(ARGS_FROMWIRE) { UNUSED(options); isc_buffer_activeregion(source, &sr); - if (sr.length < 16) - return (ISC_R_UNEXPECTEDEND); - - /* - * RSAMD5 computes key ID differently from other - * algorithms: we need to ensure there's enough data - * present for the computation - */ - algorithm = sr.base[15]; - if (algorithm == DST_ALG_RSAMD5 && sr.length < 19) - return (ISC_R_UNEXPECTEDEND); - isc_buffer_forward(source, sr.length); return (mem_tobuffer(target, sr.base, sr.length)); } @@ -225,7 +215,6 @@ towire_keydata(ARGS_TOWIRE) { isc_region_t sr; REQUIRE(rdata->type == 65533); - REQUIRE(rdata->length != 0); UNUSED(cctx); @@ -241,8 +230,6 @@ compare_keydata(ARGS_COMPARE) { REQUIRE(rdata1->type == rdata2->type); REQUIRE(rdata1->rdclass == rdata2->rdclass); REQUIRE(rdata1->type == 65533); - REQUIRE(rdata1->length != 0); - REQUIRE(rdata2->length != 0); dns_rdata_toregion(rdata1, &r1); dns_rdata_toregion(rdata2, &r2); @@ -290,7 +277,6 @@ tostruct_keydata(ARGS_TOSTRUCT) { REQUIRE(rdata->type == 65533); REQUIRE(target != NULL); - REQUIRE(rdata->length != 0); keydata->common.rdclass = rdata->rdclass; keydata->common.rdtype = rdata->type; diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 94dd4baf09..47f6ee5b47 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -2117,15 +2117,20 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { INSIST(zone != zone->raw); ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); if (zone->db != NULL) { + const dns_master_style_t *output_style; + dns_db_currentversion(zone->db, &version); dns_master_initrawheader(&rawdata); if (inline_secure(zone)) get_raw_serial(zone->raw, &rawdata); + if (zone->type == dns_zone_key) + output_style = &dns_master_style_keyzone; + else + output_style = &dns_master_style_default; result = dns_master_dumpinc3(zone->mctx, zone->db, version, - &dns_master_style_default, - zone->masterfile, zone->task, - dump_done, zone, &zone->dctx, - zone->masterformat, &rawdata); + output_style, zone->masterfile, + zone->task, dump_done, zone, &zone->dctx, zone->masterformat, + &rawdata); dns_db_closeversion(zone->db, &version, ISC_FALSE); } else result = ISC_R_CANCELED; @@ -3572,6 +3577,8 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) { /* Convert rdata to keydata. */ result = dns_rdata_tostruct(&rdata, &keydata, NULL); + if (result == ISC_R_UNEXPECTEDEND) + continue; RUNTIME_CHECK(result == ISC_R_SUCCESS); /* Set the key refresh timer. */ @@ -8178,7 +8185,7 @@ zone_sign(dns_zone_t *zone) { isc_time_settoepoch(&zone->signingtime); } -static void +static isc_result_t normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data, int size) { dns_rdata_dnskey_t dnskey; @@ -8199,6 +8206,8 @@ normalize_key(dns_rdata_t *rr, dns_rdata_t *target, break; case dns_rdatatype_keydata: result = dns_rdata_tostruct(rr, &keydata, NULL); + if (result == ISC_R_UNEXPECTEDEND) + return (result); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_keydata_todnskey(&keydata, &dnskey, NULL); dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey, @@ -8207,6 +8216,7 @@ normalize_key(dns_rdata_t *rr, dns_rdata_t *target, default: INSIST(0); } + return (ISC_R_SUCCESS); } /* @@ -8230,14 +8240,18 @@ matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) { dns_rdata_init(&rdata1); dns_rdata_init(&rdata2); - normalize_key(rr, &rdata1, data1, sizeof(data1)); + result = normalize_key(rr, &rdata1, data1, sizeof(data1)); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdset)) { dns_rdata_reset(&rdata); dns_rdataset_current(rdset, &rdata); - normalize_key(&rdata, &rdata2, data2, sizeof(data2)); + result = normalize_key(&rdata, &rdata2, data2, sizeof(data2)); + if (result != ISC_R_SUCCESS) + continue; if (dns_rdata_compare(&rdata1, &rdata2) == 0) return (ISC_TRUE); } @@ -8344,7 +8358,11 @@ minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) name, 0, &rdata)); /* Update refresh timer */ - CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL)); + result = dns_rdata_tostruct(&rdata, &keydata, NULL); + if (result == ISC_R_UNEXPECTEDEND) + continue; + if (result != ISC_R_SUCCESS) + goto failure; keydata.refresh = refresh_time(kfetch, ISC_TRUE); set_refreshkeytimer(zone, &keydata, now); @@ -9574,15 +9592,20 @@ zone_dump(dns_zone_t *zone, isc_boolean_t compact) { result = DNS_R_CONTINUE; UNLOCK_ZONE(zone); } else { + const dns_master_style_t *output_style; + dns_masterrawheader_t rawdata; dns_db_currentversion(db, &version); dns_master_initrawheader(&rawdata); if (inline_secure(zone)) get_raw_serial(zone->raw, &rawdata); + if (zone->type == dns_zone_key) + output_style = &dns_master_style_keyzone; + else + output_style = &dns_master_style_default; result = dns_master_dump3(zone->mctx, db, version, - &dns_master_style_default, - masterfile, masterformat, - &rawdata); + output_style, masterfile, + masterformat, &rawdata); dns_db_closeversion(db, &version, ISC_FALSE); } fail: