From 38bad3e5b5d2d3914982f300641a375c9d1960da Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 3 Jul 2022 12:07:52 +0000 Subject: [PATCH] Implement SVCB and HTTPS record types. Testing caspar, otto OK otto --- usr.bin/dig/lib/dns/include/dns/types.h | 2 + usr.bin/dig/lib/dns/rdata.c | 8 +- usr.bin/dig/lib/dns/rdata/in_1/https_65.c | 50 ++++ usr.bin/dig/lib/dns/rdata/in_1/svcb_64.c | 309 ++++++++++++++++++++++ 4 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 usr.bin/dig/lib/dns/rdata/in_1/https_65.c create mode 100644 usr.bin/dig/lib/dns/rdata/in_1/svcb_64.c diff --git a/usr.bin/dig/lib/dns/include/dns/types.h b/usr.bin/dig/lib/dns/include/dns/types.h index a3b2f7e31f2..2a8738c6573 100644 --- a/usr.bin/dig/lib/dns/include/dns/types.h +++ b/usr.bin/dig/lib/dns/include/dns/types.h @@ -138,6 +138,8 @@ enum { dns_rdatatype_openpgpkey = 61, dns_rdatatype_csync = 62, dns_rdatatype_zonemd = 63, + dns_rdatatype_svcb = 64, + dns_rdatatype_https = 65, dns_rdatatype_spf = 99, dns_rdatatype_unspec = 103, dns_rdatatype_nid = 104, diff --git a/usr.bin/dig/lib/dns/rdata.c b/usr.bin/dig/lib/dns/rdata.c index 8f513d05354..acd7caa50db 100644 --- a/usr.bin/dig/lib/dns/rdata.c +++ b/usr.bin/dig/lib/dns/rdata.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.c,v 1.34 2022/06/25 12:14:18 jsg Exp $ */ +/* $Id: rdata.c,v 1.35 2022/07/03 12:07:52 florian Exp $ */ /*! \file */ @@ -774,6 +774,7 @@ dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) { {"gpos", 27}, {"hinfo", 13}, {"hip", 55}, + {"https", 65}, {"ipseckey", 45}, {"isdn", 20}, {"ixfr", 251}, @@ -821,6 +822,7 @@ dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) { {"spf", 99}, {"srv", 33}, {"sshfp", 44}, + {"svcb", 64}, {"ta", 32768}, {"talink", 58}, {"tkey", 249}, @@ -1005,6 +1007,10 @@ dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) { return (isc_str_tobuffer("CSYNC", target)); case 63: return (isc_str_tobuffer("ZONEMD", target)); + case 64: + return (isc_str_tobuffer("SVCB", target)); + case 65: + return (isc_str_tobuffer("HTTPS", target)); case 99: return (isc_str_tobuffer("SPF", target)); case 100: diff --git a/usr.bin/dig/lib/dns/rdata/in_1/https_65.c b/usr.bin/dig/lib/dns/rdata/in_1/https_65.c new file mode 100644 index 00000000000..a616c5e035b --- /dev/null +++ b/usr.bin/dig/lib/dns/rdata/in_1/https_65.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 Florian Obser + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: https_65.c,v 1.1 2022/07/03 12:07:52 florian Exp $ */ + +/* draft-ietf-dnsop-svcb-https-10 */ + +#ifndef RDATA_IN_1_HTTPS_65_C +#define RDATA_IN_1_HTTPS_65_C + +static inline isc_result_t +totext_in_https(ARGS_TOTEXT) { + REQUIRE(rdata->type == dns_rdatatype_https); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + return (totext_in_svcb_https(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_in_https(ARGS_FROMWIRE) { + REQUIRE(type == dns_rdatatype_https); + REQUIRE(rdclass == dns_rdataclass_in); + return (fromwire_in_svcb_https(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_in_https(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_https); + REQUIRE(rdata->length != 0); + + return (towire_in_svcb_https(rdata, cctx, target)); +} + + +#endif /* RDATA_IN_1_HTTPS_65_C */ diff --git a/usr.bin/dig/lib/dns/rdata/in_1/svcb_64.c b/usr.bin/dig/lib/dns/rdata/in_1/svcb_64.c new file mode 100644 index 00000000000..45edc92d563 --- /dev/null +++ b/usr.bin/dig/lib/dns/rdata/in_1/svcb_64.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2022 Florian Obser + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: svcb_64.c,v 1.1 2022/07/03 12:07:52 florian Exp $ */ + +/* draft-ietf-dnsop-svcb-https-10, based on srv_33.c */ + +#ifndef RDATA_IN_1_SVCB_64_C +#define RDATA_IN_1_SVCB_64_C + +#define SVC_PARAM_MANDATORY 0 +#define SVC_PARAM_ALPN 1 +#define SVC_PARAM_NO_DEF_ALPN 2 +#define SVC_PARAM_PORT 3 +#define SVC_PARAM_IPV4HINT 4 +#define SVC_PARAM_ECH 5 +#define SVC_PARAM_IPV6HINT 6 +#define SVC_PARAM_DOHPATH 7 + +static inline const char* +svc_param_key_to_text(uint16_t key) +{ + static char buf[sizeof "key65535"]; + + switch (key) { + case SVC_PARAM_MANDATORY: + return ("mandatory"); + case SVC_PARAM_ALPN: + return ("alpn"); + case SVC_PARAM_NO_DEF_ALPN: + return ("no-default-alpn"); + case SVC_PARAM_PORT: + return ("port"); + case SVC_PARAM_IPV4HINT: + return ("ipv4hint"); + case SVC_PARAM_ECH: + return ("ech"); + case SVC_PARAM_IPV6HINT: + return ("ipv6hint"); + case SVC_PARAM_DOHPATH: + return ("dohpath"); + default: + snprintf(buf, sizeof buf, "key%u", key); + return (buf); + } +} + +static inline isc_result_t +totext_in_svcb_https(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + int sub; + char buf[sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255"]; + unsigned short num; + + dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + + /* + * Priority. + */ + dns_rdata_toregion(rdata, ®ion); + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof buf, "%u", num); + RETERR(isc_str_tobuffer(buf, target)); + RETERR(isc_str_tobuffer(" ", target)); + + /* + * Target. + */ + dns_name_fromregion(&name, ®ion); + isc_region_consume(®ion, name_length(&name)); + sub = name_prefix(&name, tctx->origin, &prefix); + RETERR(dns_name_totext(&prefix, sub, target)); + + while (region.length > 0) { + isc_region_t val_region; + uint16_t svc_param_key, svc_param_value_len, man_key, port; + + RETERR(isc_str_tobuffer(" ", target)); + + svc_param_key = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + svc_param_value_len = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + + RETERR(isc_str_tobuffer(svc_param_key_to_text(svc_param_key), + target)); + + val_region = region; + val_region.length = svc_param_value_len; + + isc_region_consume(®ion, svc_param_value_len); + + switch (svc_param_key) { + case SVC_PARAM_MANDATORY: + INSIST(val_region.length % 2 == 0); + RETERR(isc_str_tobuffer("=", target)); + while (val_region.length > 0) { + man_key = uint16_fromregion(&val_region); + isc_region_consume(&val_region, 2); + RETERR(isc_str_tobuffer(svc_param_key_to_text( + man_key), target)); + if (val_region.length != 0) + RETERR(isc_str_tobuffer(",", target)); + } + break; + case SVC_PARAM_ALPN: + RETERR(isc_str_tobuffer("=\"", target)); + while (val_region.length > 0) { + txt_totext(&val_region, 0, target); + if (val_region.length != 0) + RETERR(isc_str_tobuffer(",", target)); + } + RETERR(isc_str_tobuffer("\"", target)); + break; + case SVC_PARAM_NO_DEF_ALPN: + INSIST(val_region.length == 0); + break; + case SVC_PARAM_PORT: + INSIST(val_region.length == 2); + RETERR(isc_str_tobuffer("=", target)); + port = uint16_fromregion(&val_region); + isc_region_consume(&val_region, 2); + snprintf(buf, sizeof buf, "%u", port); + RETERR(isc_str_tobuffer(buf, target)); + break; + case SVC_PARAM_IPV4HINT: + INSIST(val_region.length % 4 == 0); + RETERR(isc_str_tobuffer("=", target)); + while (val_region.length > 0) { + inet_ntop(AF_INET, val_region.base, buf, + sizeof buf); + RETERR(isc_str_tobuffer(buf, target)); + isc_region_consume(&val_region, 4); + if (val_region.length != 0) + RETERR(isc_str_tobuffer(",", target)); + } + break; + case SVC_PARAM_ECH: + RETERR(isc_str_tobuffer("=", target)); + RETERR(isc_base64_totext(&val_region, 0, "", target)); + break; + case SVC_PARAM_IPV6HINT: + INSIST(val_region.length % 16 == 0); + RETERR(isc_str_tobuffer("=", target)); + while (val_region.length > 0) { + inet_ntop(AF_INET6, val_region.base, buf, + sizeof buf); + RETERR(isc_str_tobuffer(buf, target)); + isc_region_consume(&val_region, 16); + if (val_region.length != 0) + RETERR(isc_str_tobuffer(",", target)); + } + break; + case SVC_PARAM_DOHPATH: + RETERR(isc_str_tobuffer("=", target)); + RETERR(multitxt_totext(&val_region, target)); + break; + default: + RETERR(isc_str_tobuffer("=", target)); + RETERR(multitxt_totext(&val_region, target)); + break; + } + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_in_svcb(ARGS_TOTEXT) { + REQUIRE(rdata->type == dns_rdatatype_svcb); + REQUIRE(rdata->rdclass == dns_rdataclass_in); + REQUIRE(rdata->length != 0); + + return (totext_in_svcb_https(rdata, tctx, target)); +} + +static inline isc_result_t +fromwire_in_svcb_https(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sr; + unsigned int svc_param_value_len; + int alias_mode = 0; + + UNUSED(type); + UNUSED(rdclass); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + /* + * SvcPriority. + */ + isc_buffer_activeregion(source, &sr); + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + RETERR(isc_mem_tobuffer(target, sr.base, 2)); + alias_mode = uint16_fromregion(&sr) == 0; + isc_buffer_forward(source, 2); + + /* + * TargetName. + */ + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + if (alias_mode) { + /* + * In AliasMode, recipients MUST ignore any SvcParams that + * are present. + */ + return (ISC_R_SUCCESS); + } + + isc_buffer_activeregion(source, &sr); + while (sr.length > 0) { + /* + * SvcParamKey. + */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + + RETERR(isc_mem_tobuffer(target, sr.base, 2)); + isc_region_consume(&sr, 2); + isc_buffer_forward(source, 2); + + /* + * SvcParamValue length. + */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + + RETERR(isc_mem_tobuffer(target, sr.base, 2)); + svc_param_value_len = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + isc_buffer_forward(source, 2); + + if (sr.length < svc_param_value_len) + return (ISC_R_UNEXPECTEDEND); + + RETERR(isc_mem_tobuffer(target, sr.base, svc_param_value_len)); + isc_region_consume(&sr, svc_param_value_len); + isc_buffer_forward(source, svc_param_value_len); + } + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_in_svcb(ARGS_FROMWIRE) { + REQUIRE(type == dns_rdatatype_svcb); + REQUIRE(rdclass == dns_rdataclass_in); + return (fromwire_in_svcb_https(rdclass, type, source, dctx, options, + target)); +} + +static inline isc_result_t +towire_in_svcb_https(ARGS_TOWIRE) { + dns_name_t name; + dns_offsets_t offsets; + isc_region_t sr; + + dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); + + /* + * SvcPriority. + */ + dns_rdata_toregion(rdata, &sr); + RETERR(isc_mem_tobuffer(target, sr.base, 2)); + isc_region_consume(&sr, 2); + + /* + * TargetName. + */ + dns_name_init(&name, offsets); + dns_name_fromregion(&name, &sr); + RETERR(dns_name_towire(&name, cctx, target)); + isc_region_consume(&sr, name_length(&name)); + + /* + * SvcParams. + */ + return (isc_mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_in_svcb(ARGS_TOWIRE) { + REQUIRE(rdata->type == dns_rdatatype_svcb); + REQUIRE(rdata->length != 0); + + return (towire_in_svcb_https(rdata, cctx, target)); +} +#endif /* RDATA_IN_1_SVCB_64_C */ -- 2.20.1