From 484af99e820e570113e6bd3d849de1432822a7b6 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 19 Oct 2023 18:08:02 +0200 Subject: [PATCH] Add support for SIG and NXT RRs --- src/fallback/parser.c | 1 + src/generic/nxt.h | 61 +++++++++++++++++++++++++++++++++++++++++++ src/haswell/parser.c | 1 + src/types.h | 56 ++++++++++++++++++++++++++++++++++++--- src/westmere/parser.c | 1 + tests/types.c | 37 ++++++++++++++++++++++++++ 6 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 src/generic/nxt.h diff --git a/src/fallback/parser.c b/src/fallback/parser.c index f3e7716..9ef1543 100644 --- a/src/fallback/parser.c +++ b/src/fallback/parser.c @@ -24,6 +24,7 @@ #include "fallback/base32.h" #include "generic/base64.h" #include "generic/nsec.h" +#include "generic/nxt.h" #include "generic/caa.h" #include "generic/ilnp64.h" #include "fallback/eui.h" diff --git a/src/generic/nxt.h b/src/generic/nxt.h new file mode 100644 index 0000000..270eb7f --- /dev/null +++ b/src/generic/nxt.h @@ -0,0 +1,61 @@ +/* + * nxt.h + * + * Copyright (c) 2023, NLnet Labs. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef NXT_H +#define NXT_H + +zone_nonnull_all +static zone_really_inline int32_t scan_type( + zone_parser_t *parser, + const zone_type_info_t *type, + const zone_field_info_t *field, + const token_t *token, + uint16_t *code, + const zone_symbol_t **symbol); + +zone_nonnull_all +static zone_really_inline int32_t parse_nxt( + zone_parser_t *parser, + const zone_type_info_t *type, + const zone_field_info_t *field, + token_t *token) +{ + uint16_t code; + const zone_symbol_t *symbol; + + if (token->code == CONTIGUOUS) { + scan_type(parser, type, field, token, &code, &symbol); + int32_t result; + uint8_t bit = (uint8_t)(code % 8); + uint8_t block = (uint8_t)(code / 8), highest_block = block; + uint8_t *octets = &parser->rdata->octets[parser->rdata->length]; + + memset(octets, 0, block + 1); + octets[block] = (uint8_t)(1 << (7 - bit)); + + lex(parser, token); + while (token->code == CONTIGUOUS) { + if ((result = scan_type(parser, type, field, token, &code, &symbol)) < 0) + return result; + bit = (uint8_t)(code % 8); + block = (uint8_t)(code / 8); + if (block > highest_block) { + memset(&octets[highest_block+1], 0, block - highest_block); + highest_block = block; + } + octets[block] |= 1 << (7 - bit); + lex(parser, token); + } + + parser->rdata->length += highest_block + 1; + } + + return have_delimiter(parser, type, token); +} + +#endif // NXT_H diff --git a/src/haswell/parser.c b/src/haswell/parser.c index 18bbc9e..d9eef32 100644 --- a/src/haswell/parser.c +++ b/src/haswell/parser.c @@ -25,6 +25,7 @@ #include "haswell/base32.h" #include "generic/base64.h" #include "generic/nsec.h" +#include "generic/nxt.h" #include "generic/caa.h" #include "generic/ilnp64.h" #include "fallback/eui.h" diff --git a/src/types.h b/src/types.h index 3392491..99af88d 100644 --- a/src/types.h +++ b/src/types.h @@ -1074,6 +1074,37 @@ static int32_t parse_loc_rdata( return accept_rr(parser, type); } +zone_nonnull_all +static int32_t check_nxt_rr( + zone_parser_t *parser, const zone_type_info_t *type) +{ + int32_t r; + size_t c = 0; + const size_t n = parser->rdata->length; + const uint8_t *o = parser->rdata->octets; + const zone_field_info_t *f = type->rdata.fields; + + if ((r = check(&c, check_name(parser, type, &f[3], o+c, n-c)))) + return r; + + return accept_rr(parser, type); +} + +zone_nonnull_all +static int32_t parse_nxt_rdata( + zone_parser_t *parser, const zone_type_info_t *type, token_t *token) +{ + int32_t r; + + if ((r = parse_name(parser, type, &type->rdata.fields[0], token)) < 0) + return r; + lex(parser, token); + if ((r = parse_nxt(parser, type, &type->rdata.fields[1], token)) < 0) + return r; + + return accept_rr(parser, type); +} + zone_nonnull_all static int32_t check_srv_rr( zone_parser_t *parser, const zone_type_info_t *type) @@ -2295,6 +2326,11 @@ static const zone_field_info_t loc_rdata_fields[] = { FIELD("altitude", ZONE_INT32, 0) }; +static const zone_field_info_t nxt_rdata_fields[] = { + FIELD("next domain name", ZONE_NAME, 0), + FIELD("type bit map", 0, 0) +}; + static const zone_field_info_t srv_rdata_fields[] = { FIELD("priority", ZONE_INT16, 0), FIELD("weight", ZONE_INT16, 0), @@ -2349,6 +2385,18 @@ static const zone_symbol_t dnssec_algorithm_symbols[] = { SYMBOL("RSASHA512", 10) }; +static const zone_field_info_t sig_rdata_fields[] = { + FIELD("sigtype", ZONE_INT16, ZONE_TYPE), + FIELD("algorithm", ZONE_INT8, 0, SYMBOLS(dnssec_algorithm_symbols)), + FIELD("labels", ZONE_INT8, 0), + FIELD("origttl", ZONE_INT32, ZONE_TTL), + FIELD("expire", ZONE_INT32, ZONE_TIME), + FIELD("inception", ZONE_INT32, ZONE_TIME), + FIELD("keytag", ZONE_INT16, 0), + FIELD("signer", ZONE_NAME, 0), + FIELD("signature", ZONE_BLOB, ZONE_BASE64) +}; + static const zone_field_info_t cert_rdata_fields[] = { FIELD("type", ZONE_INT16, 0, SYMBOLS(cert_type_symbols)), FIELD("key tag", ZONE_INT16, 0), @@ -2599,9 +2647,8 @@ static const type_descriptor_t types[] = { check_nsap_rr, parse_nsap_rdata), TYPE("NSAP-PTR", ZONE_NSAP_PTR, ZONE_IN, FIELDS(nsap_ptr_rdata_fields), check_nsap_ptr_rr, parse_nsap_ptr_rdata), - - UNKNOWN_TYPE(24), - + TYPE("SIG", ZONE_SIG, ZONE_ANY, FIELDS(sig_rdata_fields), + check_rrsig_rr, parse_rrsig_rdata), TYPE("KEY", ZONE_KEY, ZONE_ANY, FIELDS(key_rdata_fields), check_key_rr, parse_key_rdata), TYPE("PX", ZONE_PX, ZONE_IN, FIELDS(px_rdata_fields), @@ -2612,8 +2659,9 @@ static const type_descriptor_t types[] = { check_aaaa_rr, parse_aaaa_rdata), TYPE("LOC", ZONE_LOC, ZONE_ANY, FIELDS(loc_rdata_fields), check_loc_rr, parse_loc_rdata), + TYPE("NXT", ZONE_NXT, ZONE_ANY | ZONE_OBSOLETE, FIELDS(nxt_rdata_fields), + check_nxt_rr, parse_nxt_rdata), - UNKNOWN_TYPE(30), UNKNOWN_TYPE(31), UNKNOWN_TYPE(32), diff --git a/src/westmere/parser.c b/src/westmere/parser.c index 0f56c07..0816fee 100644 --- a/src/westmere/parser.c +++ b/src/westmere/parser.c @@ -25,6 +25,7 @@ #include "westmere/base32.h" #include "generic/base64.h" #include "generic/nsec.h" +#include "generic/nxt.h" #include "generic/caa.h" #include "generic/ilnp64.h" #include "fallback/eui.h" diff --git a/tests/types.c b/tests/types.c index 4f3f673..17898c8 100644 --- a/tests/types.c +++ b/tests/types.c @@ -240,6 +240,35 @@ static const char nsap_ptr_text[] = static const rdata_t nsap_ptr_rdata = RDATA(4, 'h', 'o', 's', 't', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0); +static const char sig_text[] = + PAD("big.foo.tld. SIG NXT 1 3 ( ;type-cov=NXT, alg=1, labels=3\n" + " 3600 ;original ttl\n" + " 19960102030405 ;signature expiration\n" + " 19951211100908 ;time signed\n" + " 21435 ;key footprint\n" + " foo.tld. ;signer\n" + "MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6VAuHAoNUz4YoU\n" + "1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=\n" + ")"); +static const rdata_t sig_rdata = + RDATA(0, 30, // type covered + 1, // algorithm + 3, // labels + 0x00, 0x00, 0x0e, 0x10, // original ttl + 0x30, 0xe8, 0xa0, 0xa5, // signature + 0x30, 0xcc, 0x03, 0x44, // time signed + 0x53, 0xbb, // key footprint + 3, 'f', 'o', 'o', 3, 't', 'l', 'd', 0, // signer + // signature + 0x33, 0x11, 0x5c, 0x6f, 0x2f, 0x64, 0xff, 0x2b, 0xde, 0x74, + 0xc7, 0xd0, 0x80, 0xac, 0xe1, 0x1f, 0x97, 0xab, 0xd0, 0xcb, + 0xbf, 0xbc, 0x82, 0xf3, 0xe3, 0x92, 0x24, 0xb2, 0x47, 0x1e, + 0x14, 0x68, 0x22, 0x58, 0x29, 0xff, 0x1b, 0x11, 0xe1, 0x6a, + 0x2e, 0x95, 0x02, 0xe1, 0xc0, 0xa0, 0xd5, 0x33, 0xe1, 0x8a, + 0x14, 0xd6, 0xd5, 0x5f, 0x48, 0x24, 0xaa, 0x41, 0x89, 0xfa, + 0xff, 0xfd, 0x75, 0x53, 0xa3, 0x65, 0x77, 0xcd, 0x23, 0x11, + 0xe0, 0xbc, 0x69, 0x3a, 0xce, 0xf8, 0xa2, 0xa6, 0x09, 0xa6); + static const char key_text[] = PAD(" KEY 0 0 0 Zm9vYmFy"); static const char key_generic_text[] = @@ -283,6 +312,12 @@ static const rdata_t loc_rdata = 0x70, 0xbe, 0x15, 0xf0, // longitude 0x00, 0x98, 0x8d, 0x20); // altitude +static const char nxt_text[] = + PAD("big.foo.tld. NXT medium.foo.tld. A MX SIG NXT"); +static const rdata_t nxt_rdata = + RDATA(6, 'm', 'e', 'd', 'i', 'u', 'm', 3, 'f', 'o', 'o', 3, 't', 'l', 'd', 0, + 0x40, 0x01, 0x00, 0x82); + static const char naptr_text[] = PAD(" NAPTR 100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.gatech.edu."); static const char naptr_generic_text[] = @@ -821,12 +856,14 @@ static const test_t tests[] = { { ZONE_NSAP, nsap_text, &nsap_rdata }, { ZONE_NSAP, nsap_generic_text, &nsap_rdata }, { ZONE_NSAP_PTR, nsap_ptr_text, &nsap_ptr_rdata }, + { ZONE_SIG, sig_text, &sig_rdata }, { ZONE_KEY, key_text, &key_rdata }, { ZONE_KEY, key_generic_text, &key_rdata }, { ZONE_GPOS, gpos_text, &gpos_rdata }, { ZONE_PX, px_text, &px_rdata }, { ZONE_PX, px_generic_text, &px_rdata }, { ZONE_LOC, loc_text, &loc_rdata }, + { ZONE_NXT, nxt_text, &nxt_rdata }, { ZONE_NAPTR, naptr_text, &naptr_rdata }, { ZONE_NAPTR, naptr_generic_text, &naptr_rdata }, { ZONE_KX, kx_text, &kx_rdata },