summaryrefslogtreecommitdiff
path: root/src/resolve
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve')
-rw-r--r--src/resolve/dns-type.c5
-rw-r--r--src/resolve/dns-type.h1
-rw-r--r--src/resolve/resolved-dns-packet.c226
-rw-r--r--src/resolve/resolved-dns-rr.c18
-rw-r--r--src/resolve/resolved-dns-rr.h7
-rw-r--r--src/resolve/resolved-dns-scope.c13
-rw-r--r--src/resolve/resolved-dns-scope.h1
-rw-r--r--src/resolve/resolved-dns-transaction.c4
8 files changed, 168 insertions, 107 deletions
diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c
index a3e740896f..e1087b3219 100644
--- a/src/resolve/dns-type.c
+++ b/src/resolve/dns-type.c
@@ -43,3 +43,8 @@ int dns_type_from_string(const char *s) {
return sc->id;
}
+
+/* XXX: find an authorotative list of all pseudo types? */
+bool dns_type_is_pseudo(int n) {
+ return IN_SET(n, DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR, DNS_TYPE_OPT);
+}
diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h
index 86951d233a..950af36ee3 100644
--- a/src/resolve/dns-type.h
+++ b/src/resolve/dns-type.h
@@ -25,6 +25,7 @@
const char *dns_type_to_string(int type);
int dns_type_from_string(const char *s);
+bool dns_type_is_pseudo(int n);
/* DNS record types, taken from
* http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml.
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index b1cde4ab35..649e8b74e1 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -275,7 +275,7 @@ static void dns_packet_truncate(DnsPacket *p, size_t sz) {
if (p->size <= sz)
return;
- HASHMAP_FOREACH_KEY(s, n, p->names, i) {
+ HASHMAP_FOREACH_KEY(n, s, p->names, i) {
if (PTR_TO_SIZE(n) < sz)
continue;
@@ -509,22 +509,22 @@ static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t l
assert(p);
assert(types);
- if (length == 0)
- return 0;
-
saved_size = p->size;
- r = dns_packet_append_uint8(p, window, NULL);
- if (r < 0)
- goto fail;
+ if (length != 0) {
- r = dns_packet_append_uint8(p, length, NULL);
- if (r < 0)
- goto fail;
+ r = dns_packet_append_uint8(p, window, NULL);
+ if (r < 0)
+ goto fail;
- r = dns_packet_append_blob(p, types, length, NULL);
- if (r < 0)
- goto fail;
+ r = dns_packet_append_uint8(p, length, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_blob(p, types, length, NULL);
+ if (r < 0)
+ goto fail;
+ }
if (start)
*start = saved_size;
@@ -761,7 +761,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
if (r < 0)
goto fail;
- r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
+ r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
break;
case DNS_TYPE_DNSKEY:
@@ -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;
@@ -1172,9 +1208,12 @@ static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *sta
if (bitmap[i] & bitmask) {
uint16_t n;
- /* XXX: ignore pseudo-types? see RFC4034 section 4.1.2 */
n = (uint16_t) window << 8 | (uint16_t) bit;
+ /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
+ if (dns_type_is_pseudo(n))
+ continue;
+
r = bitmap_set(*types, n);
if (r < 0)
goto fail;
@@ -1197,6 +1236,38 @@ fail:
return r;
}
+static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
+ size_t saved_rindex;
+ int r;
+
+ saved_rindex = p->rindex;
+
+ while (p->rindex < saved_rindex + size) {
+ r = dns_packet_read_type_window(p, types, NULL);
+ if (r < 0)
+ goto fail;
+
+ /* don't read past end of current RR */
+ if (p->rindex > saved_rindex + size) {
+ r = -EBADMSG;
+ goto fail;
+ }
+ }
+
+ if (p->rindex != saved_rindex + size) {
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ if (start)
+ *start = saved_rindex;
+
+ return 0;
+fail:
+ dns_packet_rewind(p, saved_rindex);
+ return r;
+}
+
int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
_cleanup_free_ char *name = NULL;
uint16_t class, type;
@@ -1239,26 +1310,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 +1332,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,12 +1542,19 @@ 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;
+ if (rr->ds.digest_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
break;
case DNS_TYPE_SSHFP:
r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
@@ -1508,9 +1565,17 @@ 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.fingerprint, &rr->sshfp.fingerprint_size,
+ NULL);
+
+ if (rr->sshfp.fingerprint_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
break;
case DNS_TYPE_DNSKEY: {
@@ -1539,9 +1604,17 @@ 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);
+
+ if (rr->dnskey.key_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
break;
}
@@ -1578,9 +1651,17 @@ 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);
+
+ if (rr->rrsig.signature_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
break;
case DNS_TYPE_NSEC:
@@ -1588,11 +1669,12 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
if (r < 0)
goto fail;
- while (p->rindex != offset + rdlength) {
- r = dns_packet_read_type_window(p, &rr->nsec.types, NULL);
- if (r < 0)
- goto fail;
- }
+ r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
+ if (r < 0)
+ goto fail;
+
+ /* NSEC RRs with empty bitmpas makes no sense, but the RFC does not explicitly forbid them
+ so we allow it */
break;
@@ -1611,57 +1693,41 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
if (r < 0)
goto fail;
+ /* this may be zero */
r = dns_packet_read_uint8(p, &size, NULL);
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);
- if (r < 0)
+ if (size <= 0) {
+ r = -EBADMSG;
goto fail;
+ }
- rr->nsec3.next_hashed_name = memdup(d, rr->nsec3.next_hashed_name_size);
- if (!rr->nsec3.next_hashed_name) {
- r = -ENOMEM;
+ r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
+ if (r < 0)
goto fail;
- }
- r = dns_packet_append_types(p, rr->nsec3.types, NULL);
+ r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
if (r < 0)
goto fail;
+ /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
+
break;
}
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..2bc9f2b520 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -276,7 +276,7 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
break;
case DNS_TYPE_SSHFP:
- free(rr->sshfp.key);
+ free(rr->sshfp.fingerprint);
break;
case DNS_TYPE_DNSKEY:
@@ -434,8 +434,8 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
case DNS_TYPE_SSHFP:
return a->sshfp.algorithm == b->sshfp.algorithm &&
a->sshfp.fptype == b->sshfp.fptype &&
- a->sshfp.key_size == b->sshfp.key_size &&
- memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0;
+ a->sshfp.fingerprint_size == b->sshfp.fingerprint_size &&
+ memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0;
case DNS_TYPE_DNSKEY:
return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
@@ -533,7 +533,7 @@ static char *format_types(Bitmap *types) {
BITMAP_FOREACH(type, types, i) {
if (dns_type_to_string(type)) {
- r = strv_extend(&strv, strdup(dns_type_to_string(type)));
+ r = strv_extend(&strv, dns_type_to_string(type));
if (r < 0)
return NULL;
} else {
@@ -543,7 +543,7 @@ static char *format_types(Bitmap *types) {
if (r < 0)
return NULL;
- r = strv_extend(&strv, t);
+ r = strv_consume(&strv, t);
if (r < 0)
return NULL;
}
@@ -687,7 +687,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
break;
case DNS_TYPE_SSHFP:
- t = hexmem(rr->sshfp.key, rr->sshfp.key_size);
+ t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
if (!t)
return -ENOMEM;
@@ -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..0f40f3ceef 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 {
@@ -117,11 +117,12 @@ struct DnsResourceRecord {
size_t digest_size;
} ds;
+ /* https://tools.ietf.org/html/rfc4255#section-3.1 */
struct {
uint8_t algorithm;
uint8_t fptype;
- void *key;
- size_t key_size;
+ void *fingerprint;
+ size_t fingerprint_size;
} sshfp;
/* http://tools.ietf.org/html/rfc4034#section-2.1 */
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 7b72c090c2..0aab1e35d3 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -420,19 +420,6 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) {
return 0;
}
-int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address) {
- assert(s);
- assert(address);
-
- if (s->protocol != DNS_PROTOCOL_DNS)
- return 1;
-
- if (s->link)
- return !!link_find_dns_server(s->link, family, address);
- else
- return !!manager_find_dns_server(s->manager, family, address);
-}
-
static int dns_scope_make_reply_packet(
DnsScope *s,
uint16_t id,
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index 5c5ccc71c5..21a160ea39 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -70,7 +70,6 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add
DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain);
int dns_scope_good_key(DnsScope *s, DnsResourceKey *key);
-int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address);
DnsServer *dns_scope_get_dns_server(DnsScope *s);
void dns_scope_next_dns_server(DnsScope *s);
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index e468f245f7..3d46c99df8 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -417,8 +417,10 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
/* Only consider responses with equivalent query section to the request */
if (!dns_question_is_superset(p->question, t->question) ||
- !dns_question_is_superset(t->question, p->question))
+ !dns_question_is_superset(t->question, p->question)) {
dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
+ return;
+ }
/* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender);