mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-20 02:38:32 +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;
|
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
|
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 */
|
Try another server, or give up */
|
||||||
p = (unsigned char *)(header+1);
|
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;
|
continue;
|
||||||
GETSHORT(rtype, p);
|
GETSHORT(rtype, p);
|
||||||
GETSHORT(rclass, p);
|
GETSHORT(rclass, p);
|
||||||
@@ -3046,7 +3048,8 @@ static struct frec *lookup_frec(char *target, int class, int rrtype, int id, int
|
|||||||
unsigned char *p = (unsigned char *)(header+1);
|
unsigned char *p = (unsigned char *)(header+1);
|
||||||
int hclass, hrrtype;
|
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;
|
continue;
|
||||||
|
|
||||||
GETSHORT(hrrtype, p);
|
GETSHORT(hrrtype, p);
|
||||||
|
|||||||
@@ -16,14 +16,24 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#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,
|
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||||
char *name, int isExtract, int extrabytes)
|
char *name, int isExtract, int extrabytes)
|
||||||
{
|
{
|
||||||
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
||||||
unsigned int j, l, namelen = 0, hops = 0;
|
unsigned int j, l, namelen = 0, hops = 0;
|
||||||
int retvalue = 1;
|
int retvalue = 1, case_insens = 1;
|
||||||
|
|
||||||
if (isExtract)
|
if (isExtract == -1)
|
||||||
|
isExtract = case_insens = 0;
|
||||||
|
else if (isExtract)
|
||||||
*cp = 0;
|
*cp = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@@ -107,13 +117,13 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
cp++;
|
cp++;
|
||||||
if (c1 >= 'A' && c1 <= 'Z')
|
if (case_insens && c1 >= 'A' && c1 <= 'Z')
|
||||||
c1 += 'a' - 'A';
|
c1 += 'a' - 'A';
|
||||||
|
|
||||||
if (c1 == NAME_ESCAPE)
|
if (c1 == NAME_ESCAPE)
|
||||||
c1 = (*cp++)-1;
|
c1 = (*cp++)-1;
|
||||||
|
|
||||||
if (c2 >= 'A' && c2 <= 'Z')
|
if (case_insens && c2 >= 'A' && c2 <= 'Z')
|
||||||
c2 += 'a' - 'A';
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
if (c1 != c2)
|
if (c1 != c2)
|
||||||
|
|||||||
Reference in New Issue
Block a user