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