mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Case-sensitive matching of questions and answers.
When checking that an answer is the answer to the question that
we asked, compare the name in a case-sensitive manner.
Clients can set the letters in a query to a random pattern of
uppercase and lowercase to add more randomness as protection against
cache-poisoning attacks, and we don't want to nullify that.
This actually restores the status quo before
commit ed6d29a784
since matching questions and answers using a checksum
can't help but be case sensitive.
This patch is a preparation for introducing DNS-0x20
in the dnsmasq query path.
This commit is contained in:
@@ -1999,12 +1999,14 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the question section of the reply doesn't match the crc we sent, then
|
||||
/* If the question section of the reply doesn't match the question we sent, then
|
||||
someone might be attempting to insert bogus values into the cache by
|
||||
sending replies containing questions and bogus answers.
|
||||
sending replies containing questions and bogus answers.
|
||||
We compare the query name in a case sensitive manner, so that
|
||||
DNS-0x20 encoding is effective.
|
||||
Try another server, or give up */
|
||||
p = (unsigned char *)(header+1);
|
||||
if (extract_name(header, rsize, &p, daemon->namebuff, 0, 4) != 1)
|
||||
if (extract_name(header, rsize, &p, daemon->namebuff, -1, 4) != 1)
|
||||
continue;
|
||||
GETSHORT(rtype, p);
|
||||
GETSHORT(rclass, p);
|
||||
@@ -3045,8 +3047,9 @@ static struct frec *lookup_frec(char *target, int class, int rrtype, int id, int
|
||||
{
|
||||
unsigned char *p = (unsigned char *)(header+1);
|
||||
int hclass, hrrtype;
|
||||
|
||||
if (extract_name(header, f->stash_len, &p, target, 0, 4) != 1)
|
||||
|
||||
/* Case sensitive compare for DNS-0x20 encoding. */
|
||||
if (extract_name(header, f->stash_len, &p, target, -1, 4) != 1)
|
||||
continue;
|
||||
|
||||
GETSHORT(hrrtype, p);
|
||||
|
||||
@@ -16,14 +16,24 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
/* isExtract == 1 -> extract name
|
||||
isExtract == 0 -> compare name, case insensitive
|
||||
isExtract == -1 -> compare name, case sensitive
|
||||
|
||||
return = 0 -> error
|
||||
return = 1 -> extract OK, compare OK
|
||||
return = 2 -> extract OK, compare failed.
|
||||
*/
|
||||
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
char *name, int isExtract, int extrabytes)
|
||||
{
|
||||
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
||||
unsigned int j, l, namelen = 0, hops = 0;
|
||||
int retvalue = 1;
|
||||
|
||||
if (isExtract)
|
||||
int retvalue = 1, case_insens = 1;
|
||||
|
||||
if (isExtract == -1)
|
||||
isExtract = case_insens = 0;
|
||||
else if (isExtract)
|
||||
*cp = 0;
|
||||
|
||||
while (1)
|
||||
@@ -107,13 +117,13 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
else
|
||||
{
|
||||
cp++;
|
||||
if (c1 >= 'A' && c1 <= 'Z')
|
||||
if (case_insens && c1 >= 'A' && c1 <= 'Z')
|
||||
c1 += 'a' - 'A';
|
||||
|
||||
if (c1 == NAME_ESCAPE)
|
||||
c1 = (*cp++)-1;
|
||||
|
||||
if (c2 >= 'A' && c2 <= 'Z')
|
||||
if (case_insens && c2 >= 'A' && c2 <= 'Z')
|
||||
c2 += 'a' - 'A';
|
||||
|
||||
if (c1 != c2)
|
||||
|
||||
Reference in New Issue
Block a user