diff options
Diffstat (limited to 'src/resolve')
-rw-r--r-- | src/resolve/dns-type.c | 2 | ||||
-rw-r--r-- | src/resolve/resolved-dns-packet.c | 51 | ||||
-rw-r--r-- | src/resolve/resolved-dns-question.c | 40 | ||||
-rw-r--r-- | src/resolve/resolved-dns-question.h | 2 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 5 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 4 |
6 files changed, 74 insertions, 30 deletions
diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c index e1087b3219..63b4b36e88 100644 --- a/src/resolve/dns-type.c +++ b/src/resolve/dns-type.c @@ -44,7 +44,7 @@ int dns_type_from_string(const char *s) { return sc->id; } -/* XXX: find an authorotative list of all pseudo types? */ +/* XXX: find an authoritative 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/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 649e8b74e1..39951a362c 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -508,23 +508,21 @@ static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t l assert(p); assert(types); + assert(length > 0); saved_size = p->size; - if (length != 0) { - - r = dns_packet_append_uint8(p, window, NULL); - if (r < 0) - goto fail; + r = dns_packet_append_uint8(p, window, NULL); + if (r < 0) + goto fail; - r = dns_packet_append_uint8(p, 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; - } + r = dns_packet_append_blob(p, types, length, NULL); + if (r < 0) + goto fail; if (start) *start = saved_size; @@ -538,7 +536,7 @@ fail: static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) { Iterator i; uint8_t window = 0; - uint8_t len = 0; + uint8_t entry = 0; uint8_t bitmaps[32] = {}; unsigned n; size_t saved_size; @@ -550,30 +548,24 @@ static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) { saved_size = p->size; BITMAP_FOREACH(n, types, i) { - uint8_t entry; - assert(n <= 0xffff); - if ((n << 8) != window) { - r = dns_packet_append_type_window(p, window, len, bitmaps, NULL); + if ((n >> 8) != window && bitmaps[entry / 8] != 0) { + r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL); if (r < 0) goto fail; - if (len > 0) { - len = 0; - zero(bitmaps); - } + zero(bitmaps); } - window = n << 8; - len ++; + window = n >> 8; entry = n & 255; bitmaps[entry / 8] |= 1 << (7 - (entry % 8)); } - r = dns_packet_append_type_window(p, window, len, bitmaps, NULL); + r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL); if (r < 0) goto fail; @@ -1164,6 +1156,7 @@ static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *sta uint8_t window; uint8_t length; const uint8_t *bitmap; + uint8_t bit = 0; unsigned i; bool found = false; size_t saved_rindex; @@ -1195,10 +1188,10 @@ static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *sta for (i = 0; i < length; i++) { uint8_t bitmask = 1 << 7; - uint8_t bit = 0; if (!bitmap[i]) { found = false; + bit += 8; continue; } @@ -1673,8 +1666,12 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { 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 */ + /* The types bitmap must contain at least the NSEC record itself, so an empty bitmap means + something went wrong */ + if (bitmap_isclear(rr->nsec.types)) { + r = -EBADMSG; + goto fail; + } break; diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c index 4d71f5e3d4..0efe740d1a 100644 --- a/src/resolve/resolved-dns-question.c +++ b/src/resolve/resolved-dns-question.c @@ -188,6 +188,46 @@ int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other) { return 1; } +int dns_question_contains(DnsQuestion *a, DnsResourceKey *k) { + unsigned j; + int r; + + assert(a); + assert(k); + + for (j = 0; j < a->n_keys; j++) { + r = dns_resource_key_equal(a->keys[j], k); + if (r != 0) + return r; + } + + return 0; +} + +int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) { + unsigned j; + int r; + + assert(a); + assert(b); + + /* Checks if all keys in a are also contained b, and vice versa */ + + for (j = 0; j < a->n_keys; j++) { + r = dns_question_contains(b, a->keys[j]); + if (r <= 0) + return r; + } + + for (j = 0; j < b->n_keys; j++) { + r = dns_question_contains(a, b->keys[j]); + if (r <= 0) + return r; + } + + return 1; +} + int dns_question_cname_redirect(DnsQuestion *q, const char *name, DnsQuestion **ret) { _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL; bool same = true; diff --git a/src/resolve/resolved-dns-question.h b/src/resolve/resolved-dns-question.h index 4ba2fe9f0e..fc98677798 100644 --- a/src/resolve/resolved-dns-question.h +++ b/src/resolve/resolved-dns-question.h @@ -43,6 +43,8 @@ int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr); int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr); int dns_question_is_valid(DnsQuestion *q); int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other); +int dns_question_contains(DnsQuestion *a, DnsResourceKey *k); +int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b); int dns_question_cname_redirect(DnsQuestion *q, const char *name, DnsQuestion **ret); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 927a1ddc26..4bc4157028 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -313,6 +313,11 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co if (is_localhost(domain)) return DNS_SCOPE_NO; + /* Never resolve any loopback IP address via DNS, LLMNR or mDNS */ + if (dns_name_endswith(domain, "127.in-addr.arpa") > 0 || + dns_name_equal(domain, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) + return DNS_SCOPE_NO; + if (s->protocol == DNS_PROTOCOL_DNS) { if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 && dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0 && diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index b235fda3d2..8a93b265c6 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -406,8 +406,8 @@ 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)) { + r = dns_question_is_equal(p->question, t->question); + if (r <= 0) { dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return; } |