From 5d45a8808431987c370706d365fb0cc95cf03d52 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Mon, 13 Jul 2015 01:51:03 +0200 Subject: [PATCH] resolved: rr - add NSEC3 support Needed for DNSSEC. --- src/resolve/resolved-dns-packet.c | 106 +++++++++++++++++++++++++++--- src/resolve/resolved-dns-packet.h | 2 + src/resolve/resolved-dns-rr.c | 46 +++++++++++++ src/resolve/resolved-dns-rr.h | 11 ++++ 4 files changed, 157 insertions(+), 8 deletions(-) diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index d2b3cb0eb1b..e44d3926d9b 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -824,6 +824,40 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star if (r < 0) goto fail; + break; + case DNS_TYPE_NSEC3: + r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_types(p, rr->nsec3.types, NULL); + if (r < 0) + goto fail; + break; case _DNS_TYPE_INVALID: /* unparseable */ default: @@ -1560,6 +1594,60 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { } break; + + case DNS_TYPE_NSEC3: { + uint8_t size; + + r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL); + if (r < 0) + goto fail; + + r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL); + if (r < 0) + goto fail; + + r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL); + if (r < 0) + goto fail; + + r = dns_packet_read_uint8(p, &size, NULL); + if (r < 0) + goto fail; + + rr->nsec3.salt_size = size; + + r = dns_packet_read_blob(p, &d, rr->nsec3.salt_size, NULL); + if (r < 0) + goto fail; + + rr->nsec3.salt = memdup(d, rr->nsec3.salt_size); + if (!rr->nsec3.salt) { + r = -ENOMEM; + goto fail; + } + + r = dns_packet_read_uint8(p, &size, NULL); + if (r < 0) + goto fail; + + rr->nsec3.next_hashed_name_size = size; + + r = dns_packet_read(p, rr->nsec3.next_hashed_name_size, &d, NULL); + if (r < 0) + goto fail; + + rr->nsec3.next_hashed_name = memdup(d, rr->nsec3.next_hashed_name_size); + if (!rr->nsec3.next_hashed_name) { + r = -ENOMEM; + goto fail; + } + + r = dns_packet_append_types(p, rr->nsec3.types, NULL); + if (r < 0) + goto fail; + + break; + } default: unparseable: r = dns_packet_read(p, rdlength, &d, NULL); @@ -1694,13 +1782,15 @@ static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = { DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol); static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = { - [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5", - [DNSSEC_ALGORITHM_DH] = "DH", - [DNSSEC_ALGORITHM_DSA] = "DSA", - [DNSSEC_ALGORITHM_ECC] = "ECC", - [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1", - [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT", - [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS", - [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID", + [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5", + [DNSSEC_ALGORITHM_DH] = "DH", + [DNSSEC_ALGORITHM_DSA] = "DSA", + [DNSSEC_ALGORITHM_ECC] = "ECC", + [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1", + [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1", + [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1", + [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT", + [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS", + [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID", }; DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int); diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index 6588ed9df52..58559c85df4 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -223,6 +223,8 @@ enum { DNSSEC_ALGORITHM_DSA, DNSSEC_ALGORITHM_ECC, DNSSEC_ALGORITHM_RSASHA1, + DNSSEC_ALGORITHM_DSA_NSEC3_SHA1, + DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1, DNSSEC_ALGORITHM_INDIRECT = 252, DNSSEC_ALGORITHM_PRIVATEDNS, DNSSEC_ALGORITHM_PRIVATEOID, diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 48fb3538ae7..e9907eabc02 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -293,6 +293,12 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) { bitmap_free(rr->nsec.types); break; + case DNS_TYPE_NSEC3: + free(rr->nsec3.next_hashed_name); + free(rr->nsec3.salt); + bitmap_free(rr->nsec3.types); + break; + case DNS_TYPE_LOC: case DNS_TYPE_A: case DNS_TYPE_AAAA: @@ -457,6 +463,15 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) && bitmap_equal(a->nsec.types, b->nsec.types); + case DNS_TYPE_NSEC3: + return a->nsec3.algorithm == b->nsec3.algorithm && + a->nsec3.flags == b->nsec3.flags && + a->nsec3.iterations == b->nsec3.iterations && + a->nsec3.salt_size == b->nsec3.salt_size && + memcmp(a->nsec3.salt, b->nsec3.salt, a->nsec3.salt_size) == 0 && + memcmp(a->nsec3.next_hashed_name, b->nsec3.next_hashed_name, a->nsec3.next_hashed_name_size) == 0 && + bitmap_equal(a->nsec3.types, b->nsec3.types); + default: return a->generic.size == b->generic.size && memcmp(a->generic.data, b->generic.data, a->generic.size) == 0; @@ -757,6 +772,37 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) { return -ENOMEM; break; + case DNS_TYPE_NSEC3: { + _cleanup_free_ char *salt = NULL, *hash = NULL; + + if (rr->nsec3.salt_size) { + salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size); + if (!salt) + return -ENOMEM; + } + + hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false); + if (!hash) + return -ENOMEM; + + t = format_types(rr->nsec3.types); + if (!t) + return -ENOMEM; + + r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s", + k, + rr->nsec3.algorithm, + rr->nsec3.flags, + rr->nsec3.iterations, + rr->nsec3.salt_size ? salt : "-", + hash, + t); + if (r < 0) + return -ENOMEM; + + break; + } + default: t = hexmem(rr->generic.data, rr->generic.size); if (!t) diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h index eaaafb1f254..bdd5a5c8249 100644 --- a/src/resolve/resolved-dns-rr.h +++ b/src/resolve/resolved-dns-rr.h @@ -151,6 +151,17 @@ struct DnsResourceRecord { char *next_domain_name; Bitmap *types; } nsec; + + struct { + uint8_t algorithm; + uint8_t flags; + uint16_t iterations; + void *salt; + size_t salt_size; + void *next_hashed_name; + size_t next_hashed_name_size; + Bitmap *types; + } nsec3; }; }; -- 2.39.2