]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: DNS resolution response parsing broken
authorBaptiste Assmann <bedis9@gmail.com>
Fri, 7 Aug 2015 09:24:05 +0000 (11:24 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 8 Aug 2015 16:14:20 +0000 (18:14 +0200)
In some cases, parsing of the DNS response is broken and the response is
considered as invalid, despite being valid.

The current patch fixes this issue. It's a temporary solution until I
rework the response parsing to store the response buffer into a real DNS
packet structure.

src/dns.c

index 53e743002bee126ff7d2e80e53590cd3799f0b05..4bc54489f36a2b84ffc2bbece1910582b0254eeb 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -462,40 +462,40 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, char *
                }
 
                /* ptr now points to the name */
-               /* if cname is set, it means a CNAME recursion is in progress */
-               if (cname) {
-                       /* check if the name can stand in response */
-                       if ((reader + cnamelen) > bufend)
-                               return DNS_RESP_INVALID;
-                       /* compare cname and current name */
-                       if (memcmp(ptr, cname, cnamelen) != 0)
-                               return DNS_RESP_CNAME_ERROR;
-               }
-               /* compare server hostname to current name */
-               else if (dn_name) {
-                       /* check if the name can stand in response */
-                       if ((reader + dn_name_len) > bufend)
-                               return DNS_RESP_INVALID;
-                       if (memcmp(ptr, dn_name, dn_name_len) != 0)
-                               return DNS_RESP_WRONG_NAME;
-               }
-
-               if ((*reader & 0xc0) == 0xc0) {
-                       /* move forward 2 bytes for information pointer and address pointer */
-                       reader += 2;
-               }
-               else {
+               if ((*reader & 0xc0) != 0xc0) {
+                       /* if cname is set, it means a CNAME recursion is in progress */
                        if (cname) {
+                               /* check if the name can stand in response */
+                               if ((reader + cnamelen) > bufend)
+                                       return DNS_RESP_INVALID;
+                               /* compare cname and current name */
+                               if (memcmp(ptr, cname, cnamelen) != 0)
+                                       return DNS_RESP_CNAME_ERROR;
+
                                cname = reader;
                                cnamelen = dns_str_to_dn_label_len((const char *)cname);
 
                                /* move forward cnamelen bytes + NULL byte */
                                reader += (cnamelen + 1);
                        }
+                       /* compare server hostname to current name */
+                       else if (dn_name) {
+                               /* check if the name can stand in response */
+                               if ((reader + dn_name_len) > bufend)
+                                       return DNS_RESP_INVALID;
+                               if (memcmp(ptr, dn_name, dn_name_len) != 0)
+                                       return DNS_RESP_WRONG_NAME;
+                       }
                        else {
                                reader += (len + 1);
                        }
                }
+               else {
+                       /* shortname in progress */
+                       /* move forward 2 bytes for information pointer and address pointer */
+                       reader += 2;
+               }
+
                if (reader >= bufend)
                        return DNS_RESP_INVALID;