resolve: unify memdup() code when parsing RRs
authorLennart Poettering <lennart@poettering.net>
Thu, 23 Jul 2015 02:04:19 +0000 (04:04 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 23 Jul 2015 02:50:19 +0000 (04:50 +0200)
Let's make dns_packet_read_public_key() more generic by renaming it to
dns_packet_read_memdup() (which more accurately describes what it
does...). Then, patch all cases where we memdup() RR data to use this
new call.

This specifically checks for zero-length objects, and handles them
gracefully. It will set zero length payload fields as a result.

Special care should be taken to ensure that any code using this call
can handle the returned allocated field to be NULL if the size is
specified as 0!

src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-rr.c
src/resolve/resolved-dns-rr.h

index b1cde4a..563b956 100644 (file)
@@ -933,6 +933,42 @@ int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
         return 0;
 }
 
+static int dns_packet_read_memdup(
+                DnsPacket *p, size_t size,
+                void **ret, size_t *ret_size,
+                size_t *ret_start) {
+
+        const void *src;
+        size_t start;
+        int r;
+
+        assert(p);
+        assert(ret);
+
+        r = dns_packet_read(p, size, &src, &start);
+        if (r < 0)
+                return r;
+
+        if (size <= 0)
+                *ret = NULL;
+        else {
+                void *copy;
+
+                copy = memdup(src, size);
+                if (!copy)
+                        return -ENOMEM;
+
+                *ret = copy;
+        }
+
+        if (ret_size)
+                *ret_size = size;
+        if (ret_start)
+                *ret_start = start;
+
+        return 0;
+}
+
 int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
         const void *d;
         int r;
@@ -1239,26 +1275,6 @@ fail:
         return r;
 }
 
-static int dns_packet_read_public_key(DnsPacket *p, size_t length,
-                                      void **dp, size_t *lengthp,
-                                      size_t *start) {
-        int r;
-        const void *d;
-        void *d2;
-
-        r = dns_packet_read(p, length, &d, NULL);
-        if (r < 0)
-                return r;
-
-        d2 = memdup(d, length);
-        if (!d2)
-                return -ENOMEM;
-
-        *dp = d2;
-        *lengthp = length;
-        return 0;
-}
-
 static bool loc_size_ok(uint8_t size) {
         uint8_t m = size >> 4, e = size & 0xF;
 
@@ -1281,7 +1297,6 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
         size_t saved_rindex, offset;
         uint16_t rdlength;
-        const void *d;
         int r;
 
         assert(p);
@@ -1492,9 +1507,9 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_read_public_key(p, rdlength - 4,
-                                               &rr->ds.digest, &rr->ds.digest_size,
-                                               NULL);
+                r = dns_packet_read_memdup(p, rdlength - 4,
+                                           &rr->ds.digest, &rr->ds.digest_size,
+                                           NULL);
                 if (r < 0)
                         goto fail;
 
@@ -1508,9 +1523,9 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_read_public_key(p, rdlength - 2,
-                                               &rr->sshfp.key, &rr->sshfp.key_size,
-                                               NULL);
+                r = dns_packet_read_memdup(p, rdlength - 2,
+                                           &rr->sshfp.key, &rr->sshfp.key_size,
+                                           NULL);
                 break;
 
         case DNS_TYPE_DNSKEY: {
@@ -1539,9 +1554,9 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_read_public_key(p, rdlength - 4,
-                                               &rr->dnskey.key, &rr->dnskey.key_size,
-                                               NULL);
+                r = dns_packet_read_memdup(p, rdlength - 4,
+                                           &rr->dnskey.key, &rr->dnskey.key_size,
+                                           NULL);
                 break;
         }
 
@@ -1578,9 +1593,9 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_read_public_key(p, offset + rdlength - p->rindex,
-                                               &rr->rrsig.signature, &rr->rrsig.signature_size,
-                                               NULL);
+                r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
+                                           &rr->rrsig.signature, &rr->rrsig.signature_size,
+                                           NULL);
                 break;
 
         case DNS_TYPE_NSEC:
@@ -1615,34 +1630,18 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 if (r < 0)
                         goto fail;
 
-                rr->nsec3.salt_size = size;
-
-                r = dns_packet_read_blob(p, &d, rr->nsec3.salt_size, NULL);
+                r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
                 if (r < 0)
                         goto fail;
 
-                rr->nsec3.salt = memdup(d, rr->nsec3.salt_size);
-                if (!rr->nsec3.salt) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
-
                 r = dns_packet_read_uint8(p, &size, NULL);
                 if (r < 0)
                         goto fail;
 
-                rr->nsec3.next_hashed_name_size = size;
-
-                r = dns_packet_read(p, rr->nsec3.next_hashed_name_size, &d, NULL);
+                r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
                 if (r < 0)
                         goto fail;
 
-                rr->nsec3.next_hashed_name = memdup(d, rr->nsec3.next_hashed_name_size);
-                if (!rr->nsec3.next_hashed_name) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
-
                 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
                 if (r < 0)
                         goto fail;
@@ -1651,17 +1650,9 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
         }
         default:
         unparseable:
-                r = dns_packet_read(p, rdlength, &d, NULL);
+                r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
                 if (r < 0)
                         goto fail;
-
-                rr->generic.data = memdup(d, rdlength);
-                if (!rr->generic.data) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
-
-                rr->generic.size = rdlength;
                 break;
         }
         if (r < 0)
index 859b3f7..e489688 100644 (file)
@@ -776,7 +776,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
         case DNS_TYPE_NSEC3: {
                 _cleanup_free_ char *salt = NULL, *hash = NULL;
 
-                if (rr->nsec3.salt_size) {
+                if (rr->nsec3.salt_size > 0) {
                         salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
                         if (!salt)
                                 return -ENOMEM;
@@ -795,7 +795,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                              rr->nsec3.algorithm,
                              rr->nsec3.flags,
                              rr->nsec3.iterations,
-                             rr->nsec3.salt_size ? salt : "-",
+                             rr->nsec3.salt_size > 0 ? salt : "-",
                              hash,
                              t);
                 if (r < 0)
@@ -809,7 +809,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                 if (!t)
                         return -ENOMEM;
 
-                r = asprintf(&s, "%s \\# %"PRIu8" %s", k, rr->generic.size, t);
+                r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.size, t);
                 if (r < 0)
                         return -ENOMEM;
                 break;
index bdd5a5c..dc51126 100644 (file)
@@ -53,7 +53,7 @@ struct DnsResourceRecord {
         union {
                 struct {
                         void *data;
-                        uint16_t size;
+                        size_t size;
                 } generic;
 
                 struct {