Report Extended DNS Error codes

(cherry picked from commit b144ae1bb0)
(cherry picked from commit eed4fab37b)
This commit is contained in:
Mark Andrews 2020-05-11 14:44:23 +10:00
parent fb4ca938a2
commit c0d34e8b05
12 changed files with 275 additions and 46 deletions

View file

@ -1671,22 +1671,23 @@ typedef struct dig_ednsoptname {
} dig_ednsoptname_t;
dig_ednsoptname_t optnames[] = {
{ 1, "LLQ" }, /* draft-sekar-dns-llq */
{ 3, "NSID" }, /* RFC 5001 */
{ 5, "DAU" }, /* RFC 6975 */
{ 6, "DHU" }, /* RFC 6975 */
{ 7, "N3U" }, /* RFC 6975 */
{ 8, "ECS" }, /* RFC 7871 */
{ 9, "EXPIRE" }, /* RFC 7314 */
{ 10, "COOKIE" }, /* RFC 7873 */
{ 11, "KEEPALIVE" }, /* RFC 7828 */
{ 12, "PADDING" }, /* RFC 7830 */
{ 12, "PAD" }, /* shorthand */
{ 13, "CHAIN" }, /* RFC 7901 */
{ 14, "KEY-TAG" }, /* RFC 8145 */
{ 16, "CLIENT-TAG" }, /* draft-bellis-dnsop-edns-tags */
{ 17, "SERVER-TAG" }, /* draft-bellis-dnsop-edns-tags */
{ 26946, "DEVICEID" }, /* Brian Hartvigsen */
{ 1, "LLQ" }, /* draft-sekar-dns-llq */
{ 3, "NSID" }, /* RFC 5001 */
{ 5, "DAU" }, /* RFC 6975 */
{ 6, "DHU" }, /* RFC 6975 */
{ 7, "N3U" }, /* RFC 6975 */
{ 8, "ECS" }, /* RFC 7871 */
{ 9, "EXPIRE" }, /* RFC 7314 */
{ 10, "COOKIE" }, /* RFC 7873 */
{ 11, "KEEPALIVE" }, /* RFC 7828 */
{ 12, "PADDING" }, /* RFC 7830 */
{ 12, "PAD" }, /* shorthand */
{ 13, "CHAIN" }, /* RFC 7901 */
{ 14, "KEY-TAG" }, /* RFC 8145 */
{ 15, "EDE" }, /* ietf-dnsop-extended-error-16 */
{ 16, "CLIENT-TAG" }, /* draft-bellis-dnsop-edns-tags */
{ 17, "SERVER-TAG" }, /* draft-bellis-dnsop-edns-tags */
{ 26946, "DEVICEID" }, /* Brian Hartvigsen */
};
#define N_EDNS_OPTNAMES (sizeof(optnames) / sizeof(optnames[0]))

View file

@ -99,15 +99,17 @@
#define DNS_MESSAGEEXTFLAG_DO 0x8000U
/*%< EDNS0 extended OPT codes */
#define DNS_OPT_LLQ 1 /*%< LLQ opt code */
#define DNS_OPT_NSID 3 /*%< NSID opt code */
#define DNS_OPT_CLIENT_SUBNET 8 /*%< client subnet opt code */
#define DNS_OPT_EXPIRE 9 /*%< EXPIRE opt code */
#define DNS_OPT_COOKIE 10 /*%< COOKIE opt code */
#define DNS_OPT_PAD 12 /*%< PAD opt code */
#define DNS_OPT_KEY_TAG 14 /*%< Key tag opt code */
#define DNS_OPT_CLIENT_TAG 16 /*%< Client tag opt code */
#define DNS_OPT_SERVER_TAG 17 /*%< Server tag opt code */
#define DNS_OPT_LLQ 1 /*%< LLQ opt code */
#define DNS_OPT_NSID 3 /*%< NSID opt code */
#define DNS_OPT_CLIENT_SUBNET 8 /*%< client subnet opt code */
#define DNS_OPT_EXPIRE 9 /*%< EXPIRE opt code */
#define DNS_OPT_COOKIE 10 /*%< COOKIE opt code */
#define DNS_OPT_TCP_KEEPALIVE 11 /*%< TCP keepalive opt code */
#define DNS_OPT_PAD 12 /*%< PAD opt code */
#define DNS_OPT_KEY_TAG 14 /*%< Key tag opt code */
#define DNS_OPT_EDE 15 /*%< Extended DNS Error opt code */
#define DNS_OPT_CLIENT_TAG 16 /*%< Client tag opt code */
#define DNS_OPT_SERVER_TAG 17 /*%< Server tag opt code */
/*%< Experimental options [65001...65534] as per RFC6891 */

View file

@ -23,7 +23,8 @@
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/utf8.h>
#include <isc/util.h>
#include <dns/dnssec.h>
@ -144,6 +145,32 @@ static const char *opcodetext[] = {
"RESERVED15"
};
static const char *edetext[] = { "Other",
"Unsupported DNSKEY Algorithm",
"Unsupported DS Digest Type",
"Stale Answer",
"Forged Answer",
"DNSSEC Indeterminate",
"DNSSEC Bogus",
"Signature Expired",
"Signature Not Yet Valid",
"DNSKEY Missing",
"RRSIGs Missing",
"No Zone Key Bit Set",
"NSEC Missing",
"Cached Error",
"Not Ready",
"Blocked",
"Censored",
"Filtered",
"Prohibited",
"Stale NXDOMAIN Answer",
"Not Authoritative",
"Not Supported",
"No Reachable Authority",
"Network Error",
"Invalid Data" };
/*%
* "helper" type, which consists of a block of some type, and is linkable.
* For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
@ -3544,7 +3571,7 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg,
* Print EDNS info, if any.
*
* WARNING: The option contents may be malformed as
* dig +ednsopt=value:<content> does not validity
* dig +ednsopt=value:<content> does not perform validity
* checking.
*/
dns_rdata_init(&rdata);
@ -3782,7 +3809,7 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
dns_rdataset_t *ps = NULL;
dns_name_t *name = NULL;
isc_result_t result;
char buf[sizeof("1234567890")];
char buf[sizeof("1234567890 ")];
uint32_t mbz;
dns_rdata_t rdata;
isc_buffer_t optbuf;
@ -3916,6 +3943,33 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
ADD_STRING(target, "\n");
continue;
}
} else if (optcode == DNS_OPT_EDE) {
ADD_STRING(target, "; EDE:");
if (optlen >= 2U) {
uint16_t ede;
ede = isc_buffer_getuint16(&optbuf);
snprintf(buf, sizeof(buf), ": %u", ede);
ADD_STRING(target, buf);
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
if (ede < ARRAY_SIZE(edetext)) {
ADD_STRING(target, " (");
ADD_STRING(target,
edetext[ede]);
ADD_STRING(target, ")");
}
optlen -= 2;
} else if (optlen == 1U) {
/* Malformed */
optdata = isc_buffer_current(&optbuf);
snprintf(buf, sizeof(buf),
" %02x (\"%c\")\n", optdata[0],
isprint(optdata[0])
? optdata[0]
: '.');
isc_buffer_forward(&optbuf, optlen);
ADD_STRING(target, buf);
continue;
}
} else if (optcode == DNS_OPT_CLIENT_TAG) {
uint16_t id;
ADD_STRING(target, "; CLIENT-TAG");
@ -3951,19 +4005,22 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
ADD_STRING(target, ": ");
optdata = isc_buffer_current(&optbuf);
for (i = 0; i < optlen; i++) {
const char *sep;
switch (optcode) {
case DNS_OPT_COOKIE:
sep = "";
break;
default:
sep = " ";
break;
if (optcode != DNS_OPT_EDE) {
for (i = 0; i < optlen; i++) {
const char *sep;
switch (optcode) {
case DNS_OPT_COOKIE:
sep = "";
break;
default:
sep = " ";
break;
}
snprintf(buf, sizeof(buf),
"%02x%s", optdata[i],
sep);
ADD_STRING(target, buf);
}
snprintf(buf, sizeof(buf), "%02x%s",
optdata[i], sep);
ADD_STRING(target, buf);
}
isc_buffer_forward(&optbuf, optlen);
@ -3997,9 +4054,13 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
/*
* For non-COOKIE options, add a printable
* version
* version.
*/
ADD_STRING(target, "(\"");
if (optcode != DNS_OPT_EDE) {
ADD_STRING(target, "(\"");
} else {
ADD_STRING(target, "(");
}
if (isc_buffer_availablelength(target) < optlen)
return (ISC_R_NOSPACE);
for (i = 0; i < optlen; i++) {
@ -4010,7 +4071,11 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
else
isc_buffer_putstr(target, ".");
}
ADD_STRING(target, "\")");
if (optcode != DNS_OPT_EDE) {
ADD_STRING(target, "\")");
} else {
ADD_STRING(target, ")");
}
}
ADD_STRING(target, "\n");
}

View file

@ -18,6 +18,8 @@
DNS_RDATATYPEATTR_META | \
DNS_RDATATYPEATTR_NOTQUESTION)
#include <isc/utf8.h>
static inline isc_result_t
fromtext_opt(ARGS_FROMTEXT) {
/*
@ -202,6 +204,24 @@ fromwire_opt(ARGS_FROMWIRE) {
}
isc_region_consume(&sregion, length);
break;
case DNS_OPT_EDE:
if (length < 2) {
return (DNS_R_OPTERR);
}
/* UTF-8 Byte Order Mark is not permitted. RFC 5198 */
if (isc_utf8_bom(sregion.base + 2, length - 2)) {
return (DNS_R_OPTERR);
}
/*
* The EXTRA-TEXT field is specified as UTF-8, and
* therefore must be validated for correctness
* according to RFC 3269 security considerations.
*/
if (!isc_utf8_valid(sregion.base + 2, length - 2)) {
return (DNS_R_OPTERR);
}
isc_region_consume(&sregion, length);
break;
case DNS_OPT_CLIENT_TAG:
/* FALLTHROUGH */
case DNS_OPT_SERVER_TAG:

View file

@ -62,7 +62,7 @@ OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \
rwlock.@O@ \
safe.@O@ serial.@O@ siphash.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ \
string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \
tm.@O@ timer.@O@ version.@O@ \
tm.@O@ timer.@O@ utf8.@O@ version.@O@ \
${UNIXOBJS} ${NLSOBJS} ${THREADOBJS}
SYMTBLOBJS = backtrace-emptytbl.@O@
@ -81,7 +81,7 @@ SRCS = @ISC_EXTRA_SRCS@ @ISC_PK11_C@ @ISC_PK11_RESULT_C@ \
ratelimiter.c refcount.c region.c regex.c result.c rwlock.c \
safe.c serial.c siphash.c sha1.c sha2.c sockaddr.c stats.c string.c \
strtoul.c symtab.c task.c taskpool.c timer.c \
tm.c version.c
tm.c utf8.c version.c
LIBS = @ISC_OPENSSL_LIBS@ @LIBS@

View file

@ -32,7 +32,7 @@ HEADERS = aes.h app.h assertions.h boolean.h backtrace.h base32.h base64.h \
region.h resource.h result.h resultclass.h rwlock.h \
safe.h serial.h siphash.h sha1.h sha2.h sockaddr.h socket.h \
stats.h stdatomic.h stdio.h stdlib.h string.h symtab.h task.h \
taskpool.h timer.h tm.h types.h util.h version.h \
taskpool.h timer.h tm.h types.h utf8.h util.h version.h \
xml.h
SUBDIRS =

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*! \file isc/utf8.h */
#pragma once
#include <isc/lang.h>
#include <isc/types.h>
ISC_LANG_BEGINDECLS
bool
isc_utf8_bom(const unsigned char *buf, size_t len);
/*<
* Returns 'true' if the string of bytes in 'buf' starts
* with an UTF-8 Byte Order Mark.
*
* Requires:
*\li 'buf' != NULL
*/
bool
isc_utf8_valid(const unsigned char *buf, size_t len);
/*<
* Returns 'true' if the string of bytes in 'buf' is a valid UTF-8
* byte sequence otherwise 'false' is returned.
*
* Requires:
*\li 'buf' != NULL
*/
ISC_LANG_ENDDECLS

88
lib/isc/utf8.c Normal file
View file

@ -0,0 +1,88 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <config.h>
#include <string.h>
#include <isc/utf8.h>
#include <isc/util.h>
/*
* UTF-8 is defined in "The Unicode Standard -- Version 4.0"
* Also see RFC 3629.
*
* Char. number range | UTF-8 octet sequence
* (hexadecimal) | (binary)
* --------------------+---------------------------------------------
* 0000 0000-0000 007F | 0xxxxxxx
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
bool
isc_utf8_valid(const unsigned char *buf, size_t len) {
REQUIRE(buf != NULL);
for (size_t i = 0; i < len; i++) {
if (buf[i] <= 0x7f) {
continue;
}
if ((i + 1) < len && (buf[i] & 0xe0) == 0xc0 &&
(buf[i + 1] & 0xc0) == 0x80) {
unsigned int w;
w = (buf[i] & 0x1f) << 6;
w |= (buf[++i] & 0x3f);
if (w < 0x80) {
return (false);
}
continue;
}
if ((i + 2) < len && (buf[i] & 0xf0) == 0xe0 &&
(buf[i + 1] & 0xc0) == 0x80 && (buf[i + 2] & 0xc0) == 0x80)
{
unsigned int w;
w = (buf[i] & 0x0f) << 12;
w |= (buf[++i] & 0x3f) << 6;
w |= (buf[++i] & 0x3f);
if (w < 0x0800) {
return (false);
}
continue;
}
if ((i + 3) < len && (buf[i] & 0xf8) == 0xf0 &&
(buf[i + 1] & 0xc0) == 0x80 &&
(buf[i + 2] & 0xc0) == 0x80 && (buf[i + 3] & 0xc0) == 0x80)
{
unsigned int w;
w = (buf[i] & 0x07) << 18;
w |= (buf[++i] & 0x3f) << 12;
w |= (buf[++i] & 0x3f) << 6;
w |= (buf[++i] & 0x3f);
if (w < 0x10000 || w > 0x10FFFF) {
return (false);
}
continue;
}
return (false);
}
return (true);
}
bool
isc_utf8_bom(const unsigned char *buf, size_t len) {
REQUIRE(buf != NULL);
if (len >= 3U && !memcmp(buf, "\xef\xbb\xbf", 3)) {
return (true);
}
return (false);
}

View file

@ -754,6 +754,8 @@ isc_timermgr_destroy
isc_timermgr_poke
isc_tm_timegm
isc_tm_strptime
isc_utf8_bom
isc_utf8_valid
isc_win32os_versioncheck
openlog
@IF PKCS11

View file

@ -277,6 +277,9 @@
<ClInclude Include="..\include\isc\types.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isc\utf8.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isc\util.h">
<Filter>Library Header Files</Filter>
</ClInclude>
@ -666,6 +669,9 @@
<ClCompile Include="..\tm.c">
<Filter>Library Source Files</Filter>
</ClCompile>
<ClCompile Include="..\utf8.c">
<Filter>Library Source Files</Filter>
</ClCompile>
@IF PKCS11
<ClCompile Include="..\pk11.c">
<Filter>Library Source Files</Filter>

View file

@ -389,6 +389,7 @@ copy InstallFiles ..\Build\Release\
<ClInclude Include="..\include\isc\timer.h" />
<ClInclude Include="..\include\isc\tm.h" />
<ClInclude Include="..\include\isc\types.h" />
<ClInclude Include="..\include\isc\utf8.h" />
<ClInclude Include="..\include\isc\util.h" />
<ClInclude Include="..\include\isc\version.h" />
<ClInclude Include="..\include\isc\xml.h" />
@ -497,6 +498,7 @@ copy InstallFiles ..\Build\Release\
<ClCompile Include="..\taskpool.c" />
<ClCompile Include="..\timer.c" />
<ClCompile Include="..\tm.c" />
<ClCompile Include="..\utf8.c" />
@IF PKCS11
<ClCompile Include="..\pk11.c" />
<ClCompile Include="..\pk11_result.c" />

View file

@ -4050,6 +4050,7 @@
./lib/isc/include/isc/timer.h C 1998,1999,2000,2001,2002,2004,2005,2006,2007,2008,2009,2012,2013,2014,2016,2018,2019,2020
./lib/isc/include/isc/tm.h C 2014,2016,2018,2019,2020
./lib/isc/include/isc/types.h C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2012,2013,2014,2016,2018,2019,2020
./lib/isc/include/isc/utf8.h C 2020
./lib/isc/include/isc/util.h C 1998,1999,2000,2001,2004,2005,2006,2007,2010,2011,2012,2015,2016,2017,2018,2019,2020
./lib/isc/include/isc/version.h C 2001,2004,2005,2006,2007,2016,2018,2019,2020
./lib/isc/include/isc/xml.h C 2006,2007,2016,2018,2019,2020
@ -4223,6 +4224,7 @@
./lib/isc/unix/strerror.c C 2001,2004,2005,2007,2009,2016,2018,2019,2020
./lib/isc/unix/syslog.c C 2001,2004,2005,2007,2016,2018,2019,2020
./lib/isc/unix/time.c C 1998,1999,2000,2001,2003,2004,2005,2006,2007,2008,2011,2012,2014,2015,2016,2017,2018,2019,2020
./lib/isc/utf8.c C 2020
./lib/isc/version.c C 1998,1999,2000,2001,2004,2005,2007,2016,2018,2019,2020
./lib/isc/win32/DLLMain.c C 2001,2004,2007,2016,2018,2019,2020
./lib/isc/win32/Makefile.in MAKE 1999,2000,2001,2004,2007,2009,2012,2014,2015,2016,2018,2019,2020