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