resolved: discard more invalid llmnr messages
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user