]> 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>
Tue, 12 May 2020 12:01:54 +0000 (22:01 +1000)
bin/dig/dighost.c
lib/dns/include/dns/message.h
lib/dns/message.c
lib/dns/rdata/generic/opt_41.c
lib/isc/Makefile.am
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 bfc0c2c65f31883faffb5b565c891260a61e672a..0384d7ccada947791118c4935741448171008a12 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 702d02012a00858d5ae857f587be3cea74f820e3..2d96823e93bcd2898ab2761d5fcb45602d048b60 100644 (file)
@@ -88,6 +88,7 @@ libisc_la_HEADERS =                   \
        include/isc/timer.h             \
        include/isc/tm.h                \
        include/isc/types.h             \
+       include/isc/utf8.h              \
        include/isc/util.h              \
        pthreads/include/isc/condition.h\
        pthreads/include/isc/mutex.h    \
@@ -205,6 +206,7 @@ libisc_la_SOURCES =         \
        taskpool.c              \
        timer.c                 \
        tm.c                    \
+       utf8.c                  \
        pthreads/condition.c    \
        pthreads/mutex.c        \
        pthreads/thread.c       \
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 aecf8002448666c3644c576a22e3c7c75dfd6c05..7b47b79c2607bc086a6b558a4232bea304b12bac 100644 (file)
@@ -689,6 +689,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 f4e1964f06c48ccf340298ff6ac94ba3d7e77ac6..5dcf67ab50d22ca1c129ccb99213d812935cf883 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 b4574460b708ce660383fbbea52828f92b0b093e..297df38905255d7cb0385ff895b4ef8726b8210d 100644 (file)
@@ -370,6 +370,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" />
 @IF PKCS11
     <ClInclude Include="..\include\pk11\constants.h" />
@@ -471,6 +472,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 4aecf882c5f5dd460b540487e6795c27350252d2..5c71e8dee8e63ede50b88c1e50ef3d2553d0b3bf 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/pk11/constants.h             C       2014,2016,2017,2018,2019,2020
 ./lib/isc/include/pk11/internal.h              C       2014,2016,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/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
 ./lib/isc/win32/dir.c                          C       1999,2000,2001,2004,2007,2008,2009,2011,2012,2013,2016,2017,2018,2019,2020