resolved: store DNSKEY fields flags+protocol as-is
When verifying signatures we need to be able to verify the original data we got for an RR set, and that means we cannot simply drop flags bits or consider RRs invalid too eagerly. Hence, instead of parsing the DNSKEY flags store them as-is. Similar, accept the protocol field as it is, and don't consider it a parsing error if it is not 3. Of course, this means that the DNSKEY handling code later on needs to check explicit for protocol != 3.
This commit is contained in:
parent
e30ec345ac
commit
f91dc2400d
|
@ -826,11 +826,11 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
|
|||
break;
|
||||
|
||||
case DNS_TYPE_DNSKEY:
|
||||
r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
|
||||
r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dns_packet_append_uint8(p, 3u, NULL);
|
||||
r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -1412,17 +1412,6 @@ static bool loc_size_ok(uint8_t size) {
|
|||
return m <= 9 && e <= 9 && (m > 0 || e == 0);
|
||||
}
|
||||
|
||||
static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
|
||||
assert(rr);
|
||||
|
||||
if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
|
||||
return -EBADMSG;
|
||||
|
||||
rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
|
||||
rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
|
||||
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
|
||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
||||
|
@ -1691,28 +1680,15 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
|
|||
|
||||
break;
|
||||
|
||||
case DNS_TYPE_DNSKEY: {
|
||||
uint16_t flags;
|
||||
uint8_t proto;
|
||||
|
||||
r = dns_packet_read_uint16(p, &flags, NULL);
|
||||
case DNS_TYPE_DNSKEY:
|
||||
r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dnskey_parse_flags(rr, flags);
|
||||
r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dns_packet_read_uint8(p, &proto, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
/* protocol is required to be always 3 */
|
||||
if (proto != 3) {
|
||||
r = -EBADMSG;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
@ -1729,7 +1705,6 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
|
|||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DNS_TYPE_RRSIG:
|
||||
r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
|
||||
|
|
|
@ -223,15 +223,11 @@ DnsProtocol dns_protocol_from_string(const char *s) _pure_;
|
|||
#define LLMNR_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 252U) })
|
||||
#define LLMNR_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } })
|
||||
|
||||
#define DNSKEY_FLAG_ZONE_KEY (1u << 8)
|
||||
#define DNSKEY_FLAG_SEP (1u << 0)
|
||||
#define DNSKEY_FLAG_ZONE_KEY (UINT16_C(1) << 8)
|
||||
#define DNSKEY_FLAG_SEP (UINT16_C(1) << 0)
|
||||
|
||||
static inline uint16_t dnskey_to_flags(const DnsResourceRecord *rr) {
|
||||
return (rr->dnskey.zone_key_flag * DNSKEY_FLAG_ZONE_KEY |
|
||||
rr->dnskey.sep_flag * DNSKEY_FLAG_SEP);
|
||||
}
|
||||
|
||||
/* http://tools.ietf.org/html/rfc4034#appendix-A.1 */
|
||||
/* http://tools.ietf.org/html/rfc4034#appendix-A.1 and
|
||||
* https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
|
||||
enum {
|
||||
DNSSEC_ALGORITHM_RSAMD5 = 1,
|
||||
DNSSEC_ALGORITHM_DH,
|
||||
|
|
|
@ -576,8 +576,8 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
|
|||
memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0;
|
||||
|
||||
case DNS_TYPE_DNSKEY:
|
||||
return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
|
||||
a->dnskey.sep_flag == b->dnskey.sep_flag &&
|
||||
return a->dnskey.flags == b->dnskey.flags &&
|
||||
a->dnskey.protocol == b->dnskey.protocol &&
|
||||
a->dnskey.algorithm == b->dnskey.algorithm &&
|
||||
a->dnskey.key_size == b->dnskey.key_size &&
|
||||
memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
|
||||
|
@ -883,9 +883,10 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
|
|||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
r = asprintf(&s, "%s %u 3 %.*s%.*u %s",
|
||||
r = asprintf(&s, "%s %u %u %.*s%.*u %s",
|
||||
k,
|
||||
dnskey_to_flags(rr),
|
||||
rr->dnskey.flags,
|
||||
rr->dnskey.protocol,
|
||||
alg ? -1 : 0, alg,
|
||||
alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
|
||||
t);
|
||||
|
|
|
@ -135,8 +135,8 @@ struct DnsResourceRecord {
|
|||
|
||||
/* http://tools.ietf.org/html/rfc4034#section-2.1 */
|
||||
struct {
|
||||
bool zone_key_flag:1;
|
||||
bool sep_flag:1;
|
||||
uint16_t flags;
|
||||
uint8_t protocol;
|
||||
uint8_t algorithm;
|
||||
void* key;
|
||||
size_t key_size;
|
||||
|
|
Loading…
Reference in a new issue