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