From e44165c0f77929a4dd56694e1323337d68b624d1 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 6 Feb 2025 10:32:29 +0000 Subject: [PATCH] Fix bug in 0x20 encoding. We must only compare case when mapping an answer from upstream to a forwarding record, not when checking a query to see if it's a duplicate. Since the saved query name is scrambled, that ensures that almost all such checks will wrongly fail. Thanks to Peter Tirsek for an exemplary bug report for this. --- src/dnsmasq.h | 1 + src/forward.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/dnsmasq.h b/src/dnsmasq.h index d563bf7..9996599 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -775,6 +775,7 @@ struct dyndir { #define FREC_DO_QUESTION 64 #define FREC_HAS_PHEADER 128 #define FREC_GONE_TO_TCP 256 +#define FREC_ANSWER 512 struct frec { struct frec_src { diff --git a/src/forward.c b/src/forward.c index 08f229b..87035ed 100644 --- a/src/forward.c +++ b/src/forward.c @@ -1098,7 +1098,7 @@ void reply_query(int fd, time_t now) GETSHORT(rrtype, p); GETSHORT(class, p); - if (!(forward = lookup_frec(daemon->namebuff, class, rrtype, ntohs(header->id), 0, 0))) + if (!(forward = lookup_frec(daemon->namebuff, class, rrtype, ntohs(header->id), FREC_ANSWER, 0))) return; filter_servers(forward->sentto->arrayposn, F_SERVER, &first, &last); @@ -3057,6 +3057,16 @@ static struct frec *lookup_frec(char *target, int class, int rrtype, int id, int { struct frec *f; struct dns_header *header; + int compare_mode = EXTR_NAME_COMPARE; + + /* Only compare case-sensitive when matching frec to a an recieved anwer, + not when looking for a duplicated question. */ + if (flags & FREC_ANSWER) + { + flags &= ~FREC_ANSWER; + if (!option_bool(OPT_NO_0x20)) + compare_mode = EXTR_NAME_NOCASE; + } for (f = daemon->frec_list; f; f = f->next) if (f->sentto && @@ -3068,7 +3078,7 @@ static struct frec *lookup_frec(char *target, int class, int rrtype, int id, int int hclass, hrrtype, rc; /* Case sensitive compare for DNS-0x20 encoding. */ - if ((rc = extract_name(header, f->stash_len, &p, target, option_bool(OPT_NO_0x20) ? EXTR_NAME_COMPARE : EXTR_NAME_NOCASE, 4))) + if ((rc = extract_name(header, f->stash_len, &p, target, compare_mode, 4))) { GETSHORT(hrrtype, p); GETSHORT(hclass, p);