]> 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 02:18:55 +0000 (12:18 +1000)
(cherry picked from commit b144ae1bb01cf896997b6c6b9bcd55394a3f5ce9)
(cherry picked from commit eed4fab37b5dc28484828dfe3f95611f15ce16a5)

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 61b00b007681c67bf6f4781147fe4ee89544050a..8551459078cbeafa2603048ccf7ce04337bb2930 100644 (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]))
index 6c9a14eb6e744c0ae09bda7c9af6788ac74b2e4d..0072d5a8f2bd356569ea820e302b62bd4d842d0f 100644 (file)
 #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 */
 
index 70733ab1df8e8a29c7c45f465c70d3a86f71d3fb..2ec4f96316c3c2bd9bf1f26299765806ef08f5a0 100644 (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");
                }
index 15f6299a1fae5e73378270da579ad08ade70ac81..7bd0c4ff8d6fe55aebe86d3d5cf6437bf9add8b7 100644 (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:
index 0fd08379ae5985e04b6b8401cf1219d51fccf260..149552a1ea13ac9c700384079767f4be2d1ed9a8 100644 (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@
 
index e4034d333fae154e5059e1f43329c0cb5f7eab81..001a7bd468555271c3f939a7275fed547c87199e 100644 (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 =
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..7ceaabb
--- /dev/null
@@ -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);
+}
index ee06bf07097bb08f5114848bb2952011e498fa91..3e6c4b59ae3551ced479018d27489047fd37d2b4 100644 (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
index 71551d690a7de77f075bbc8c9afe7819059c3a3f..ecf0164bc2093a4e173014529277987a3b32a4fa 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 d47c52c619abda37f468b6a5cc7170b1dd10797e..66457ba98bf6b17e689ffae77e33a8be3759f2da 100644 (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" />
index aa8dae1289eaf901f1b3c4ec45763d76eb6f4605..36743c1a7d5dd6686276799a03c011cd7f4a6740 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,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
 ./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