From ea917db9e662ae6e6d0ae07e0118b323688c8616 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Jul 2014 19:50:28 +0200 Subject: resolved: discard more invalid llmnr messages --- src/resolve/resolved-dns-packet.c | 30 +++++++++++++++++++++++++++--- src/resolve/resolved-dns-packet.h | 2 ++ src/resolve/resolved-dns-query.c | 9 +++++++++ src/resolve/resolved-dns-scope.c | 16 +++++++++++++++- 4 files changed, 53 insertions(+), 4 deletions(-) (limited to 'src/resolve') diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 1ff56875e6..5eaee2cb4f 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -72,10 +72,26 @@ int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) { h = DNS_PACKET_HEADER(p); - if (protocol == DNS_PROTOCOL_DNS) - h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 1, 0, 0, 0, 0)); /* ask for recursion */ + if (protocol == DNS_PROTOCOL_LLMNR) + h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */, + 0 /* opcode */, + 0 /* c */, + 0 /* tc */, + 0 /* t */, + 0 /* ra */, + 0 /* ad */, + 0 /* cd */, + 0 /* rcode */)); else - h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0)); + h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */, + 0 /* opcode */, + 0 /* aa */, + 0 /* tc */, + 1 /* rd (ask for recursion) */, + 0 /* ra */, + 0 /* ad */, + 0 /* cd */, + 0 /* rcode */)); *ret = p; return 0; @@ -148,6 +164,11 @@ int dns_packet_validate_reply(DnsPacket *p) { if (DNS_PACKET_OPCODE(p) != 0) return -EBADMSG; + /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */ + if (p->protocol == DNS_PROTOCOL_LLMNR && + DNS_PACKET_QDCOUNT(p) != 1) + return -EBADMSG; + return 1; } @@ -169,13 +190,16 @@ int dns_packet_validate_query(DnsPacket *p) { if (DNS_PACKET_TC(p)) return -EBADMSG; + /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */ if (p->protocol == DNS_PROTOCOL_LLMNR && DNS_PACKET_QDCOUNT(p) != 1) return -EBADMSG; + /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */ if (DNS_PACKET_ANCOUNT(p) > 0) return -EBADMSG; + /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */ if (DNS_PACKET_NSCOUNT(p) > 0) return -EBADMSG; diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index ad4a38e6e4..af51f16c3c 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -99,6 +99,8 @@ static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) { #define DNS_PACKET_OPCODE(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 11) & 15) #define DNS_PACKET_RCODE(p) (be16toh(DNS_PACKET_HEADER(p)->flags) & 15) #define DNS_PACKET_TC(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 9) & 1) +#define DNS_PACKET_C(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1) +#define DNS_PACKET_T(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1) #define DNS_PACKET_QDCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->qdcount) #define DNS_PACKET_ANCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->ancount) #define DNS_PACKET_NSCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->nscount) diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 42f4f23cb9..ecffe06959 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -261,6 +261,9 @@ void dns_query_transaction_process_reply(DnsQueryTransaction *t, DnsPacket *p) { if (p->family != t->scope->family) return; + /* Don't accept UDP packets directed to anything but + * the LLMNR multicast addresses. */ + if (p->ipproto == IPPROTO_UDP) { if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS)) return; @@ -268,6 +271,12 @@ void dns_query_transaction_process_reply(DnsQueryTransaction *t, DnsPacket *p) { if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS)) return; } + + /* Tentative replies shall be discarded, see RFC 4795, + * 2.1.1 */ + + if (DNS_PACKET_T(p)) + return; } if (t->scope->protocol == DNS_PROTOCOL_DNS) { diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 5d2edbae47..b226f5a457 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -404,7 +404,16 @@ static int dns_scope_make_reply_packet(DnsScope *s, uint16_t id, int rcode, DnsQ return r; DNS_PACKET_HEADER(p)->id = id; - DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(1, 0, 0, 0, 0, 0, 0, 0, rcode)); + DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS( + 1 /* qr */, + 0 /* opcode */, + 0 /* c */, + 0 /* tc */, + 0 /* t */, + 0 /* (ra) */, + 0 /* (ad) */, + 0 /* (cd) */, + rcode)); if (q) { for (i = 0; i < q->n_keys; i++) { @@ -449,6 +458,11 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) { return; } + if (DNS_PACKET_C(p)) { + /* FIXME: Somebody notified us about a likely conflict */ + return; + } + r = dns_zone_lookup(&s->zone, p->question, &answer); if (r < 0) { log_debug("Failed to lookup key: %s", strerror(-r)); -- cgit v1.2.3-54-g00ecf