]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Report Extended DNS Error codes
authorMark Andrews <marka@isc.org>
Mon, 11 May 2020 04:44:23 +0000 (14:44 +1000)
committerMark Andrews <marka@isc.org>
Wed, 13 May 2020 00:26:39 +0000 (10:26 +1000)
(cherry picked from commit b144ae1bb01cf896997b6c6b9bcd55394a3f5ce9)

12 files changed:
bin/dig/dighost.c
lib/dns/include/dns/message.h
lib/dns/message.c
lib/dns/rdata/generic/opt_41.c
lib/isc/Makefile.in
lib/isc/include/isc/Makefile.in
lib/isc/include/isc/utf8.h [new file with mode: 0644]
lib/isc/utf8.c [new file with mode: 0644]
lib/isc/win32/libisc.def.in
lib/isc/win32/libisc.vcxproj.filters.in
lib/isc/win32/libisc.vcxproj.in
util/copyrights

index 4a4d0b677358d00eb9fac70245c8780ffb264d8b..9a7aa2d1ccfd9f20b236cdb5593e070e72ebd754 100644 (file)
@@ -1452,6 +1452,7 @@ dig_ednsoptname_t optnames[] = {
        { 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 */
index e2eef88c0674c8076848e7f3b5a7b802065b0f06..ec3e065daa05c327969881a92ea2974300ab3e1d 100644 (file)
 #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 */
 
index 4e4d692a479f5c8563adb6ba549bf25a8fec96f3..fe08420436e9f0f4eb04037faf59adf49c4a4726 100644 (file)
@@ -23,6 +23,7 @@
 #include <isc/mem.h>
 #include <isc/print.h>
 #include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/utf8.h>
 #include <isc/util.h>
 
 #include <dns/dnssec.h>
@@ -127,6 +128,32 @@ static const char *opcodetext[] = { "QUERY",         "IQUERY",     "STATUS",
                                    "RESERVED12", "RESERVED13", "RESERVED14",
                                    "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
@@ -3590,7 +3617,7 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, dns_pseudosection_t section,
                 * 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);
@@ -4004,6 +4031,36 @@ dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section,
                                        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;
+                                       if (optlen != 0) {
+                                               ADD_STRING(target, ":");
+                                       }
+                               } 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:");
@@ -4038,19 +4095,22 @@ dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section,
                                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);
@@ -4087,9 +4147,13 @@ dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section,
 
                                /*
                                 * 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);
@@ -4102,7 +4166,11 @@ dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section,
                                                isc_buffer_putstr(target, ".");
                                        }
                                }
-                               ADD_STRING(target, "\")");
+                               if (optcode != DNS_OPT_EDE) {
+                                       ADD_STRING(target, "\")");
+                               } else {
+                                       ADD_STRING(target, ")");
+                               }
                        }
                        ADD_STRING(target, "\n");
                }
index 22c3f472e669053d8d83d4622af8f212f12072b1..55a96853f1ae52acc02c7d3c667c32e4fd3b77a9 100644 (file)
@@ -18,6 +18,8 @@
        (DNS_RDATATYPEATTR_SINGLETON | DNS_RDATATYPEATTR_META | \
         DNS_RDATATYPEATTR_NOTQUESTION)
 
+#include <isc/utf8.h>
+
 static inline isc_result_t
 fromtext_opt(ARGS_FROMTEXT) {
        /*
@@ -206,6 +208,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:
index 61a5312729112376d6258b061966851672fe7e65..294a1cd8b1a1c9da08ba5387174858f58fb3c350 100644 (file)
@@ -62,7 +62,7 @@ OBJS =                pk11.@O@ pk11_result.@O@ \
                region.@O@ regex.@O@ result.@O@ rwlock.@O@ \
                safe.@O@ serial.@O@ siphash.@O@ sockaddr.@O@ stats.@O@ \
                string.@O@ symtab.@O@ task.@O@ taskpool.@O@ \
-               tm.@O@ timer.@O@ version.@O@ \
+               utf8.@O@ tm.@O@ timer.@O@ version.@O@ \
                ${UNIXOBJS} ${THREADOBJS}
 SYMTBLOBJS =   backtrace-emptytbl.@O@
 
@@ -80,7 +80,7 @@ SRCS =                pk11.c pk11_result.c \
                ratelimiter.c region.c regex.c result.c rwlock.c \
                safe.c serial.c siphash.c sockaddr.c stats.c string.c \
                symtab.c task.c taskpool.c timer.c \
-               tm.c version.c
+               utf8.c tm.c version.c
 
 LIBS =         ${OPENSSL_LIBS} ${JSON_C_LIBS} ${LIBUV_LIBS} ${LIBXML2_LIBS} ${ZLIB_LIBS} @LIBS@
 
index b883578f42c6dffec10715369ba3b793b4435b2a..2ccb804b99f4de356c6c8d3ec58edbfe928fdfab 100644 (file)
@@ -33,7 +33,7 @@ HEADERS =     aes.h app.h assertions.h astack.h atomic.h backtrace.h \
                region.h resource.h result.h resultclass.h rwlock.h \
                safe.h serial.h siphash.h sockaddr.h socket.h \
                stats.h stdio.h strerr.h string.h symtab.h \
-               task.h taskpool.h timer.h tm.h types.h util.h version.h
+               task.h taskpool.h timer.h tm.h types.h utf8.h util.h version.h
 
 SUBDIRS =
 TARGETS =
diff --git a/lib/isc/include/isc/utf8.h b/lib/isc/include/isc/utf8.h
new file mode 100644 (file)
index 0000000..a642c3f
--- /dev/null
@@ -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
diff --git a/lib/isc/utf8.c b/lib/isc/utf8.c
new file mode 100644 (file)
index 0000000..5bfd94f
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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 <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);
+}
index 476d29735fe212228559b33989454b42ce2625f0..4d38d47c5339b95ab8448a2a54d83f340bbce331 100644 (file)
@@ -693,6 +693,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
index 70007dc05c950d936285ea4b27148bbaa1074151..e72cf040afdd98df8135e0ac199d971b44772e77 100644 (file)
     <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>
     <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>
index 4e170c8338464bcb02dbf47968e01e9a92c95e5d..91da972b794222c232a3511f366bf9065de2dffd 100644 (file)
@@ -375,6 +375,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" />
 @IF PKCS11
@@ -478,6 +479,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" />
index ddd0e1e55f444892d06f72a2bf36ef5423e7112c..6d41f6616863e61c03d61fe94b4bce8ec8291a63 100644 (file)
 ./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,2017,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/pk11/constants.h             C       2014,2016,2017,2018,2019,2020
 ./lib/isc/unix/stdtime.c                       C       1999,2000,2001,2004,2005,2007,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/condition.c                    C       1998,1999,2000,2001,2004,2006,2007,2016,2018,2019,2020