summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-07-23 04:04:19 +0200
committerLennart Poettering <lennart@poettering.net>2015-07-23 04:50:19 +0200
commitf5430a3ef308f3a102899fcaf7fbece757082f2a (patch)
treeca31992b7c4fff12ebcf2ec4f254a2b964b0ccd6
parent6aafa9483d167f55a50e01f4dc5984866f12c8ec (diff)
resolve: unify memdup() code when parsing RRs
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!
-rw-r--r--src/resolve/resolved-dns-packet.c111
-rw-r--r--src/resolve/resolved-dns-rr.c6
-rw-r--r--src/resolve/resolved-dns-rr.h2
3 files changed, 55 insertions, 64 deletions
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index b1cde4ab35..563b9563e9 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -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)
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index 859b3f7339..e489688b85 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -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;
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index bdd5a5c824..dc51126f97 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -53,7 +53,7 @@ struct DnsResourceRecord {
union {
struct {
void *data;
- uint16_t size;
+ size_t size;
} generic;
struct {