dnsmasq with DNSSEC compiled in and enabled is vulnerable to this,
referenced by CERT VU#434904.
+ Be sure to only accept UDP DNS query replies at the address
+ from which the query was originated. This keeps as much entropy
+ in the {query-ID, random-port} tuple as possible, help defeat
+ cache poisoning attacks. Refer: CERT VU#434904.
+
version 2.79
Fix parsing of CNAME arguments, which are confused by extra spaces.
Thanks to Diego Aguirre for spotting the bug.
#include "dnsmasq.h"
-static struct frec *lookup_frec(unsigned short id, void *hash);
+static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash);
static struct frec *lookup_frec_by_sender(unsigned short id,
union mysockaddr *addr,
void *hash);
hash = &crc;
crc = questions_crc(header, n, daemon->namebuff);
#endif
-
- if (!(forward = lookup_frec(ntohs(header->id), hash)))
+ if (!(forward = lookup_frec(ntohs(header->id), fd, family, hash)))
return;
/* log_query gets called indirectly all over the place, so
}
/* crc is all-ones if not known. */
-static struct frec *lookup_frec(unsigned short id, void *hash)
+static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash)
{
struct frec *f;
for(f = daemon->frec_list; f; f = f->next)
if (f->sentto && f->new_id == id &&
- (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
- return f;
-
+ (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
+ {
+ /* sent from random port */
+ if (family == AF_INET && f->rfd4 && f->rfd4->fd == fd)
+ return f;
+
+ if (family == AF_INET6 && f->rfd6 && f->rfd6->fd == fd)
+ return f;
+
+ /* sent to upstream from bound socket. */
+ if (f->sentto->sfd && f->sentto->sfd->fd == fd)
+ return f;
+ }
+
return NULL;
}
static unsigned short get_id(void)
{
unsigned short ret = 0;
-
- do
- ret = rand16();
- while (lookup_frec(ret, NULL));
-
- return ret;
-}
-
+ struct frec *f;
+ while (1)
+ {
+ ret = rand16();
+ /* ensure id is unique. */
+ for (f = daemon->frec_list; f; f = f->next)
+ if (f->sentto && f->new_id == ret)
+ break;
+ if (!f)
+ return ret;
+ }
+}