resolved: apparently not all names are used in canonical form for DNSSEC validation

Specifically, it appears as if the NSEC next domain name should be in
the original casing rather than canonical form, when validating.
This commit is contained in:
Lennart Poettering 2015-12-11 20:19:05 +01:00
parent 654d1b3350
commit a3db237b8f
3 changed files with 116 additions and 13 deletions

View File

@ -438,10 +438,15 @@ int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_
return 0;
}
int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) {
uint8_t *w;
int r;
/* Append a label to a packet. Optionally, does this in DNSSEC
* canonical form, if this label is marked as a candidate for
* it, and the canonical form logic is enabled for the
* packet */
assert(p);
assert(d);
@ -454,7 +459,7 @@ int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start
*(w++) = (uint8_t) l;
if (p->canonical_form) {
if (p->canonical_form && canonical_candidate) {
size_t i;
/* Generate in canonical form, as defined by DNSSEC
@ -479,6 +484,7 @@ int dns_packet_append_name(
DnsPacket *p,
const char *name,
bool allow_compression,
bool canonical_candidate,
size_t *start) {
size_t saved_size;
@ -533,7 +539,7 @@ int dns_packet_append_name(
if (k > 0)
r = k;
r = dns_packet_append_label(p, label, r, &n);
r = dns_packet_append_label(p, label, r, canonical_candidate, &n);
if (r < 0)
goto fail;
@ -574,7 +580,7 @@ int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start)
saved_size = p->size;
r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, true, NULL);
if (r < 0)
goto fail;
@ -762,14 +768,14 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
if (r < 0)
goto fail;
r = dns_packet_append_name(p, rr->srv.name, true, NULL);
r = dns_packet_append_name(p, rr->srv.name, true, false, NULL);
break;
case DNS_TYPE_PTR:
case DNS_TYPE_NS:
case DNS_TYPE_CNAME:
case DNS_TYPE_DNAME:
r = dns_packet_append_name(p, rr->ptr.name, true, NULL);
r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL);
break;
case DNS_TYPE_HINFO:
@ -812,11 +818,11 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
break;
case DNS_TYPE_SOA:
r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL);
if (r < 0)
goto fail;
r = dns_packet_append_name(p, rr->soa.rname, true, NULL);
r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL);
if (r < 0)
goto fail;
@ -844,7 +850,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
if (r < 0)
goto fail;
r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL);
break;
case DNS_TYPE_LOC:
@ -948,7 +954,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
if (r < 0)
goto fail;
r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
if (r < 0)
goto fail;
@ -956,7 +962,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
break;
case DNS_TYPE_NSEC:
r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, NULL);
r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
if (r < 0)
goto fail;

View File

@ -169,8 +169,8 @@ int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start);
int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start);
int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start);
int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start);
int dns_packet_append_label(DnsPacket *p, const char *s, size_t l, size_t *start);
int dns_packet_append_name(DnsPacket *p, const char *name, bool allow_compression, size_t *start);
int dns_packet_append_label(DnsPacket *p, const char *s, size_t l, bool canonical_candidate, size_t *start);
int dns_packet_append_name(DnsPacket *p, const char *name, bool allow_compression, bool canonical_candidate, size_t *start);
int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, size_t *start);
int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start);
int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start);

View File

@ -28,6 +28,102 @@
#include "resolved-dns-rr.h"
#include "string-util.h"
static void test_dnssec_verify_rrset2(void) {
static const uint8_t signature_blob[] = {
0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11,
0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b,
0xa7, 0x5c, 0x83, 0x39, 0x8c, 0x28, 0xac, 0xce, 0x6e, 0x9c, 0x18, 0xe3, 0x31, 0x16, 0x6e, 0xca,
0x38, 0x31, 0xaf, 0xd9, 0x94, 0xf1, 0x84, 0xb1, 0xdf, 0x5a, 0xc2, 0x73, 0x22, 0xf6, 0xcb, 0xa2,
0xe7, 0x8c, 0x77, 0x0c, 0x74, 0x2f, 0xc2, 0x13, 0xb0, 0x93, 0x51, 0xa9, 0x4f, 0xae, 0x0a, 0xda,
0x45, 0xcc, 0xfd, 0x43, 0x99, 0x36, 0x9a, 0x0d, 0x21, 0xe0, 0xeb, 0x30, 0x65, 0xd4, 0xa0, 0x27,
0x37, 0x3b, 0xe4, 0xc1, 0xc5, 0xa1, 0x2a, 0xd1, 0x76, 0xc4, 0x7e, 0x64, 0x0e, 0x5a, 0xa6, 0x50,
0x24, 0xd5, 0x2c, 0xcc, 0x6d, 0xe5, 0x37, 0xea, 0xbd, 0x09, 0x34, 0xed, 0x24, 0x06, 0xa1, 0x22,
};
static const uint8_t dnskey_blob[] = {
0x03, 0x01, 0x00, 0x01, 0xc3, 0x7f, 0x1d, 0xd1, 0x1c, 0x97, 0xb1, 0x13, 0x34, 0x3a, 0x9a, 0xea,
0xee, 0xd9, 0x5a, 0x11, 0x1b, 0x17, 0xc7, 0xe3, 0xd4, 0xda, 0x20, 0xbc, 0x5d, 0xba, 0x74, 0xe3,
0x37, 0x99, 0xec, 0x25, 0xce, 0x93, 0x7f, 0xbd, 0x22, 0x73, 0x7e, 0x14, 0x71, 0xe0, 0x60, 0x07,
0xd4, 0x39, 0x8b, 0x5e, 0xe9, 0xba, 0x25, 0xe8, 0x49, 0xe9, 0x34, 0xef, 0xfe, 0x04, 0x5c, 0xa5,
0x27, 0xcd, 0xa9, 0xda, 0x70, 0x05, 0x21, 0xab, 0x15, 0x82, 0x24, 0xc3, 0x94, 0xf5, 0xd7, 0xb7,
0xc4, 0x66, 0xcb, 0x32, 0x6e, 0x60, 0x2b, 0x55, 0x59, 0x28, 0x89, 0x8a, 0x72, 0xde, 0x88, 0x56,
0x27, 0x95, 0xd9, 0xac, 0x88, 0x4f, 0x65, 0x2b, 0x68, 0xfc, 0xe6, 0x41, 0xc1, 0x1b, 0xef, 0x4e,
0xd6, 0xc2, 0x0f, 0x64, 0x88, 0x95, 0x5e, 0xdd, 0x3a, 0x02, 0x07, 0x50, 0xa9, 0xda, 0xa4, 0x49,
0x74, 0x62, 0xfe, 0xd7,
};
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *nsec = NULL, *rrsig = NULL, *dnskey = NULL;
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
_cleanup_free_ char *x = NULL, *y = NULL, *z = NULL;
DnssecResult result;
nsec = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC, "nasa.gov");
assert_se(nsec);
nsec->nsec.next_domain_name = strdup("3D-Printing.nasa.gov");
assert_se(nsec->nsec.next_domain_name);
nsec->nsec.types = bitmap_new();
assert_se(nsec->nsec.types);
assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_A) >= 0);
assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NS) >= 0);
assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_SOA) >= 0);
assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_MX) >= 0);
assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_TXT) >= 0);
assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_RRSIG) >= 0);
assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NSEC) >= 0);
assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_DNSKEY) >= 0);
assert_se(bitmap_set(nsec->nsec.types, 65534) >= 0);
assert_se(dns_resource_record_to_string(nsec, &x) >= 0);
log_info("NSEC: %s", x);
rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
assert_se(rrsig);
rrsig->rrsig.type_covered = DNS_TYPE_NSEC;
rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256;
rrsig->rrsig.labels = 2;
rrsig->rrsig.original_ttl = 300;
rrsig->rrsig.expiration = 0x5689002f;
rrsig->rrsig.inception = 0x56617230;
rrsig->rrsig.key_tag = 30390;
rrsig->rrsig.signer = strdup("Nasa.Gov.");
assert_se(rrsig->rrsig.signer);
rrsig->rrsig.signature_size = sizeof(signature_blob);
rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size);
assert_se(rrsig->rrsig.signature);
assert_se(dns_resource_record_to_string(rrsig, &y) >= 0);
log_info("RRSIG: %s", y);
dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
assert_se(dnskey);
dnskey->dnskey.flags = 256;
dnskey->dnskey.protocol = 3;
dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
dnskey->dnskey.key_size = sizeof(dnskey_blob);
dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
assert_se(dnskey->dnskey.key);
assert_se(dns_resource_record_to_string(dnskey, &z) >= 0);
log_info("DNSKEY: %s", z);
log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey));
assert_se(dnssec_key_match_rrsig(nsec->key, rrsig) > 0);
assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey) > 0);
answer = dns_answer_new(1);
assert_se(answer);
assert_se(dns_answer_add(answer, nsec, 0) >= 0);
/* Validate the RR as it if was 2015-12-11 today */
assert_se(dnssec_verify_rrset(answer, nsec->key, rrsig, dnskey, 1449849318*USEC_PER_SEC, &result) >= 0);
assert_se(result == DNSSEC_VALIDATED);
}
static void test_dnssec_verify_rrset(void) {
static const uint8_t signature_blob[] = {
@ -214,6 +310,7 @@ int main(int argc, char*argv[]) {
test_dnssec_canonicalize();
test_dnssec_verify_dns_key();
test_dnssec_verify_rrset();
test_dnssec_verify_rrset2();
return 0;
}