]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dns-domain: check resulting domain name length in dns_name_to_wire_format()
authorLennart Poettering <lennart@poettering.net>
Mon, 30 Nov 2015 18:39:19 +0000 (19:39 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 30 Nov 2015 18:42:35 +0000 (19:42 +0100)
Let's better be safe than sorry.

src/shared/dns-domain.c
src/test/test-dns-domain.c

index ba6eff8f60c26e0dd915762f0330c150ca6e6c93..03c010730892353b71a697b935edada0a3834f79 100644 (file)
@@ -864,7 +864,7 @@ bool dns_name_is_single_label(const char *name) {
         return dns_name_is_root(name);
 }
 
-/* Encode a domain name according to RFC 1035 Section 3.1 */
+/* Encode a domain name according to RFC 1035 Section 3.1, without compression */
 int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) {
         uint8_t *label_length, *out;
         int r;
@@ -875,24 +875,35 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) {
         out = buffer;
 
         do {
-                /* reserve a byte for label length */
+                /* Reserve a byte for label length */
                 if (len <= 0)
                         return -ENOBUFS;
                 len--;
                 label_length = out;
                 out++;
 
-                /* convert and copy a single label */
+                /* Convert and copy a single label. Note that
+                 * dns_label_unescape() returns 0 when it hits the end
+                 * of the domain name, which we rely on here to encode
+                 * the trailing NUL byte. */
                 r = dns_label_unescape(&domain, (char *) out, len);
                 if (r < 0)
                         return r;
 
-                /* fill label length, move forward */
+                /* Fill label length, move forward */
                 *label_length = r;
                 out += r;
                 len -= r;
+
         } while (r != 0);
 
+        /* Verify the maximum size of the encoded name. The trailing
+         * dot + NUL byte account are included this time, hence
+         * compare against DNS_HOSTNAME_MAX + 2 (which is 255) this
+         * time. */
+        if (out - buffer > DNS_HOSTNAME_MAX + 2)
+                return -EINVAL;
+
         return out - buffer;
 }
 
index 0762faa9a7d5fd9585a65eca593e8ccfcf122329..a1795b3be2784971efbb923c8ddd5b75c1efffc1 100644 (file)
@@ -66,10 +66,36 @@ static void test_dns_name_to_wire_format_one(const char *what, const char *expec
 }
 
 static void test_dns_name_to_wire_format(void) {
-        const char out0[] = { 0 };
-        const char out1[] = { 3, 'f', 'o', 'o', 0 };
-        const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
-        const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+        static const char out0[] = { 0 };
+        static const char out1[] = { 3, 'f', 'o', 'o', 0 };
+        static const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+        static const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+        static const char out4[] = { 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     3, 'a', '1', '2', 0 };
 
         test_dns_name_to_wire_format_one("", out0, sizeof(out0), sizeof(out0));
 
@@ -81,6 +107,9 @@ static void test_dns_name_to_wire_format(void) {
         test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL);
 
         test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3));
+
+        test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", NULL, 500, -EINVAL);
+        test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", out4, sizeof(out4), sizeof(out4));
 }
 
 static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) {