86006e
From 362f91d807d293791008cdb7616d40f7784ece83 Mon Sep 17 00:00:00 2001
86006e
From: bradh352 <brad@brad-house.com>
86006e
Date: Fri, 11 Jun 2021 11:27:45 -0400
86006e
Subject: [PATCH 1/2] ares_expand_name() should escape more characters
86006e
86006e
RFC1035 5.1 specifies some reserved characters and escaping sequences
86006e
that are allowed to be specified.  Expand the list of reserved characters
86006e
and also escape non-printable characters using the \DDD format as
86006e
specified in the RFC.
86006e
86006e
Bug Reported By: philipp.jeitner@sit.fraunhofer.de
86006e
Fix By: Brad House (@bradh352)
86006e
---
86006e
 src/lib/ares_expand_name.c | 41 +++++++++++++++++++++++++++++++++++---
86006e
 1 file changed, 38 insertions(+), 3 deletions(-)
86006e
86006e
diff --git a/src/lib/ares_expand_name.c b/src/lib/ares_expand_name.c
86006e
index 407200ef..f1c874a9 100644
86006e
--- a/src/lib/ares_expand_name.c
86006e
+++ b/src/lib/ares_expand_name.c
86006e
@@ -32,6 +32,26 @@
86006e
 static int name_length(const unsigned char *encoded, const unsigned char *abuf,
86006e
                        int alen);
86006e
 
86006e
+/* Reserved characters for names that need to be escaped */
86006e
+static int is_reservedch(int ch)
86006e
+{
86006e
+  switch (ch) {
86006e
+    case '"':
86006e
+    case '.':
86006e
+    case ';':
86006e
+    case '\\':
86006e
+    case '(':
86006e
+    case ')':
86006e
+    case '@':
86006e
+    case '$':
86006e
+      return 1;
86006e
+    default:
86006e
+      break;
86006e
+  }
86006e
+
86006e
+  return 0;
86006e
+}
86006e
+
86006e
 /* Expand an RFC1035-encoded domain name given by encoded.  The
86006e
  * containing message is given by abuf and alen.  The result given by
86006e
  * *s, which is set to a NUL-terminated allocated buffer.  *enclen is
86006e
@@ -111,9 +131,18 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
86006e
           p++;
86006e
           while (len--)
86006e
             {
86006e
-              if (*p == '.' || *p == '\\')
86006e
+              if (!isprint(*p)) {
86006e
+                /* Output as \DDD for consistency with RFC1035 5.1 */
86006e
+                *q++ = '\\';
86006e
+                *q++ = '0' + *p / 100;
86006e
+                *q++ = '0' + (*p % 100) / 10;
86006e
+                *q++ = '0' + (*p % 10);
86006e
+              } else if (is_reservedch(*p)) {
86006e
                 *q++ = '\\';
86006e
-              *q++ = *p;
86006e
+                *q++ = *p;
86006e
+              } else {
86006e
+                *q++ = *p;
86006e
+              }
86006e
               p++;
86006e
             }
86006e
           *q++ = '.';
86006e
@@ -171,7 +200,13 @@ static int name_length(const unsigned char *encoded, const unsigned char *abuf,
86006e
           encoded++;
86006e
           while (offset--)
86006e
             {
86006e
-              n += (*encoded == '.' || *encoded == '\\') ? 2 : 1;
86006e
+              if (!isprint(*encoded)) {
86006e
+                n += 4;
86006e
+              } else if (is_reservedch(*encoded)) {
86006e
+                n += 2;
86006e
+              } else {
86006e
+                n += 1;
86006e
+              }
86006e
               encoded++;
86006e
             }
86006e
           n++;
86006e
86006e
From 44c009b8e62ea1929de68e3f438181bea469ec14 Mon Sep 17 00:00:00 2001
86006e
From: bradh352 <brad@brad-house.com>
86006e
Date: Fri, 11 Jun 2021 12:39:24 -0400
86006e
Subject: [PATCH 2/2] ares_expand_name(): fix formatting and handling of root
86006e
 name response
86006e
86006e
Fixes issue introduced in prior commit with formatting and handling
86006e
of parsing a root name response which should not be escaped.
86006e
86006e
Fix By: Brad House
86006e
---
86006e
 src/lib/ares_expand_name.c | 62 ++++++++++++++++++++++++--------------
86006e
 1 file changed, 40 insertions(+), 22 deletions(-)
86006e
86006e
diff --git a/src/lib/ares_expand_name.c b/src/lib/ares_expand_name.c
86006e
index f1c874a9..eb9268c1 100644
86006e
--- a/src/lib/ares_expand_name.c
86006e
+++ b/src/lib/ares_expand_name.c
86006e
@@ -127,27 +127,37 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
86006e
         }
86006e
       else
86006e
         {
86006e
-          len = *p;
86006e
+          int name_len = *p;
86006e
+          len = name_len;
86006e
           p++;
86006e
+
86006e
           while (len--)
86006e
             {
86006e
-              if (!isprint(*p)) {
86006e
-                /* Output as \DDD for consistency with RFC1035 5.1 */
86006e
-                *q++ = '\\';
86006e
-                *q++ = '0' + *p / 100;
86006e
-                *q++ = '0' + (*p % 100) / 10;
86006e
-                *q++ = '0' + (*p % 10);
86006e
-              } else if (is_reservedch(*p)) {
86006e
-                *q++ = '\\';
86006e
-                *q++ = *p;
86006e
-              } else {
86006e
-                *q++ = *p;
86006e
-              }
86006e
+              /* Output as \DDD for consistency with RFC1035 5.1, except
86006e
+               * for the special case of a root name response  */
86006e
+              if (!isprint(*p) && !(name_len == 1 && *p == 0))
86006e
+                {
86006e
+
86006e
+                  *q++ = '\\';
86006e
+                  *q++ = '0' + *p / 100;
86006e
+                  *q++ = '0' + (*p % 100) / 10;
86006e
+                  *q++ = '0' + (*p % 10);
86006e
+                }
86006e
+              else if (is_reservedch(*p))
86006e
+                {
86006e
+                  *q++ = '\\';
86006e
+                  *q++ = *p;
86006e
+                }
86006e
+              else
86006e
+                {
86006e
+                  *q++ = *p;
86006e
+                }
86006e
               p++;
86006e
             }
86006e
           *q++ = '.';
86006e
         }
86006e
-    }
86006e
+     }
86006e
+
86006e
   if (!indir)
86006e
     *enclen = aresx_uztosl(p + 1U - encoded);
86006e
 
86006e
@@ -194,21 +204,29 @@ static int name_length(const unsigned char *encoded, const unsigned char *abuf,
86006e
         }
86006e
       else if (top == 0x00)
86006e
         {
86006e
-          offset = *encoded;
86006e
+          int name_len = *encoded;
86006e
+          offset = name_len;
86006e
           if (encoded + offset + 1 >= abuf + alen)
86006e
             return -1;
86006e
           encoded++;
86006e
+
86006e
           while (offset--)
86006e
             {
86006e
-              if (!isprint(*encoded)) {
86006e
-                n += 4;
86006e
-              } else if (is_reservedch(*encoded)) {
86006e
-                n += 2;
86006e
-              } else {
86006e
-                n += 1;
86006e
-              }
86006e
+              if (!isprint(*encoded) && !(name_len == 1 && *encoded == 0))
86006e
+                {
86006e
+                  n += 4;
86006e
+                }
86006e
+              else if (is_reservedch(*encoded))
86006e
+                {
86006e
+                  n += 2;
86006e
+                }
86006e
+              else
86006e
+                {
86006e
+                  n += 1;
86006e
+                }
86006e
               encoded++;
86006e
             }
86006e
+
86006e
           n++;
86006e
         }
86006e
       else